2016-01-17 17 views
14

Ho letto che in Slim v2, $ app era legata alla classe middleware. Sto trovando questo non essere il caso in v3? Qui di seguito è la mia classe middleware, ma sto solo l'undefined:

<?php 
namespace CrSrc\Middleware; 

class Auth 
{ 
    /** 
    * Example middleware invokable class 
    * 
    * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request 
    * @param \Psr\Http\Message\ResponseInterface  $response PSR7 response 
    * @param callable         $next  Next middleware 
    * 
    * @return \Psr\Http\Message\ResponseInterface 
    */ 
    public function __invoke($request, $response, $next) 
    { 
     // before 

var_dump($this->getContainer()); // method undefined 
var_dump($this->auth); exit; // method undefined 
     if (! $this->get('auth')->isAuthenticated()) { 
      // Not authenticated and must be authenticated to access this resource 
      return $response->withStatus(401); 
     } 

     // pass onto the next callable 
     $response = $next($request, $response); 

     // after 


     return $response; 
    } 
} 

Qual è il modo corretto per accedere al contenitore DI entro middleware? Immagino che dovrebbe esserci un modo?

risposta

21

un po 'tardi alla festa, ma potrebbe aiutare gli altri ... Bisogna iniettare il contenitore quando un'istanza del middleware

$container = $app->getContainer(); 
$app->add(new Auth($container)); 

E middleware ha bisogno di un costruttore

<?php 
namespace CrSrc\Middleware; 

class Auth 
{ 

    private $container; 

    public function __construct($container) { 
     $this->container = $container 
    } 

    /** 
    * Example middleware invokable class 
    * 
    * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request 
    * @param \Psr\Http\Message\ResponseInterface  $response PSR7 response 
    * @param callable         $next  Next middleware 
    * 
    * @return \Psr\Http\Message\ResponseInterface 
    */ 
    public function __invoke($request, $response, $next) 
    { 
     // $this->container has the DI 

    } 
} 

LE: Espandendo un po 'la risposta iniziale, il contenitore ottiene injected in the constructor se si fornisce il middleware come classe stringa

$app->add('Auth'); 

o

$app->add('Auth:similarToInvokeMethod') 
+0

Grazie. Penso che alla fine ho pensato che fosse la strada da percorrere nella v3. Sembra funzionare bene comunque. – Martyn

+0

Ottima risposta. Un sacco di persone che usano Slimphp cercano questa risposta, ma è nascosta dietro i cespugli noti come Iniezione delle dipendenze. Grazie! – user2800382

-1

Per quanto ho capito il codice, Slim (v3) funziona nel seguente modo:

  • se si passa una chiusura come middleware, allora chiama bindTo con contenitore come param.
  • se si passa una classe/string che si risolve in una classe, poi Slim crea l'istanza e passa il contenitore come param al costruttore

    <?php 
    $app->add(Auth); 
    
  • altrimenti (per esempio, se si aggiunge un'istanza middleware creato in precedenza) quindi sembra che tu debba occuparsi di passare tutti i riferimenti necessari.

+0

Questo è in parte corretto: 'bindTo' applica Chiusure quando passato come middleware, ma se si passa una classe non fornirà nulla nel costruttore –

+0

@ il- noob L'ho appena testato con Slim 3.0.0 e aggiungendo middleware usando l'istanza '$ app-> add (ClassName)' creata da 'ClassName' che fornisce il contenitore come primo parametro del costruttore. – Rafael

+0

ciò accade solo se si fornisce il middleware richiamabile come stringa. Andrà su [CallableResolver :: resolve] (https://github.com/slimphp/Slim/blob/3.x/Slim/CallableResolver.php#L51-L79) e tale metodo istanzia la tua classe. Immagino che l'affermazione sbagliata sia 'class/string' ... è davvero solo' stringa'. –