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
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();
},
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.