2015-03-03 15 views
7

Pracuję nad pakietem dla Laravel 5, a teraz muszę skorzystać z wtrysku zależności, aby uzyskać bardziej skalowalną i możliwą do ponownego wykorzystania aplikację, nie wiem, które podejście najlepiej zrobić i dlaczego, to jest kawałek mojego kodu i muszę wstrzykuje zależność Lang klasyNajlepsze podejście do iniekcji Dependency w pakiecie Laravel 5

class MyController extends \App\Http\Controllers\Controller 
{   
    public $text; 
    public $lang; 

    public function __construct() 
    {   
     // Some codes here        
    } 

    public function myFunction(){ 
     $this->text = \Lang::get('package::all.text1');   
    } 
} 

W tym linkiem http://laravel.com/docs/4.2/ioc 2 podejście sugeruje, Basic Usage i Automatic Resolution na podstawie mojego zrozumienia z linkiem biorąc pierwszy podejście muszę dodać

App::bind('lang', function($app) 
{ 
    return new \Lang(); 
});  

do części rejestru aplikacji, a następnie w funkcji Muszę coś tak:

public function myFunction() 
{ 
    $lang = \App::make('lang');  
    $this->text = $lang::get('package::all.text1');   
} 

Innym sposobem jest modyfikacja constructor jak

public function __construct(Lang $lang) 
    {   
     $this->lang = $lang; 
    } 

A potem instancję obiekt z klasy podobnej do

$myController = App::make('MyController'); 

Która droga jest lepsza sposób, aby wziąć pod uwagę, biorąc pod uwagę, że ten class jest Controller i będzie on wywoływany w pliku routes, lub proszę mnie poprawić, jeśli moje zrozumienie z linku nie jest poprawne. proszę również poinformować mnie, dlaczego sugerujecie którekolwiek z tych podejść.

+2

Sugerowałbym biorąc go jako argument konstruktora chyba znaleźć się po wiele zależności zewnętrzne (lang , żądanie, uri, router, poczta itd.). Alternatywnie użyj nowego [method dependency injection] (http://laravel.com/docs/5.0/controllers#dependency-injection-and-controllers) (przewiń w dół), jeśli metoda, której używasz, jest faktycznym działaniem kontrolera . – alexrussell

+0

Wydaje się również, że Twój wpis nie zawiera właściwego linku, o którym wspomniałeś. – alexrussell

+0

@alexrussell właśnie zredagował pytanie i dodał link: – Siavosh

Odpowiedz

7

Należy zauważyć, że przy użyciu lokalnego rozdzielczość IoC ($app->make() stylee) nie jest dużo lepiej niż przy użyciu fasad bezpośrednio (Lang::get() stylee) - jesteś jeszcze bardzo dużo opierając się na konkretnych klas laravel bez naprawdę czyni Twój kod jednoznacznie stwierdzić, że potrzebuje tych dokładnych klas. Tak więc ogólną radą jest, w miarę możliwości, kodowanie do interfejsu, jeśli chcesz, aby twój kod był maksymalnie przenośny.

Oczywiście istnieje kilka dużych downsides to obecnie w rozwoju PHP:

  1. Interfejsy te nie są ogólnie zdefiniowane (z wyjątkiem interfejsu PSR-3LoggerInterface), więc wciąż muszą polegać na konkretnej instancji interfejs (w tym przypadku Laravel).
  2. Jeśli zdecydujesz się na stworzenie własnego ogólnego interfejsu (lub FIG w końcu tworzy niektóre z nich), klasy, które Laravel zapewnia do tłumaczenia (na przykład), nie implementują go mimo to, więc powinieneś podklasować istniejące tylko po to, aby wyglądało na to, że implementuje własny interfejs. Ale hej, to jest najlepsza praktyka, więc domyślam się, że jeśli chcesz używać obecnych najlepszych praktyk, koduj interfejs i nie przejmuj się, że interfejs, który kodujesz, jest specyficzny dla Laravel.

Ale w każdym razie, oto moje przemyślenia na temat konkretnego pytania. Po pierwsze powinienem powiedzieć, że jeszcze nie używałem Laravel 5 (tylko 4s), ale ogólnie śledziłem jego rozwój.

Jeśli klasa, której koduję, będzie używać pewnej zależności dość dużo lub jako główna część tego, jak klasa działa, użyję wtrysku zależnego od konstruktora. Przykładami są tutaj klasa Request lub niektóre repozytorium w kontrolerze lub klasa logiki biznesowej w klasie komend konsoli.

Jeśli to, czego potrzebuję, potrzebuję tylko do określonego celu (może przekierowanie z kontrolera i potrzebuję wygenerować URI) Rozwiążę wersję lokalną z kontenera IoC ($this->app->make()) i wtedy używam tego. Jeśli używałem Laravel 5 i metoda została wywołana bezpośrednio przez Laravel (np. Metoda działania kontrolera) I może użyć wtrysku metody, nie jestem w 100% pewny.

W końcowej nocie, ogólna rada jest taka, że ​​jeśli konstruktor metoda podpisów zbyt duża ze względu na dużą zależności:

  1. Nadszedł czas, aby przyjrzeć się, czy Twój kod opiera się zbytnio na zewnętrzny zależności. Może niektóre funkcje twojej klasy mogą zostać wyodrębnione do jej własnej klasy, która rozdzieli zależności między tymi dwoma.
  2. Powinieneś rozważyć użycie metod ustawiających zamiast wstrzykiwania konstruktora - tak więc zamiast akceptować obiekt żądania, masz metodę $class->setRequest(). Minusem tego jest to, że musisz powiedzieć kontenerowi IoC Laravel, jak utworzyć instancję obiektu (to znaczy, że te setery muszą zostać wywołane). To nie jest wielka sprawa, ale coś wartego uwagi.

Istotne linki:

+0

Dziękuję za odpowiedź, ponieważ w wielu przypadkach muszę używać "metod statycznych" i nie można uzyskać do nich dostępu za pomocą instancjonowanego obiektu klasy, jak na przykład w pytaniu: '\ App :: make ('lang');' don czy uważasz, że lepiej byłoby zastosować '($ app-> make() stylee), lub innymi słowy, wydaje się obowiązkowe – Siavosh

+0

Nie jestem pewien, o co pytasz, ale może warto mnie wskazać że wywoływanie fasad (jak 'Lang :: get()') jest równoważne rozwiązywaniu (właściwie * *) instancji z kontenera IoC przy użyciu '\ App :: make()' lub '$ app-> make() ', a następnie używając go jako instancji' $ lang-> get() ', jak fasady w Laravel, za kulisami, faktycznie tworzą instancję i działają jako klasy proxy. Tak więc proponuję, abyś wziął instancję 'Container' w swoim konstruktorze, aby reszta klasy mogła użyć' $ this-> app-> make() 'do rozstrzygnięcia instancji. – alexrussell

+0

Może nie było jasne w moim pytaniu, ale miałem na myśli to, że nie możemy tego mieć jako atrybutu klasy, na przykład w klasie 'MyClass' możemy mieć' $ Lang-> get() 'ale ten język nie może być atrybut klasy i nie może to być '$ this-> lang-> get()' – Siavosh

Powiązane problemy