Trying to inject PDO with failing when using type hinting

I’ve spent the whole afternoon trying to get DI to work with PDO, but for what’s probably a dumb reason it didn’t work, so, can I ask for a bit of help here?

     $builder = new DI\ContainerBuilder();
    $builder->addDefinitions([
        PDO::class => function (ContainerInterface $container) {
            $host = 'localhost';
            $dbname = 'xxx';
            $username = 'yyyy';
            $password = 'zzzz';
            $charset = 'utf8mb4';
            $flags =  [
                // Turn off persistent connections
                PDO::ATTR_PERSISTENT => false,
                // Enable exceptions
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                // Emulate prepared statements
                PDO::ATTR_EMULATE_PREPARES => true,
                // Set default fetch mode to array
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                // Set character set
                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
            ];
            $dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
    
            return new PDO($dsn, $username, $password, $flags);
        },
    ]);
    $container = $builder->build();
    AppFactory::setContainer($container);

So far this works if I use

die(var_dump(DPO::class)); 

I can see that a PDO object has been created.

But when it come to the time to use it on a constructor:

    abstract class Controller
    {
        private $db = null;
        public function __construct(PDO $db)
        {
            $this->db = $db;
        }
    }

I get the error:
Entry "PDO" cannot be resolved: Parameter $dsn of __construct() has no value defined or guessable

What could I be doing wrong?

I wonder why this line works for you:

This line gives me: string(3) "DPO", but the output must be object(PDO)#1 (0) {}

Entry “PDO” cannot be resolved: Parameter $dsn of __construct() has no value defined or guessable

This error message says that the DI container could not find a container definition and tried to create it manually. So make sure that the DI container for DPO::class is correctly configured.

Example:

use DI\ContainerBuilder;
use Slim\App;
use Slim\Factory\AppFactory;

$containerBuilder = new ContainerBuilder();

// Add container definitions
$containerBuilder->addDefinitions( /* ... */ );

// Build PHP-DI Container instance
$container = $containerBuilder->build();

// Create App instance
$app = $container->get(App::class);

// ...

$app->run();

Also make sure to set the correct container instance into the Slim AppFactory.
I would also recommend putting the App::class into the DI container:

App::class => function (ContainerInterface $container) {
    AppFactory::setContainer($container);

    return AppFactory::create();
},

Here’s the configuration for the container:

Here I attempt to create the app:

Now it fails with

Before I had been using

so it failed once later, but I figured I’d better try to follow your example as closely as possible.

I think I may be stupid.

I used “$app = \DI\Bridge\Slim\Bridge::create();” since I saw it as being the recomended way to initialize the app after installing the PHP-DI Slim bridge, but I never noticed I didn’t pass it the container.

Using “$app = \DI\Bridge\Slim\Bridge::create($container);” solved the problem.