3

How to get access to $app inside a controller as the Slim 3.3 injects only the ContainerInterface?

Code to illustrate the question:

$app = new \Slim\App;

$app->get('/home', 'HomeController:get');

$app->run();

class HomeController {
    private $ci;

    public function _construct($ci) {
        $this->ci = $ci;
    }

    public function get($request, $response) {
        $this->ci->get(...);
        // How to access $app and dependencies like $app->jwt?
    }
}
Max Bündchen
  • 1,283
  • 17
  • 38
  • What's your Slim version? `\Slim\Slim::getInstance();` an option? – ficuscr Apr 01 '16 at 20:15
  • Just use `global` I think is the DI pattern ;) Naw, read this one? http://stackoverflow.com/questions/32365258/access-app-in-class-in-slim-framework-3 – ficuscr Apr 01 '16 at 20:17
  • @ficuscr I added the information to the post. I'm using the version 3.3 so the getInstance deprecated. – Max Bündchen Apr 01 '16 at 20:24
  • @ficuscr The $app object injection using the container generates an exception 'Slim Application Error'. Otherwise it's a nice one! – Max Bündchen Apr 01 '16 at 20:32
  • 1
    @MaxBündchen you don't need to ever get the $app instance. There is nothing on the $app instance anymore everything is stored in the container which is why we inject it. – geggleto Apr 06 '16 at 12:25
  • @geggleto I see some extensions that inject into $app objects like jwt for json web token authentication. I inject the relevant information in the container from the original $app->jwt so I don't need the app as you said (that make much more sense and are much more test friendly), but I got curious about this problem. – Max Bündchen Apr 06 '16 at 12:51
  • 1
    @MaxBündchen this is a common pattern in Slim v2... It's super easy to confuse v2 with v3. The dead giveaway is the $app object is Slim\Slim in v2 and Slim\App in v3. Service location via injecting into the $app is the classic pattern for v2. Dependency Injection is the pattern for v3. – geggleto Apr 06 '16 at 13:03

2 Answers2

1

This was a tough one.

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

First inside your dependencies.php you need to grab the $app and throw it in a container to inject it to the Controller later.

$container['slim'] = function ($c) {
   global $app;
   return $app;
};

Then you got to inject it:

// Generic Controller
$container['App\Controllers\_Controller'] = function ($c) {
    return new _Controller($c->get('slim'));
};

Now on your controller.php:

private $slim;

/**
     * @param \Psr\Log\LoggerInterface       $logger
     * @param \App\DataAccess                $dataaccess
     * @param \App\$app                      $slim
     */
    public function __construct(LoggerInterface $logger, _DataAccess $dataaccess, $slim)
    {       
        $this->logger = $logger;
        $this->dataaccess = $dataaccess;
        $this->slim = $slim;
    }

Now you just got call it like this:

$this->slim->doSomething();
Leo Leao
  • 161
  • 1
  • 5
0

You can make your own 'singleton' to mimic Slim::getInstance(); ;)

class Anorexic extends \Slim\App {
    private static $_instance;
    public static function getInstance(){
        if(empty(self::$_instance){
            self::$_instance = new self();
        }
        return self::$_instance;
    }
}

Then change your initialization like this:

// $app = new \Slim\App;
$app = Anorexic::getInstance();

Now you can get your \Slim\App instance anywhere in your code by calling Anorexic::getInstance(); Ofcourse you should never try this at home :P

brense
  • 272
  • 3
  • 5