Laravel: Инъекция против фасций?

То, что я делал ранее, заключалось в том, чтобы вводить только MY MODELS с помощью конструктора и использовать, например, Facades для предоставленных Laravel классов, например Session , Auth , Validator т. Д. Будет ли это хорошей идеей, если я инжектирую каждый класс (или мой или Laravel's) через конструкцию и использую его с помощью синтаксиса $this->.. или я должен вводить свои собственные классы с использованием конструктора и использовать Facades для чего-либо, предоставленного Laravel?

Чтобы быть более конкретным, вот как обычно выглядят мои контроллеры:

 class MyController extends BaseController { public function __construct( User $user, Bookmark $bookmark ) { $this->user = $user; $this->bookmark = $bookmark } public function foobar ( ) { $user_id = Input::get('bar'); ... Session::get('someInfo'); ... return Redirect::to('/'); } ... } 

Должен ли я структурировать свои методы, такие как контроллер, например, следующим образом?

 class MyController extends BaseController { public function __construct( User $user, Bookmark $bookmark, Input $input, Session $session, Redirect $redirect ) { $this->user = $user; $this->bookmark = $bookmark $this->input = $input; $this->session = $session; $this->redirect = $redirect; } public function foobar ( ) { $user_id = $this->input->get('bar'); ... $this->session->get('someInfo'); ... return $this->redirect->to('/'); } ... } 

Laravel теперь поддерживает те же функции инъекций для методов классов (а не только для конструкторов), которые связаны с маршрутом, например контроллеры и промежуточное программное обеспечение.

Вы можете предотвратить ненужные инъекции, только введя методы, в которых зависимость уникальна, возможно, оставляя более общие зависимости в конструкторе:

 class MyController extends BaseController { public function __construct( Input $input, Session $session, Redirect $redirect ) { $this->input = $input; $this->session = $session; $this->redirect = $redirect; } public function foobar ( User $user, Bookmark $bookmark ) { $user_id = $this->input->get('bar'); ... $this->session->get('someInfo'); ... return $this->redirect->to('/'); } ... } 

Что касается того, следует ли вам это делать, это зависит от вас – заставить все зависимости появляться в определениях методов кажется более чистым для меня, и проще провести единичный тест.

Элегантно и полезно вводить определенные классы, такие как Request. По-моему, они должны быть указаны в методах контроллера, где они необходимы, поскольку они затем логически связаны с реализацией метода. Удивительно до сих пор.

Я считаю, что два фасада являются проблемными – App и Log. Ни один из них не логически связан с контроллером или его действиями. Приложение и журнал не являются входами в любом контексте. Поскольку приложения и журналы являются служебными классами, они также имеют отношение к службам и репозиториям, и это становится совершенно неприятным, если вы набираете намеки на них в контроллерах, а затем передаете их в качестве параметров конструктора или метода для своих классов поддержки.

Дополнительная проблема заключается в том, что фасад приложения не реализует интерфейс Illuminate \ Contracts \ Auth \ Guard, который он проксирует, поэтому моя IDE загорается с предупреждениями, поскольку статический анализ невозможен.

Для согласованности и общего разделения проблем я бы поэтому создавал экземпляр как App, так и Log в конструкторе или методе, в зависимости от того, насколько широко они используются в классе. Чтобы сделать мою среду IDE счастливой, я создал класс ниже, чтобы дать мне правильно типизированный экземпляр, где бы он мне ни понадобился:

 <?php namespace App\Components; use Illuminate\Contracts\Auth\Guard; use Psr\Log\LoggerInterface; /** * Get the underlying object instances of facades from the container. */ class AppGlobal { /** * Returns the global logger instance. * * @return LoggerInterface */ public static function log() { return app('log'); } /** * Returns the global auth instance, which internally proxies a guard. * * @return Guard */ public static function auth() { return app('auth'); } } 

Если вам нужны свойства объекта wit – введите его как инъекцию (например, Input, Session …), в противном случае, если вы не храните никаких данных в объекте и не будете довольны использованием класса, чем используйте фасады (например, Log :: …, Redirect :: …).

Например, Laravel заменил многие из его фасадов помощниками

 use Auth; 

а также

 Auth::user() 

теперь просто

 auth()->user() 

это упрощает и упрощает (также предотвращает ошибки)

Я бы предложил использовать помощники, где это возможно, и если не существует помощника, используйте фасад, потому что его легче высмеивать, чем инъецируемый экземпляр.