PDO Instance Slim 4

Where is the best place to create a PDO instance in v4?

I have started with the slim-skeleton.

In my previous version with Slim3 I just added dependency like this:

$container[‘db’] = function ($container) {
$db = $container[‘settings’][‘db’];

$pdo = new PDO("mysql:host=" . $db['host'] . ";dbname=" . $db['dbname'],
    $db['user'], $db['pass']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;

};

In the slim-skeleton / slim 4 the dependencies looks like this where it just returns value. Is something like this possible or do I need to retype my dependencies page to add each one individually to the container as opposed to just returning just a logger?

return function (ContainerBuilder $containerBuilder) {
$containerBuilder->addDefinitions([
LoggerInterface::class => function (ContainerInterface $c) {
$settings = $c->get(‘settings’);

        $loggerSettings = $settings['logger'];
        $logger = new Logger($loggerSettings['name']);

        $processor = new UidProcessor();
        $logger->pushProcessor($processor);

        $handler = new StreamHandler($loggerSettings['path'], $loggerSettings['level']);
        $logger->pushHandler($handler);

        return $logger;
    },
]);

$containerBuilder->addDefinitions([
    DatabaseInterface::class => function (ContainerInterface $c) {
        $settings = $c->get('settings');

        $dbSettings = $settings['db'];

        $pdo = new PDO("mysql:host=" . $dbSettings['host'] . ";dbname=" . $dbSettings['dbname'], $dbSettings['user'], $dbSettings['pass']);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        return $pdo;
    },
]);

};

Adding it to the container as you did in your example is exactly the way it should be done.

My question then is regarding the DatabaseInterface::class

I have not created that yet. What would it look like? Just an empty class?

All of the db connection parameters are configured in settings. Not sure what useful info would be in there?

The question is: Do you really want to be able to exchange the connection even though you only use PDO?? If not, you may not need a generic database interface.

If yes, here is a PDO “inspired” connection interface:

interface ConnectionInterface
{
    public function beginTransaction(): bool;

    public function commit(): bool;

    public function errorCode(): string;

    public function errorInfo(): array;

    public function exec(string $statement): int;

    public function inTransaction(): bool;

    public function lastInsertId(string $name = null): string;

    public function prepare(string $statement, array $driverOptions = []): PDOStatement;

    public function query(string $statement): PDOStatement;

    public function quote(string $string, int $parameterType = PDO::PARAM_STR): string;

    public function rollBack(): bool;
}

This interface is still not perfect, because the PDOStatement is not abstracted away. This would require another interface like a StatementInterface etc. You see, it’s getting more and more complex :slight_smile:

So how would you load the PDO dependency into the containerBuilder without a DatabaseInterface abstraction layer?

Like you do it. But in this special case without the interface.

PDO itself is already a database (driver) abstraction layer.
Also PDO does not implement any interface nor DatabaseInterface.

Instead of DatabaseInterface::class use just PDO::class, because you are returning a PDO instance here.

Great! Thanks for the clarification