2016-04-25 17 views
5

Ich verwende Slim Framework 3, um eine API zu erstellen. Die App-Struktur lautet: MVCP (Model, View, Controller, Providers).Dependency Injection Slim Framework 3

Ist es möglich Slim Dependency Inject alle meine Klassen zu haben?

Ich verwende Composer, um alle meine Abhängigkeiten automatisch zu laden.

Meine Verzeichnisstruktur sieht wie folgt aus:

/app 
    - controllers/ 
    - Models/ 
    - services/ 
    index.php 
/vendor 
composer.json 

Hier ist meine composer.json Datei.

{ 
    "require": { 
    "slim/slim": "^3.3", 
    "monolog/monolog": "^1.19" 
    }, 
    "autoload" : { 
    "psr-4" : { 
     "Controllers\\" : "app/controllers/", 
     "Services\\" : "app/services/", 
     "Models\\" : "app/models/" 
    } 
    } 
} 

Hier ist meine index.php Datei.

<?php 

namespace Services; 

use Model\PeopleModel; 
use Model\AddressModel; 
use Model\AutoModel; 


class PeopleService 
{ 
    protected $peopleModel; 
    protected $autoModel; 
    protected $addressModel; 

    public function __construct(PeopleModel $peopleModel, AddressModel $addressModel, AutoModel $autoModel) 
    { 
     $this->addressModel = $addressModel; 
     $this->autoModel = $autoModel; 
     $this->peopleModel = $peopleModel; 
    } 

    public function getAllPeopleInfo() 
    { 
     $address = $this->addressModel->getAddress(); 
     $auto = $this->autoModel->getAutoMake(); 
     $person = $this->peopleModel->getPeople(); 

     return [ 
      $person[1], $address[1], $auto[1] 
     ]; 
    } 
} 

Models/AddressModels.php

<?php 

namespace Model; 

class AddressModel 
{ 

    public function __construct() 
    { 
     // do stuff 
    } 

    public function getAddress() 
    { 
     return [ 
      1 => '123 Maple Street', 
     ]; 
    } 
} 
: Auch hier sind die Abhängigkeiten durch die automatische Komponist

injiziert wird, wie diese
<?php 
use \Psr\Http\Message\ServerRequestInterface as Request; 
use \Psr\Http\Message\ResponseInterface as Response; 

require '../vendor/autoload.php'; 

$container = new \Slim\Container; 
$app = new \Slim\App($container); 

$app->get('/test/{name}', '\Controllers\PeopleController:getEveryone'); 

$app->run(); 

Mein Controller

<?php #controllers/PeopleController.php 

namespace Controllers; 

use \Psr\Http\Message\ServerRequestInterface as Request; 
use \Psr\Http\Message\ResponseInterface as Response; 


class PeopleController 
{ 
    protected $peopleService; 

    protected $ci; 
    protected $request; 
    protected $response; 

    public function __construct(Container $ci, PeopleService $peopleService) 
    { 
     $this->peopleService = $peopleService; 
     $this->ci = $ci; 
    } 

    public function getEveryone($request, $response) 
    { 
     die($request->getAttribute('name')); 

     return $this->peopleService->getAllPeoples(); 
    } 
} 

Meine PeopleService Datei sieht wie folgt aussieht

Models/AutoModel.php

namespace Model; 

class AutoModel 
{ 

    public function __construct() 
    { 
     // do stuff 
    } 

    public function getAutoMake() 
    { 
     return [ 
      1 => 'Honda' 
     ]; 
    } 
} 

Models/PeopleModel.php

<?php 
namespace Model; 

class PeopleModel 
{ 

    public function __construct() 
    { 
     // do stuff 
    } 

    public function getPeople() 
    { 
     return [ 
      1 => 'Bob' 
     ]; 
    } 

} 

ERROR Ich bin jetzt die folgende Fehlermeldung erhalten:

PHP Catchable fatal error: Argument 2 passed to Controllers\PeopleController::__construct() must be an instance of Services\PeopleService, none given, called in /var/www/vendor/slim/slim/Slim/CallableResolver.php on line 64 and defined in /var/www/app/controllers/PeopleController.php on line 21 

DIE FRAGE Wie Abhängigkeits ich alle meine cl injizieren Esel? Gibt es eine Möglichkeit, Slim DI Container automatisch dazu zu bringen, es zu tun?

+2

Sie möchten also injizieren oder sie automatisch laden? Wenn Sie Autoloading meinen, haben Sie wahrscheinlich vergessen, die Datei 'vendor/autoload.php' am Anfang von' index.php' einzufügen. Es enthält generierte Autoloader. –

+0

Nun, das war eines meiner Probleme. Danke! Ich habe den Index aktualisiert.PHP, um die PHP-Datei des Authorizon Autoload einzubinden. Ich habe die Frage aktualisiert, um den Fehler, den ich jetzt bekomme, einzuschließen. Auch hier ist das Problem, wie Dependency Inject meine Klassen. –

+0

Nun, der Fehler ist selbsterklärend. Was ist hier nicht klar? –

Antwort

4

Wenn Sie eine Klasse in der aufrufbaren Route Slim referenzieren, wird das DIC danach fragen. Wenn der DIC keine Registrierung für diesen Klassennamen besitzt, instanziiert er die Klasse selbst und übergibt den Container als einziges Argument an die Klasse.

, also die richtigen Abhängigkeiten für Ihren Controller zu injizieren, müssen Sie nur noch Ihre eigene DIC Fabrik erstellen:

$container = $app->getContainer(); 
$container['\Controllers\PeopleController'] = function ($c) { 
    $peopleService = $c->get('\Services\PeopleService'); 
    return new Controllers\PeopleController($c, $peopleService); 
}; 

Natürlich können Sie jetzt brauchen eine DIC Fabrik für die PeopleService:

$container['\Services\PeopleService'] = function ($c) { 
    $peopleModel = new Models\PeopleModel; 
    $addressModel = new Models\AddressModel; 
    $autoModel = new Models\AutoModel; 
    return new Services\PeopleService($peopleModel, $addressModel, $autoModel); 
}; 

(Wenn PeopleModel, AddressModel oder AutoModel Abhängigkeiten hatten, würden Sie auch DIC-Factories für diese erstellen.)

+0

benötigt Slim, dass Sie den Container an * jede * Klasse übergeben, die sie benötigt? Das scheint kein sehr trockener Ansatz zu sein. Ich bin es gewohnt mit CakePHP zu arbeiten und es scheint, als wären die Dinge "global" verfügbar, wenn man das benutzt (möglicherweise aufgrund des AppModels und AppControllers). Es scheint in Slim, dass Sie Dinge wie den Container jedes Mal weitergeben müssen, wenn Sie sie brauchen? Also, wenn ich 100 Klassen habe, muss ich Code verwenden, der dem entspricht, was Sie über 100 Mal setzen? – Andy

+0

Es liegt an dir. Es gibt nichts, was Sie daran hindert, eine globale statische Funktion zu erstellen, mit der Sie den Container erfassen können. Persönlich mag ich diese Ebene der Kopplung nicht, also tu es nicht so. –