Database Connection with Container

I’ve been working through the slim3 application-tutorial and I can’t seem to get my db to connect using the DIC method.

Here’s my code:

require ‘composer/vendor/autoload.php’;

spl_autoload_register(function ($classname) {
    require ("./models/" . $classname . ".php");
});

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use Slim\Views\PhpRenderer;

$config['displayErrorDetails'] = true;
$config['addContentLengthHeader'] = false;

$config['db']['host']   = "127.0.0.1";
$config['db']['user']   = "root";
$config['db']['pass']   = "";
$config['db']['dbname'] = "assessment";

// Create the Slim application using our container.
$app = new \Slim\App(["settings" => $config]);

$container = $app->getContainer();

//database
$container['db'] = function($c){ 
    //setup NOTORM
    $db = $c['settings']['db'];
    $pdo = new PDO("mysql:host=" . $db['host'] . ";dbname=" . $db['dbname'], $db['user'], $db['pass']);
    $db = new NotORM($pdo);
    $db->debug = true;
    return $db;
};

$term = $app->db->term()[1];
echo '<pre>'; print_r($term['name']);
exit;

$app->db is equaling null ???

I haven’t explored that tutorial much myself, but within a route’s closure, you would typically access your database using something like $this->db since $this is bound to $app at that point.

yep, I realize that but that won’t work if my simple little script all on one page wont work.

Maybe start by testing your container?

if($app->has('db')) {
       return '$app has db';
    }

good thinking, tried it and it errors:

Fatal error: Uncaught exception 'BadMethodCallException' with message 'Method has is not a valid method' in C:\xampp\htdocs\assessment_admin\composer\vendor\slim\slim\Slim\App.php:129 Stack trace: #0 C:\xampp\htdocs\assessment_admin\index.php(31): Slim\App->__call('has', Array) #1 C:\xampp\htdocs\assessment_admin\index.php(31): Slim\App->has('db') #2 {main} thrown in C:\xampp\htdocs\assessment_admin\composer\vendor\slim\slim\Slim\App.php on line 129

Yeah, since there is no route it doesn’t know the method. I’d try it within a simple route closure.

You sir are a clever one indeed! That was the solution. But the reason I was trying to run $app out in the open was because I wanted to pass it to my main class right away. This way the child classes could inherit all the db settings, etc. later on.

So I typically do something like this near the start of my applications:
$m = new Main();
$m->set_app($app);

That’s not going to work with SLIM 3 I guess but I’m sure there’s a slim way to do it.

How does one make the slim DIC available to inherited classes?

Well, you can pass the container itself to your classes, then you have access to anything within the DIC from your classes. But this isn’t considered good practice as it becomes service location rather than dependency injection. For info on this, check out this comment and the reply for info about not going the service location way.

See the amazing @akrabat’s article on Accessing services in Slim 3 as well as the Slim docs on Container Resolution for a few different methods and some commentary.

So in summary, it isn’t really a great idea to make the DIC available to your classes. Pass the classes what they need from the container instead. :slight_smile:

Excellent resources @tflight … looks like I’ve got some studying to do. (after I digest all this info I’m sure I’ll have some more questions which I’ll post in another thread) Thanks again for all your timely and super helpful responses!