1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace League\Database\Driver; |
4
|
|
|
|
5
|
|
|
use League\Database\Exceptions\InvalidArgumentException; |
6
|
|
|
use PDO; |
7
|
|
|
|
8
|
|
|
final class Engine |
9
|
|
|
{ |
10
|
|
|
/** |
11
|
|
|
* List of all existed connections |
12
|
|
|
* |
13
|
|
|
* @var array |
14
|
|
|
*/ |
15
|
|
|
private static $connections = []; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Default database configurations, that will be added to connection, if they were missed |
19
|
|
|
*/ |
20
|
|
|
const DEFAULT_SETTINGS = [ |
21
|
|
|
'charset' => 'utf8', |
22
|
|
|
'type' => 'mysql', |
23
|
|
|
'port' => 3306, // 3306 for MySQL, 5432 (or 5433) for PostgreSQL |
|
|
|
|
24
|
|
|
'options' => [], |
25
|
|
|
]; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Required attributes in database configuration |
29
|
|
|
*/ |
30
|
|
|
const REQUIRED_ATTRIBUTES = ['host', 'database', 'username', 'password']; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Set connection with database |
34
|
|
|
* |
35
|
|
|
* @param string $name Unique name for connection |
36
|
|
|
* @param array $config Configuration settings for database connection |
37
|
|
|
* @param array $options Some specific options |
38
|
|
|
* |
39
|
|
|
* @throws \League\Database\Exceptions\InvalidArgumentException |
40
|
|
|
* @return bool|TransactionPDO |
41
|
|
|
*/ |
42
|
|
|
public static function setConnection(string $name, array $config, array $options = []) |
43
|
|
|
{ |
44
|
|
|
if (isset(self::$connections[$name])) { |
45
|
|
|
return false; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
self::checkRequiredAttributes($config); |
49
|
|
|
$config += self::DEFAULT_SETTINGS; |
50
|
|
|
|
51
|
|
|
$dsn = "{$config['type']}:host={$config['host']};port={$config['port']};dbname={$config['database']}"; |
52
|
|
|
$username = $config['username']; |
53
|
|
|
$password = $config['password']; |
54
|
|
|
$opts = self::fetchOptions($options, $config); |
55
|
|
|
|
56
|
|
|
self::$connections[$name] = new TransactionPDO($dsn, $username, $password, $opts); |
57
|
|
|
|
58
|
|
|
return self::$connections[$name]; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Returns database handler |
63
|
|
|
* @param string $name Unique name of connection |
64
|
|
|
* |
65
|
|
|
* @return bool|TransactionPDO |
66
|
|
|
*/ |
67
|
|
|
public static function getConnection(string $name) |
68
|
|
|
{ |
69
|
|
|
return self::$connections[$name] ?? false; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Check for required database configurations |
74
|
|
|
* |
75
|
|
|
* @param array $config Configuration settings for database connection |
76
|
|
|
* |
77
|
|
|
* @throws InvalidArgumentException |
78
|
|
|
*/ |
79
|
|
|
private static function checkRequiredAttributes(array $config) |
80
|
|
|
{ |
81
|
|
|
$attributes = array_keys($config); |
82
|
|
|
|
83
|
|
|
if ($diff = array_diff(self::REQUIRED_ATTRIBUTES, $attributes)) { |
84
|
|
|
throw new InvalidArgumentException( |
85
|
|
|
'Missing required database configurations: '.implode(',', $diff) |
86
|
|
|
); |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Fetch options to be set with PDO connection |
92
|
|
|
* |
93
|
|
|
* @param array $customOptions |
94
|
|
|
* @param array $config |
95
|
|
|
* |
96
|
|
|
* @return array |
97
|
|
|
*/ |
98
|
|
|
private static function fetchOptions(array $customOptions, array $config) : array |
99
|
|
|
{ |
100
|
|
|
$options = [ |
101
|
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, |
102
|
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, |
103
|
|
|
]; |
104
|
|
|
|
105
|
|
|
if ($config['type'] === 'mysql') { |
106
|
|
|
$options += self::fetchMySqlOptions($config); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
return $customOptions + $config['options'] + $options; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Fetch default MySQL options |
114
|
|
|
* |
115
|
|
|
* @param array $config |
116
|
|
|
* |
117
|
|
|
* @return array |
118
|
|
|
*/ |
119
|
|
|
private static function fetchMySqlOptions(array $config) : array |
120
|
|
|
{ |
121
|
|
|
return [ |
122
|
|
|
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES " . $config['charset'], |
123
|
|
|
]; |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.