Laravel — использование $app вместо фасадов

Просматривая исходный код на Github, я заметил, что некоторые пакеты используют для доступа к IOC сам контейнер приложения, а не фасады. Зачем вам использовать что-то подобное...

$app = app();
$user = $app['db']->connection()->table('users')->where('name', '=', 'Foo')->first();

...вместо этого?

$user = User::where('name', '=', 'Foo')->first();

person searsaw    schedule 03.12.2013    source источник


Ответы (2)


Мотив 1

Некоторые пакеты должны.

Обычно вы увидите, как ServiceProviders используют его следующим образом:

$this->app['db']

Или внутри привязки закрытия:

$this->app->bindShared('anything', function($app)
{
    return new DatabaseClass($app['db']->connection());
});

Потому что $app является свойством Illuminate\Support\ServiceProvider, а ServiceProviders — это ребята, которые загружают сервисы, которые будут использоваться Facades в вашем приложении.

Итак, сначала Laravel создаст экземпляр и загрузит всех ServiceProviders, которые предоставляют службу, связанную с IoC, например:

$this->app->bindShared('db', function($app)
{
    return new DatabaseManager($app, $app['db.factory']);
});

И после этого конкретного звонка у вас есть доступ к Фасаду:

DB::table(...);

До этого вы получаете сообщение об ошибке, сообщающее вам, что нет привязки «db».

И я должен подчеркнуть, что вы в основном увидите, что это используется в ServiceProviders таким образом, потому что замыкание предоставляет переменную $app, чтобы использовать его таким образом:

$app['db']->connection()...

Конечно, любой может получить привязку IoC для приложения и установить для нее переменную $app...

Мотив 2

Некоторые другие могут злоупотреблять этим, чтобы не сломать свои пакеты. Полагаться на псевдоним, чтобы ваш пакет работал, опасно, потому что, если пользователь изменит этот псевдоним, пакет может сломаться. Это может быть проблемой пользователя, но это также создаст для них некоторые проблемы, например, проблемы на Github.

person Antonio Carlos Ribeiro    schedule 04.12.2013
comment
Антонио Карлос Рибейро, вы бы использовали Fascades при создании пакета или $app? Как в контроллерах и командах? - person searsaw; 04.12.2013
comment
При создании пакета я бы использовал $app в ServiceProvider, а также создал бы для него Фасад. Фасады — это фантастический и красивый способ облегчить доступ к вашему пакету, но это всего лишь ярлык, поэтому пользователям не нужно создавать их экземпляры все время. - person Antonio Carlos Ribeiro; 04.12.2013

Просто чтобы добавить что-то к этому ответу.

Существует больше типов псевдонимов, через которые провайдеры могут быть разрешены вне IoC:

  • Псевдонимы Ahort, привязанные непосредственно к контейнеру (этот список можно найти в файле Illuminate\Foundation\Application.php). Например, $app["db"]

    Псевдонимы, которые фасады используют для «статического» доступа (этот список можно найти в файле app/config/app.php, например View::make("index");

    И вы можете выполнить привязку с помощью метода AliasLoader::getInstance().

Это сбивало меня с толку, потому что имена некоторых статических псевдонимов отличаются от их коротких имен провайдеров. Например, Eloquent указывает на модель, а средство доступа к фасаду Route — router (не route). Или конфигурация, которая не привязана к IoC через поставщика услуг — она указывает на класс Repository в файле Application.php. Таким образом, эти простые шаблоны предлагают нам большую гибкость.

person Miroslav Trninic    schedule 07.02.2014