These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | |||
4 | interface ModelInterface { |
||
5 | /** |
||
6 | * Get all models from database. |
||
7 | * |
||
8 | * @return array |
||
9 | */ |
||
10 | function static getAll(); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
11 | |||
12 | /** |
||
13 | * Find model with the specified id. |
||
14 | */ |
||
15 | function static find($id); |
||
16 | |||
17 | /** |
||
18 | * Delete model with the specified id. |
||
19 | * |
||
20 | */ |
||
21 | function static destroy($id); |
||
22 | } |
||
23 | |||
24 | abstract Model { |
||
25 | |||
26 | /** |
||
27 | * The connection name for the model. |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | protected $connection; |
||
32 | |||
33 | |||
34 | } |
||
35 | |||
36 | class DatabaseConnectionFactory { |
||
37 | |||
38 | |||
39 | |||
40 | |||
41 | } |
||
42 | |||
43 | |||
44 | class Connection { |
||
45 | |||
46 | /** |
||
47 | * The current globally used instance. |
||
48 | * |
||
49 | * @var object |
||
50 | */ |
||
51 | protected static $instance; |
||
52 | |||
53 | private $host; |
||
54 | private $user; |
||
55 | private $pass; |
||
56 | private $dbname; |
||
57 | |||
58 | private $dbh; |
||
59 | private $error; |
||
60 | |||
61 | public function __construct(){ |
||
62 | $config = parse_ini_file('config.ini'); |
||
63 | // Set DSN |
||
64 | $dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname; |
||
65 | // Set options |
||
66 | $options = array( |
||
67 | PDO::ATTR_PERSISTENT => true, |
||
68 | PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION |
||
69 | ); |
||
70 | // Create a new PDO instanace |
||
71 | try{ |
||
72 | $this->dbh = new PDO($dsn, $this->user, $this->pass, $options); |
||
73 | } |
||
74 | // Catch any errors |
||
75 | catch(PDOException $e){ |
||
76 | $this->error = $e->getMessage(); |
||
77 | } |
||
78 | } |
||
79 | } |
||
80 | |||
81 | |||
82 | try { |
||
83 | |||
84 | $dbh = new PDO('mysql:host=localhost;dbname=potatoORM', 'homestead', 'secret'); |
||
85 | foreach($dbh->query('SELECT * from test') as $row) { |
||
86 | print_r($row); |
||
87 | } |
||
88 | } catch (PDOException $e) { |
||
89 | print "Error!: " . $e->getMessage() . "<br/>"; |
||
90 | die(); |
||
91 | } |
||
92 | |||
93 | $stmt = $dbh->prepare("INSERT INTO test (id, body) VALUES (?, ?)"); |
||
94 | $stmt->bindParam(1, $id); |
||
95 | $stmt->bindParam(2, $body); |
||
96 | |||
97 | // insert one row |
||
98 | $id = 3; |
||
99 | $body = 'Some other test msg'; |
||
100 | $stmt->execute(); |
||
101 | |||
102 | // insert another row with different values |
||
103 | $id = 4; |
||
104 | $body = 'Some other test msg 2'; |
||
105 | $stmt->execute(); |
||
106 | $dbh = null; |
||
107 | |||
108 | class Model { |
||
109 | |||
110 | |||
111 | |||
112 | function __construct() |
||
0 ignored issues
–
show
|
|||
113 | { |
||
114 | /** |
||
115 | * Load the environment variables |
||
116 | * @return connection object |
||
117 | */ |
||
118 | $this->loadDotenv(); |
||
119 | |||
120 | $this->database = getenv('DB_DATABASE'); |
||
121 | $this->host = getenv('DB_host'); |
||
122 | $this->username = getenv('DB_USERNAME'); |
||
123 | $this->password = getenv('DB_PASSWORD'); |
||
124 | $this->driver = getenv('DB_CONNECTION'); |
||
125 | |||
126 | } |
||
127 | /** |
||
128 | * use vlucas dotenv to access the .env file |
||
129 | **/ |
||
130 | protected function loadDotenv() |
||
131 | { |
||
132 | if(getenv('APP_ENV') !== 'production') |
||
133 | { |
||
134 | $dotenv = new Dotenv(__DIR__); |
||
135 | $dotenv->load(); |
||
136 | } |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Handle dynamic static method calls into the method. |
||
141 | * |
||
142 | * @param string $method |
||
143 | * @param array $parameters |
||
144 | * @return mixed |
||
145 | */ |
||
146 | public static function __callStatic($method, $parameters) |
||
147 | { |
||
148 | $instance = new static; |
||
149 | |||
150 | return call_user_func_array([$instance, $method], $parameters); |
||
151 | } |
||
152 | |||
153 | } |
||
154 | |||
155 | |||
156 | class MySqlConnector extends DatabaseAdapter implements DatabaseAdapterInterface |
||
157 | { |
||
158 | /** |
||
159 | * Establish a database connection. |
||
160 | * |
||
161 | * @param array $config |
||
162 | * @return \PDO |
||
163 | */ |
||
164 | public function connect(array $config) |
||
165 | { |
||
166 | $dsn = $this->getDsn($config); |
||
167 | |||
168 | $options = $this->getOptions($config); |
||
169 | |||
170 | // We need to grab the PDO options that should be used while making the brand |
||
171 | // new connection instance. The PDO options control various aspects of the |
||
172 | // connection's behavior, and some might be specified by the developers. |
||
173 | $connection = $this->createConnection($dsn, $config, $options); |
||
174 | |||
175 | $collation = $config['collation']; |
||
176 | |||
177 | // Next we will set the "names" and "collation" on the clients connections so |
||
178 | // a correct character set will be used by this client. The collation also |
||
179 | // is set on the server but needs to be set here on this client objects. |
||
180 | $charset = $config['charset']; |
||
181 | |||
182 | $names = "set names '$charset'". |
||
183 | (! is_null($collation) ? " collate '$collation'" : ''); |
||
184 | |||
185 | $connection->prepare($names)->execute(); |
||
186 | |||
187 | return $connection; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Create a DSN string from a configuration. |
||
192 | * |
||
193 | * Chooses socket or host/port based on the 'unix_socket' config value. |
||
194 | * |
||
195 | * @param array $config |
||
196 | * @return string |
||
197 | */ |
||
198 | protected function getDsn(array $config) |
||
199 | { |
||
200 | return $this->configHasSocket($config) ? $this->getSocketDsn($config) : $this->getHostDsn($config); |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Determine if the given configuration array has a UNIX socket value. |
||
205 | * |
||
206 | * @param array $config |
||
207 | * @return bool |
||
208 | */ |
||
209 | protected function configHasSocket(array $config) |
||
210 | { |
||
211 | return isset($config['unix_socket']) && ! empty($config['unix_socket']); |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Get the DSN string for a socket configuration. |
||
216 | * |
||
217 | * @param array $config |
||
218 | * @return string |
||
219 | */ |
||
220 | protected function getSocketDsn(array $config) |
||
221 | { |
||
222 | return "mysql:unix_socket={$config['unix_socket']};dbname={$config['database']}"; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Get the DSN string for a host / port configuration. |
||
227 | * |
||
228 | * @param array $config |
||
229 | * @return string |
||
230 | */ |
||
231 | protected function getHostDsn(array $config) |
||
232 | { |
||
233 | extract($config, EXTR_SKIP); |
||
234 | |||
235 | return isset($port) |
||
236 | ? "mysql:host={$host};port={$port};dbname={$database}" |
||
237 | : "mysql:host={$host};dbname={$database}"; |
||
238 | } |
||
239 | } |
||
240 | |||
241 | |||
242 | interface DatabaseAdapterInterface |
||
243 | { |
||
244 | /** |
||
245 | * Establish a database connection. |
||
246 | * |
||
247 | * @param array $config |
||
248 | * @return \PDO |
||
249 | */ |
||
250 | public function connect(array $config); |
||
251 | } |
||
252 | |||
253 | |||
254 | class DatabaseConnection |
||
255 | { |
||
256 | /** |
||
257 | * [$instance description] |
||
258 | * @var [type] |
||
259 | */ |
||
260 | private static $instance; |
||
261 | |||
262 | /** |
||
263 | * [$databaseConnection description] |
||
264 | * @var [type] |
||
265 | */ |
||
266 | private $databaseConnection; |
||
267 | |||
268 | /** |
||
269 | * The default PDO connection options. |
||
270 | * |
||
271 | * @var array |
||
272 | */ |
||
273 | protected $options = [ |
||
274 | PDO::ATTR_CASE => PDO::CASE_NATURAL, |
||
275 | PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, |
||
276 | PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, |
||
277 | PDO::ATTR_STRINGIFY_FETCHES => false, |
||
278 | PDO::ATTR_EMULATE_PREPARES => false, |
||
279 | ]; |
||
280 | |||
281 | /** |
||
282 | * Singleton Class: |
||
283 | * Constructor reads database config file and creates connection. |
||
284 | */ |
||
285 | private function __construct(DatabaseConnectionStringFactoryInterface $dbConnStringFactory) |
||
286 | { |
||
287 | //Read config file |
||
288 | $this->config = parse_ini_file('config.ini'); |
||
289 | $dsn = $dbConnStringFactory->createDatabaseSourceString($this->config); |
||
290 | $this->createConnection($dsn, $this->options); |
||
291 | } |
||
292 | |||
293 | public static function getInstance() |
||
294 | { |
||
295 | if (self::$instance === null) { |
||
296 | self::$instance = new self(new DatabaseConnectionStringFactory); |
||
297 | } |
||
298 | return self::$instance; |
||
299 | } |
||
300 | |||
301 | |||
302 | /** |
||
303 | * Create a new PDO connection. |
||
304 | * |
||
305 | * @param string $dsn |
||
306 | * @param array $config |
||
307 | * @return \PDO |
||
308 | */ |
||
309 | public function createConnection($dsn, array $config) |
||
310 | { |
||
311 | $username = $this->config['USERNAME']; |
||
312 | |||
313 | $password = $this->config['PASSWORD']; |
||
314 | |||
315 | try { |
||
316 | $pdo = new PDO($dsn, $username, $password, $options); |
||
317 | } catch (Exception $e) { |
||
318 | $pdo = $this->tryAgainIfCausedByLostConnection( |
||
319 | $e, $dsn, $username, $password, $options |
||
320 | ); |
||
321 | } |
||
322 | |||
323 | return $pdo; |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Get the default PDO connection options. |
||
328 | * |
||
329 | * @return array |
||
330 | */ |
||
331 | public function getDefaultOptions() |
||
332 | { |
||
333 | return $this->options; |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * Set the default PDO connection options. |
||
338 | * |
||
339 | * @param array $options |
||
340 | * @return void |
||
341 | */ |
||
342 | public function setDefaultOptions(array $options) |
||
343 | { |
||
344 | $this->options = $options; |
||
345 | } |
||
346 | |||
347 | /** |
||
348 | * Handle a exception that occurred during connect execution. |
||
349 | * |
||
350 | * @param \Exception $e |
||
351 | * @param string $dsn |
||
352 | * @param string $username |
||
353 | * @param string $password |
||
354 | * @param array $options |
||
355 | * @return \PDO |
||
356 | * |
||
357 | * @throws \Exception |
||
358 | */ |
||
359 | protected function tryAgainIfCausedByLostConnection(Exception $e, $dsn, $username, $password, $options) |
||
360 | { |
||
361 | if ($this->causedByLostConnection($e)) { |
||
362 | return new PDO($dsn, $username, $password, $options); |
||
363 | } |
||
364 | |||
365 | throw $e; |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Determine if the given exception was caused by a lost connection. |
||
370 | * |
||
371 | * @param \Exception $e |
||
372 | * @return bool |
||
373 | */ |
||
374 | protected function causedByLostConnection(Exception $e) |
||
375 | { |
||
376 | $message = $e->getMessage(); |
||
377 | |||
378 | return Helpers::contains($message, [ |
||
379 | 'server has gone away', |
||
380 | 'no connection to the server', |
||
381 | 'Lost connection', |
||
382 | 'is dead or not enabled', |
||
383 | 'Error while sending', |
||
384 | 'decryption failed or bad record mac', |
||
385 | 'SSL connection has been closed unexpectedly', |
||
386 | 'Deadlock found when trying to get lock', |
||
387 | ]); |
||
388 | } |
||
389 | } |
||
390 | |||
391 | |||
392 | class Helpers { |
||
393 | |||
394 | /** |
||
395 | * Determine if a given string contains a given substring. |
||
396 | * |
||
397 | * @param string $haystack |
||
398 | * @param string|array $needles |
||
399 | * @return bool |
||
400 | */ |
||
401 | public static function contains($haystack, $needles) |
||
402 | { |
||
403 | foreach ((array) $needles as $needle) { |
||
404 | if ($needle != '' && strpos($haystack, $needle) !== false) { |
||
405 | return true; |
||
406 | } |
||
407 | } |
||
408 | |||
409 | return false; |
||
410 | } |
||
411 | } |