Problem: DI Factories passing entire container

Hi, I’m a bit new to frameworks and DI in general but I found this article helpful: https://akrabat.com/di-factories-for-slim-controllers/

But I’m having a problem, it seems that when I try to inject a dependency into a controller it’s getting passed the entire container object.

 $container['DatabaseService'] = function ($c) {
    return new \Lib\SqlModel(); // Aura/Sql wrapper
 };

$container['ServiceRecordsController'] = function($c) {
    $dbService = $c->get('DatabaseService');
    return new ServiceRecordsController($dbService);
};

My route looks like so:

$app->get('/records', ServiceRecordsController::class . ':show')
  ->setName('show_records');

And my controller looks like:

...
public function __construct($dbService)
  {
    $this->dbService = $dbService; // this is the container, not $c['DatabaseService']
    $this->serRecHandle = new ServiceRecords($this->dbService);
  }
...

when I eventually get to where I use $dbService I need to reference it as $dbService[‘DatabaseService’] and it works fine.

What am I missing?

Thanks - Don

If Slim doesn’t fid an entry for your controller in the container, it will pass the container to the controller’s constructor. So it would appear as though Slim isn’t finding the entry for your controller in the container if you are getting it in the constructor.

The issue isn’t obvious to me based on what you have posted. I wonder if it is perhaps a namespace issue, or perhaps needing a leading backlash.

$app->get('/records', \ServiceRecordsController::class . ':show')

Is yoru controller class namespaced?

Yes it’s namespaced, I tried the leading slash and the app broke. Now that I know why it’s acting like it is I’ll work with it and see what I can find.

Thanks, Don

Check if that contains a reference to the container.

Try to namespace the container ID e.g.

$container[ServiceRecordsController::class] = function($c) {

If your class is namespaced, your container entry will likely need to be.

$app->get('/records', App\Controllers\ServiceRecordsController::class . ':show')

Thanks, I’ll check this out tonight. This is on a personal project.

Please excuse my bumping this old thread but, … to which result did you come @dstefani ?
I’m asking this because I have exactly the same problem, and am still trying to find the solution.

Oh my goodness,… literally 2 minutes after this post, I figured out the cause by having a look at an example API by @akrabat.
The original code :

$container['FileServiceController'] = function ($container) {
        return new App\Controllers\FileService\FileServiceController($container['settings']['FileStoragePath']);
    };

The solution was to not add to container via string identifier, but to use the Class:class :

$container[App\Controllers\FileService\FileServiceController::class] = function ($container) {
        return new App\Controllers\FileService\FileServiceController($container['settings']['FileStoragePath']);
    };

Presumed you are using the Classname::class.’:method’ approach in your routes. It seems that whatever pattern you use in your routes, has to be used throughout the project, or more precisely the other way round.
At least that does work for now, but probably introduces other issues.