diff --git a/src/Config.php b/src/Config.php index a1e8bbf..bc1f643 100644 --- a/src/Config.php +++ b/src/Config.php @@ -2,8 +2,6 @@ namespace Connector; -use RuntimeException; - class Config { protected $name; @@ -17,6 +15,7 @@ class Config protected $properties = []; // arbitrary database properties such as name, description, tier, etc protected $arguments = []; // DSN arguments protected $fileName; + protected $queries = []; public function getName() { @@ -26,6 +25,7 @@ public function getName() public function setName($name) { $this->name = $name; + return $this; } @@ -37,6 +37,7 @@ public function getPort() public function setPort($port) { $this->port = $port; + return $this; } @@ -48,6 +49,7 @@ public function getServer() public function setServer($server) { $this->server = $server; + return $this; } @@ -59,10 +61,10 @@ public function getCluster() public function setCluster($cluster) { $this->cluster = $cluster; + return $this; } - public function getAddress() { return $this->address; @@ -71,10 +73,10 @@ public function getAddress() public function setAddress($address) { $this->address = $address; + return $this; } - public function getPassword() { return $this->password; @@ -83,6 +85,7 @@ public function getPassword() public function setPassword($password) { $this->password = $password; + return $this; } @@ -94,6 +97,7 @@ public function getUsername() public function setUsername($username) { $this->username = $username; + return $this; } @@ -110,6 +114,7 @@ public function setDriver($driver) $this->port = 3306; break; } + return $this; } @@ -128,6 +133,7 @@ public function setFileName($fileName) public function setProperty($key, $value) { $this->properties[$key] = $value; + return $this; } @@ -136,12 +142,14 @@ public function getProperty($key) if (!isset($this->properties[$key])) { return null; } + return $this->properties[$key]; } public function setArgument($key, $value) { $this->arguments[$key] = $value; + return $this; } @@ -150,6 +158,7 @@ public function getArgument($key) if (!isset($this->arguments[$key])) { return null; } + return $this->arguments[$key]; } @@ -161,33 +170,52 @@ public function getArguments() public function validate() { if (!$this->getName()) { - throw new RuntimeException("Missing name"); + throw new \RuntimeException('Missing name'); } switch ($this->getDriver()) { case 'mysql': case 'pgsql': if (!$this->getUsername()) { - throw new RuntimeException("Missing username"); + throw new \RuntimeException('Missing username'); } if (!$this->getUsername()) { - throw new RuntimeException("Missing password"); + throw new \RuntimeException('Missing password'); } if (!$this->getAddress()) { - throw new RuntimeException("Missing address"); + throw new \RuntimeException('Missing address'); } if (!$this->getPort()) { - throw new RuntimeException("Missing port"); + throw new \RuntimeException('Missing port'); } break; case 'sqlite': break; case 'sqlsrv': if (!$this->getAddress()) { - throw new RuntimeException("Missing address"); + throw new \RuntimeException('Missing address'); } break; default: - throw new RuntimeException("Unsupported driver: " . $this->getDriver()); + throw new \RuntimeException('Unsupported driver: '.$this->getDriver()); } } + + /** + * @param [array] $array + */ + public function setQueries($array = []): self + { + $this->queries = $array; + + return $this; + } + + public function getQuery($key) + { + if (!isset($this->queries[$key])) { + return null; + } + + return $this->queries[$key]; + } } diff --git a/src/Connector.php b/src/Connector.php index c9aa7c8..2955e6a 100644 --- a/src/Connector.php +++ b/src/Connector.php @@ -3,12 +3,11 @@ namespace Connector; use Connector\Backend\BackendInterface; -use PDO; -use RuntimeException; class Connector { protected $backends = []; + public function registerBackend(BackendInterface $backend) { $this->backends[] = $backend; @@ -26,7 +25,7 @@ public function getConfig($dsn) $arguments = parse_url($dsn, PHP_URL_QUERY); parse_str($arguments, $arguments); // parse ?x=y&a=b format into k/v array - foreach ($arguments as $k=>$v) { + foreach ($arguments as $k => $v) { $config->setArgument($k, $v); } @@ -34,7 +33,7 @@ public function getConfig($dsn) $config->setPort($port); } $urlPath = parse_url($dsn, PHP_URL_PATH); - if (parse_url($dsn, PHP_URL_SCHEME) == 'sqlite') { + if ('sqlite' == parse_url($dsn, PHP_URL_SCHEME)) { $i = pathinfo($urlPath); $config->setName($i['filename']); $config->setFileName($urlPath); @@ -42,6 +41,12 @@ public function getConfig($dsn) $config->setName(substr($urlPath, 1)); } + // query pramater + parse_str(parse_url($dsn, PHP_URL_QUERY), $params); + if ($params) { + $config->setQueries($params); + } + // TODO: support further resolving cluster/server settings // from backends based on address/host/server? return $config; @@ -54,24 +59,25 @@ public function getConfig($dsn) $this->loadKeys($config, $dsnKeys); if ($config->getCluster()) { - $clusterKeys = $backend->getKeys('clusters/' . $config->getCluster()); + $clusterKeys = $backend->getKeys('clusters/'.$config->getCluster()); if ($clusterKeys) { $this->loadKeys($config, $clusterKeys); } } if ($config->getServer()) { - $serverKeys = $backend->getKeys('servers/' . $config->getServer()); + $serverKeys = $backend->getKeys('servers/'.$config->getServer()); if ($serverKeys) { $this->loadKeys($config, $serverKeys); } else { $config->setAddress($config->getServer()); } } + return $config; } } - throw new RuntimeException("Can't resolve DSN `" . $dsn . '`'); + throw new \RuntimeException("Can't resolve DSN `".$dsn.'`'); } public function getPdoDsn(Config $config, $mode = 'db') @@ -81,71 +87,72 @@ public function getPdoDsn(Config $config, $mode = 'db') case 'server': break; default: - throw new RuntimeException("Invalid mode: " . $mode); + throw new \RuntimeException('Invalid mode: '.$mode); } - $pdoDsn = $config->getDriver() . ':'; + $pdoDsn = $config->getDriver().':'; switch ($config->getDriver()) { case 'pgsql': case 'mysql': - $pdoDsn .= 'host=' . $config->getAddress() . ';'; + $pdoDsn .= 'host='.$config->getAddress().';'; if ($config->getPort()) { - $pdoDsn .= 'port=' . $config->getPort() . ';'; + $pdoDsn .= 'port='.$config->getPort().';'; } - if ($mode=='db') { - $pdoDsn .= 'dbname=' . $config->getName() . ';'; + if ('db' == $mode) { + $pdoDsn .= 'dbname='.$config->getName().';'; } - $pdoDsn .= 'charset=utf8;'; + $pdoDsn .= 'charset='.($config->getQuery('charset') ? $config->getQuery('charset') : 'utf8;'); break; case 'sqlite': $pdoDsn .= $config->getFileName(); break; case 'sqlsrv': - $pdoDsn .= 'Server=' . $config->getAddress() . ';Database=' . $config->getName(); - foreach ($config->getArguments() as $k=>$v) { - $pdoDsn .= ';' . $k . '=' . $v; + $pdoDsn .= 'Server='.$config->getAddress().';Database='.$config->getName(); + foreach ($config->getArguments() as $k => $v) { + $pdoDsn .= ';'.$k.'='.$v; } break; default: - throw new RuntimeException("Unsupported driver: " . $config->getDriver()); + throw new \RuntimeException('Unsupported driver: '.$config->getDriver()); } + return $pdoDsn; } public function create(Config $config) { if ($this->exists($config)) { - throw new RuntimeException("Database already exists"); + throw new \RuntimeException('Database already exists'); } // TODO: validate dbname? switch ($config->getDriver()) { case 'mysql': $pdo = $this->getPdo($config, 'server'); $stmt = $pdo->prepare( - "CREATE DATABASE " . $config->getName() + 'CREATE DATABASE '.$config->getName() ); $stmt->execute(); break; default: - throw new RuntimeException("Unsupported driver: " . $config->getDriver()); + throw new \RuntimeException('Unsupported driver: '.$config->getDriver()); } } public function drop(Config $config) { if (!$this->exists($config)) { - throw new RuntimeException("Database does not exists"); + throw new \RuntimeException('Database does not exists'); } // TODO: validate dbname? switch ($config->getDriver()) { case 'mysql': $pdo = $this->getPdo($config, 'server'); $stmt = $pdo->prepare( - "DROP DATABASE " . $config->getName() + 'DROP DATABASE '.$config->getName() ); $stmt->execute(); break; default: - throw new RuntimeException("Unsupported driver: " . $config->getDriver()); + throw new \RuntimeException('Unsupported driver: '.$config->getDriver()); } } @@ -155,20 +162,21 @@ public function exists(Config $config) case 'mysql': $pdo = $this->getPdo($config, 'server'); $stmt = $pdo->prepare( - "SELECT COUNT(*) AS c FROM INFORMATION_SCHEMA.SCHEMATA - WHERE SCHEMA_NAME = :dbname" + 'SELECT COUNT(*) AS c FROM INFORMATION_SCHEMA.SCHEMATA + WHERE SCHEMA_NAME = :dbname' ); $stmt->execute( [ - ':dbname' => $config->getName() + ':dbname' => $config->getName(), ] ); + return (bool) $stmt->fetchColumn(); case 'sqlite': return $this->getPdo($config, 'server'); break; default: - throw new RuntimeException("Unsupported driver"); + throw new \RuntimeException('Unsupported driver'); } } @@ -177,7 +185,7 @@ public function getPdo(Config $config, $mode = 'db') $pdoDsn = $this->getPdoDsn($config, $mode); $config->validate(); // throws if invalid - return new PDO($pdoDsn, $config->getUsername(), $config->getPassword()); + return new \PDO($pdoDsn, $config->getUsername(), $config->getPassword()); } public function loadKeys(Config $config, $keys) @@ -186,13 +194,14 @@ public function loadKeys(Config $config, $keys) return; } foreach ($keys as $key => $value) { - $methodName = 'set' . ucfirst($key); + $methodName = 'set'.ucfirst($key); if (method_exists($config, $methodName)) { $config->$methodName($value); } else { $config->setProperty($key, $value); } } + return $config; } }