Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access app in class in Slim Framework 3

Im having trouble understanding how to access the instance of Slim when a route is in a seperate class than index.php

When using Slim Framework 2 I always used the following, but its not working in Slim 3:

$this->app = \Slim\Slim::getInstance();

Im trying to access a database connection I have setup in the container, but from a separate class. This is what I currently got in my index.php to initiate a Slim app:

require_once("rdb/rdb.php");
$conn = r\connect('localhost');
$container = new \Slim\Container;
$container['rdb'] = function ($c){return $conn;}
$app = new \Slim\App($container);

And here is my route:

$app->get('/test','\mycontroller:test');

And this is what I got in my mycontroller.php class which my route points to, which obviously is not working as $this->app doesn't exist:

class mycontroller{
public function test($request,$response){
$this->app->getContainer()->get('rdb');
}

The error message is the following, due to getinstance not being part of Slim 3 compared to Slim 2:

Call to undefined method Slim\App::getInstance() 

Grateful for any help,

Regards Dan

like image 416
user3507740 Avatar asked Sep 03 '15 00:09

user3507740


2 Answers

Have a look at the Slim 3 Skeleton created by Rob Allen.

Slim 3 heavily uses dependency injection, so you might want to use it too.

In your dependencies.php add something like:

$container = $app->getContainer();

$container['rdb'] = function ($c) {
    return $conn;
};

$container['Your\Custom\Class'] = function ($c) {
    return new \Your\Custom\Class($c['rdb']);
};

And in your Your\Custom\Class.php:

class Class {
    private $rdb;
    function __construct($rdb) {
        $this->rdb = $rdb;
    }

    public function test($request, $response, $args) {
        $this->rdb->doSomething();
    }
}

I hope this helps, if you have any more questions feel free to ask.

Update:

When you define your route like this

$app->get('/test', '\mycontroller:test');

Slim looks up \mycontroller:test in your container:

$container['\mycontroller'] = function($c) {
    return new \mycontroller($c['rdb']);
}

So when you open www.example.com/test in your browser, Slim automatically creates a new instance of \mycontroller and executes the method test with the arguments $request, $response and $args. And because you accept the database connection as an argument for the constructor of your mycontroller class, you can use it in the method as well :)

like image 97
Martin Avatar answered Sep 27 '22 00:09

Martin


With Slim 3 RC2 and onwards given a route of:

$app->get('/test','MyController:test');

The CallableResolver will look for a key in the DIC called 'MyController' and expect that to return the controller, so you can register with the DIC like this:

// Register controller with DIC
$container = $app->getContainer();
$container['MyController'] = function ($c) {
    return new MyController($c->get('rdb'));   
}

// Define controller as:
class MyController
{
    public function __construct($rdb) {
        $this->rdb = $rdb;
    }

    public function test($request,$response){
        // do something with $this->rdb
    }
}

Alternatively, if you don't register with the DIC, then the CallableResolver will pass the container to your constructor, so you can just create a controller like this:

class MyController
{
    public function __construct($container) {
        $this->rdb = $container->get('rdb');
    }

    public function test($request,$response){
        // do something with $this->rdb
    }
}
like image 42
Rob Allen Avatar answered Sep 26 '22 00:09

Rob Allen