Laravel: Инъекция зависимости от фасадов?

То, что я делал ранее, было вводить только МОИ МОДЕЛИ, используя конструктор а также использовать Фасады для предоставленных классов Laravel то есть Session, Auth, Validator и т. д., например. Это будет хорошая идея, если я ввожу каждый класс (или мой или Laravel’s) через конструирование и использовать его $this->.. синтаксис или я должен вводить свои собственные классы с помощью конструктора и использовать Фасады для чего-либо, предоставленного 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('/');
}
...
}

8

Решение

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('/');
}
...
}

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

1

Другие решения

Изящно и полезно вводить определенные классы, такие как Запрос. По моему мнению, они должны быть указаны в методах контроллера там, где они необходимы, поскольку они затем логически связаны с реализацией метода. Круто пока.

Я нахожу два фасада проблематичными — App и Log. Ни логически не связаны с контроллером или его действиями. App и Log не являются входными данными ни в каком контексте. Так как 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');
}

}
0

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

0

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

use Auth;

а также

Auth::user()

сейчас просто

auth()->user()

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

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

0
По вопросам рекламы [email protected]