Explorar o código

add createFromDsn factory with debug and logger support

phpdevcommunity hai 1 mes
pai
achega
52bb179915

+ 2 - 1
composer.json

@@ -26,7 +26,8 @@
     "phpdevcommunity/relational-query": "^1.0",
     "phpdevcommunity/php-console": "^1.0",
     "phpdevcommunity/michel-package-starter": "^1.0",
-    "phpdevcommunity/php-filesystem": "^1.0"
+    "phpdevcommunity/php-filesystem": "^1.0",
+    "psr/log": "^1.1|^2.0|^3.0"
   },
   "require-dev": {
     "phpdevcommunity/unitester": "^0.1.0@alpha"

+ 1 - 7
src/Debugger/PDOStatementLogger.php

@@ -27,21 +27,15 @@ class PDOStatementLogger extends \PDOStatement
 
     private function startQuery(string $query, array $params): void
     {
-        if ($this->getSqlDebugger() === null) {
-            return;
-        }
         $this->getSqlDebugger()->startQuery($query , $params);
     }
 
     private function stopQuery(): void
     {
-        if ($this->getSqlDebugger() === null) {
-            return;
-        }
         $this->getSqlDebugger()->stopQuery();
     }
 
-    public function getSqlDebugger(): ?SqlDebugger
+    public function getSqlDebugger(): SqlDebugger
     {
         return $this->debugger;
     }

+ 13 - 0
src/Debugger/SqlDebugger.php

@@ -2,12 +2,21 @@
 
 namespace PhpDevCommunity\PaperORM\Debugger;
 
+use Psr\Log\LoggerInterface;
+
 class SqlDebugger
 {
+    private ?LoggerInterface $logger;
+
     private array $queries = [];
 
     public int $currentQuery = 0;
 
+    public function __construct(?LoggerInterface $logger = null)
+    {
+        $this->logger = $logger;
+    }
+
     public function startQuery(string $query, array $params): void
     {
         $query = preg_replace('/\s*\n\s*/', ' ', $query);
@@ -27,6 +36,9 @@ class SqlDebugger
 
         $start = $this->queries[$this->currentQuery]['startTime'];
         $this->queries[$this->currentQuery]['executionTime'] = microtime(true) - $start;
+        if ($this->logger !== null) {
+            $this->logger->debug($this->queries[$this->currentQuery]);
+        }
     }
 
     public function getQueries(): array
@@ -38,4 +50,5 @@ class SqlDebugger
     {
         $this->queries = [];
     }
+
 }

+ 11 - 4
src/Driver/DriverManager.php

@@ -6,8 +6,13 @@ use Exception;
 use PhpDevCommunity\PaperORM\PaperConnection;
 use PhpDevCommunity\PaperORM\Platform\MariaDBPlatform;
 
-class DriverManager
+final class DriverManager
 {
+
+    private function __construct()
+    {
+    }
+
     private static array $driverSchemeAliases = [
         'sqlite' => SqliteDriver::class,
         'sqlite3' => SqliteDriver::class,
@@ -15,14 +20,16 @@ class DriverManager
         'mariadb' => MariaDBDriver::class
     ];
 
-    public static function getConnection(string $driver, array $params): PaperConnection
+    public static function createConnection(string $driver, array $params): PaperConnection
     {
         $driver = strtolower($driver);
 
         $drivers = self::$driverSchemeAliases;
-        if (isset($params['driver_class'])) {
-            $drivers[$driver] = $params['driver_class'];
+        if (isset($params['options']['driverClass'])) {
+            $drivers[$driver] = $params['options']['driverClass'];
+            unset($params['options']['driverClass']);
         }
+
         if (!isset($drivers[$driver])) {
             throw new Exception('Driver not found, please check your config : ' . $driver);
         }

+ 2 - 2
src/Driver/MariaDBDriver.php

@@ -57,8 +57,8 @@ final class MariaDBDriver implements DriverInterface
             $dsn .= 'unix_socket=' . $params['unix_socket'] . ';';
         }
 
-        if (isset($params['charset'])) {
-            $dsn .= 'charset=' . $params['charset'] . ';';
+        if (isset($params['options']['charset'])) {
+            $dsn .= sprintf('charset=%s;', $params['options']['charset']);
         }
 
         return $dsn;

+ 16 - 1
src/EntityManager.php

@@ -5,8 +5,10 @@ namespace PhpDevCommunity\PaperORM;
 use PhpDevCommunity\PaperORM\Cache\EntityMemcachedCache;
 use PhpDevCommunity\PaperORM\Driver\DriverManager;
 use PhpDevCommunity\PaperORM\Mapper\EntityMapper;
+use PhpDevCommunity\PaperORM\Parser\DSNParser;
 use PhpDevCommunity\PaperORM\Platform\PlatformInterface;
 use PhpDevCommunity\PaperORM\Repository\Repository;
+use Psr\Log\LoggerInterface;
 
 class EntityManager implements EntityManagerInterface
 {
@@ -21,10 +23,23 @@ class EntityManager implements EntityManagerInterface
 
     private EntityMemcachedCache $cache;
 
+    public static function createFromDsn(string $dsn, bool $debug = false, LoggerInterface $logger = null): self
+    {
+        if (empty($dsn)) {
+            throw new \LogicException('Cannot create an EntityManager from an empty DSN.');
+        }
+        $params = DSNParser::parse($dsn);
+        $params['extra']['debug'] = $debug;
+        if ($logger !== null) {
+            $params['extra']['logger'] = $logger;
+        }
+        return new self($params);
+    }
+
     public function __construct(array $config = [])
     {
         $driver = $config['driver'];
-        $this->connection = DriverManager::getConnection($driver, $config);
+        $this->connection = DriverManager::createConnection($driver, $config);
         $this->unitOfWork = new UnitOfWork();
         $this->cache = new EntityMemcachedCache();
     }

+ 1 - 0
src/Michel/Package/MichelPaperORMPackage.php

@@ -30,6 +30,7 @@ class MichelPaperORMPackage implements PackageInterface
                     throw new LogicException('Database DSN not found, please set DATABASE_DSN in .env file or database.dsn in config');
                 }
                 $params = DSNParser::parse($container->get('database.dsn'));
+                $params['options']['debug'] = $container->get('michel.debug');
                 return new EntityManager($params);
             },
             PaperMigration::class => static function (ContainerInterface $container) {

+ 22 - 3
src/PaperConnection.php

@@ -2,10 +2,13 @@
 
 namespace PhpDevCommunity\PaperORM;
 
+use Exception;
+use LogicException;
 use PDO;
 use PDOStatement;
 use PhpDevCommunity\PaperORM\Driver\DriverInterface;
 use PhpDevCommunity\PaperORM\Pdo\PaperPDO;
+use Psr\Log\LoggerInterface;
 
 final class PaperConnection
 {
@@ -16,12 +19,26 @@ final class PaperConnection
     private DriverInterface $driver;
 
     private bool $debug;
+    private ?LoggerInterface $logger = null;
 
     public function __construct(DriverInterface $driver, array $params)
     {
         $this->params = $params;
         $this->driver = $driver;
-        $this->debug = $params['debug'] ?? false;
+        $extra = $params['extra'] ?? [];
+        $this->debug = (bool)($extra['debug'] ?? false);
+
+        if (array_key_exists('logger', $extra)) {
+            $logger = $extra['logger'];
+            if (!$logger instanceof LoggerInterface) {
+                $given = is_object($logger) ? get_class($logger) : gettype($logger);
+                throw new LogicException(sprintf(
+                    'The logger must be an instance of Psr\Log\LoggerInterface, %s given.',
+                    $given
+                ));
+            }
+            $this->logger = $logger;
+        }
     }
 
 
@@ -35,7 +52,7 @@ final class PaperConnection
     {
         $db = $this->getPdo()->prepare($query);
         if ($db === false) {
-            throw new \Exception($this->getPdo()->errorInfo()[2]);
+            throw new Exception($this->getPdo()->errorInfo()[2]);
         }
         foreach ($params as $key => $value) {
             if (is_string($key)) {
@@ -80,9 +97,11 @@ final class PaperConnection
     public function connect(): bool
     {
         if (!$this->isConnected()) {
+            $params = $this->params;
+            unset($params['extra']);
             $this->pdo = $this->driver->connect($this->params);
             if ($this->debug) {
-                $this->pdo->enableSqlDebugger();
+                $this->pdo->enableSqlDebugger($this->logger);
             }
             return true;
         }

+ 1 - 0
src/Parser/DSNParser.php

@@ -46,6 +46,7 @@ final class DSNParser
 
         $options = [];
         if (isset($params['query'])) {
+            parse_str("mysql://user:pass@host/db?charset=utf8mb4&driverClass=App\Database\Driver\MyFancyDriver", $options);
             parse_str($params['query'], $options);
             unset($params['query']);
         }

+ 3 - 2
src/Pdo/PaperPDO.php

@@ -4,15 +4,16 @@ namespace PhpDevCommunity\PaperORM\Pdo;
 
 use PhpDevCommunity\PaperORM\Debugger\PDOStatementLogger;
 use PhpDevCommunity\PaperORM\Debugger\SqlDebugger;
+use Psr\Log\LoggerInterface;
 
 final class PaperPDO extends \PDO
 {
     private ?SqlDebugger $debug = null;
 
-    public function enableSqlDebugger() : void
+    public function enableSqlDebugger(?LoggerInterface $logger = null) : void
     {
         if ($this->debug === null) {
-            $this->debug = new SqlDebugger();
+            $this->debug = new SqlDebugger($logger);
         }
         $this->setAttribute(\PDO::ATTR_STATEMENT_CLASS, [PDOStatementLogger::class, [$this->debug]]);
     }

+ 0 - 1
tests/Common/SqlDebuggerTest.php

@@ -42,5 +42,4 @@ class SqlDebuggerTest extends TestCase
         $this->assertEquals([], $queries[0]['params']);
         $this->assertNotNull($queries[0]['executionTime']);
     }
-
 }

+ 0 - 2
tests/MigrationTest.php

@@ -176,8 +176,6 @@ class MigrationTest extends TestCase
 
     private function testFailedMigration(PaperMigration  $paperMigration): void
     {
-        $em = $paperMigration->getEntityManager();
-
         $paperMigration->generateMigration();
 
         $this->expectException(RuntimeException::class, function () use ($paperMigration){