|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
namespace MySociety\TheyWorkForYou\Db; |
|
4
|
|
|
|
|
5
|
|
|
// We'll add up the times of each query so we can output the page total at the end. |
|
6
|
|
|
|
|
7
|
|
|
global $mysqltotalduration; |
|
|
|
|
|
|
8
|
|
|
$mysqltotalduration = 0.0; |
|
9
|
|
|
$global_connection = null; |
|
10
|
|
|
|
|
11
|
|
|
/** |
|
12
|
|
|
* Database Connection |
|
13
|
|
|
* |
|
14
|
|
|
* Somewhere (probably in `includes/easyparliament/init.php`) there should be |
|
15
|
|
|
* something like: |
|
16
|
|
|
* |
|
17
|
|
|
* ```php |
|
18
|
|
|
* Class ParlDB extends \MySociety\TheyWorkForYou\Db\Connection { |
|
19
|
|
|
* function ParlDB() { |
|
20
|
|
|
* $this->init (OPTION_TWFY_DB_HOST, OPTION_TWFY_DB_USER, OPTION_TWFY_DB_PASS, OPTION_TWFY_DB_NAME); |
|
21
|
|
|
* } |
|
22
|
|
|
* } |
|
23
|
|
|
* ``` |
|
24
|
|
|
* |
|
25
|
|
|
* Then, when you need to do queries, you do: |
|
26
|
|
|
* |
|
27
|
|
|
* ```php |
|
28
|
|
|
* $db = new ParlDB; |
|
29
|
|
|
* $q = $db->query("SELECT haddock FROM fish"); |
|
30
|
|
|
* ``` |
|
31
|
|
|
* |
|
32
|
|
|
* `$q` is then an instance of `Db\Query`. |
|
33
|
|
|
* |
|
34
|
|
|
* If other databases are needed, we just need to create a class for each, each |
|
35
|
|
|
* one extending `Db\Connection`. |
|
36
|
|
|
* |
|
37
|
|
|
* Call `$db->display_total_duration()` at the end of a page to send total |
|
38
|
|
|
* query time to `debug()`. |
|
39
|
|
|
* |
|
40
|
|
|
* Depends on having the `debug()` and `getmicrotime()` functions available |
|
41
|
|
|
* elsewhere to output debugging info. |
|
42
|
|
|
* |
|
43
|
|
|
*/ |
|
44
|
|
|
|
|
45
|
|
|
class Connection { |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* Initialise Connection |
|
49
|
|
|
* |
|
50
|
|
|
* If an existing MySQL connection exists, use that. Otherwise, create a |
|
51
|
|
|
* new connection. |
|
52
|
|
|
* |
|
53
|
|
|
* @param string $db_host The hostname of the database server |
|
54
|
|
|
* @param string $db_user The user to connect to the database as |
|
55
|
|
|
* @param string $db_pass The password for the database user |
|
56
|
|
|
* @param string $db_name The name of the database |
|
57
|
|
|
* |
|
58
|
|
|
* @return boolean If the connection has been created successfully. |
|
59
|
|
|
*/ |
|
60
|
|
|
|
|
61
|
82 |
|
public function init($db_host, $db_user, $db_pass, $db_name) { |
|
62
|
82 |
|
global $global_connection; |
|
|
|
|
|
|
63
|
|
|
// These vars come from config.php. |
|
64
|
|
|
|
|
65
|
82 |
|
if (!$global_connection) { |
|
66
|
|
|
$dsn = 'mysql:charset=utf8;dbname=' . $db_name . ';host=' . $db_host; |
|
67
|
|
|
|
|
68
|
|
|
try { |
|
69
|
|
|
$conn = new \PDO($dsn, $db_user, $db_pass); |
|
70
|
|
|
} catch (\PDOException $e) { |
|
71
|
|
|
$this->fatal_error('We were unable to connect to the TheyWorkForYou database for some reason. Please try again in a few minutes.'); |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
$global_connection = $conn; |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
82 |
|
$this->conn = $global_connection; |
|
78
|
|
|
|
|
79
|
82 |
|
return true; |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* Quote String |
|
84
|
|
|
* |
|
85
|
|
|
* @param string $string The string to quote. |
|
86
|
|
|
* |
|
87
|
|
|
* @return string The quoted string. |
|
88
|
|
|
*/ |
|
89
|
|
|
|
|
90
|
|
|
public function quote($string) { |
|
91
|
|
|
return $this->conn->quote($string); |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* Execute Query |
|
96
|
|
|
* |
|
97
|
|
|
* Takes a query, executes it and turns it into a query object. |
|
98
|
|
|
* |
|
99
|
|
|
* @param string $sql The SQL query to execute |
|
100
|
|
|
* @param array|null $params Parameters to inject into the query |
|
101
|
|
|
* |
|
102
|
|
|
* @return Query An object containing the results of the query. |
|
103
|
|
|
*/ |
|
104
|
|
|
|
|
105
|
76 |
|
public function query($sql, $params = null) { |
|
106
|
|
|
|
|
107
|
76 |
|
$start = getmicrotime(); |
|
108
|
76 |
|
$q = new \MySociety\TheyWorkForYou\Db\Query($this->conn); |
|
109
|
76 |
|
$q->query($sql, $params); |
|
110
|
|
|
|
|
111
|
76 |
|
$duration = getmicrotime() - $start; |
|
112
|
76 |
|
global $mysqltotalduration; |
|
|
|
|
|
|
113
|
76 |
|
$mysqltotalduration += $duration; |
|
114
|
76 |
|
twfy_debug("SQL", "Complete after $duration seconds."); |
|
115
|
|
|
// We could also output $q->mysql_info() here, but that's for |
|
116
|
|
|
// PHP >= 4.3.0. |
|
117
|
76 |
|
return $q; |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
/** |
|
121
|
|
|
* Display Total Duration |
|
122
|
|
|
* |
|
123
|
|
|
* Displays the total time taken to execute all queries made via this |
|
124
|
|
|
* connection. |
|
125
|
|
|
*/ |
|
126
|
|
|
|
|
127
|
|
|
public function display_total_duration() { |
|
128
|
|
|
global $mysqltotalduration; |
|
|
|
|
|
|
129
|
|
|
twfy_debug("TIME", "Total time for MySQL queries on this page: " . $mysqltotalduration . " seconds."); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
/** |
|
133
|
|
|
* Fatal Error |
|
134
|
|
|
* |
|
135
|
|
|
* Display a fatal error and exit the script. |
|
136
|
|
|
* |
|
137
|
|
|
* @param string $error The error message to display. |
|
138
|
|
|
*/ |
|
139
|
|
|
|
|
140
|
|
|
public function fatal_error($error) { |
|
141
|
|
|
echo ' |
|
142
|
|
|
<html><head><title>TheyWorkForYou - Database Error</title></head> |
|
143
|
|
|
<body> |
|
144
|
|
|
<h1><a href="/"><img border="0" src="/images/theyworkforyoucom.gif" width="293" height="28" alt="TheyWorkForYou"></a></h1> |
|
145
|
|
|
<h2>Database error</h2> |
|
146
|
|
|
'; |
|
147
|
|
|
echo "<p>$error</p>"; |
|
148
|
|
|
echo '</body></html>'; |
|
149
|
|
|
exit; |
|
|
|
|
|
|
150
|
|
|
} |
|
151
|
|
|
|
|
152
|
|
|
} |
|
153
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.