Я не могу понять суть системы привязки Laravel. Я знаю, что означает внедрение зависимостей. И он может работать даже без этих странных «привязок», правда? Я видел в документации, что привязка может возвращать новый объект. Почему и когда я должен это использовать? Объясните, пожалуйста, не очень сложно, потому что я читал документацию и не мог понять использование и назначение этих привязок. Спасибо.






And it can work even without that weird "bindings", right?
Не совсем. Конечно, он может работать нормально, если требуемые зависимости легко создать. Допустим, у вас есть этот простой класс Foo, хранящийся в каталоге app:
<?php
namespace App;
class Foo
{
public function hello()
{
return 'Hello World';
}
}
Вы можете ввести этот класс с подсказкой, не привязывая его сначала к контейнеру. Laravel по-прежнему сможет разрешить этот класс. Допустим, вы напечатали это в маршрутах следующим образом:
Route::get('/foo', function (App\Foo $foo) {
return $foo->hello(); // Hello World
});
Мы можем пойти даже дальше, допустим, для этого класса Foo требуется еще один простой класс Bar. Наш класс Bar выглядит так:
<?php
namespace App;
class Bar
{
public function hello()
{
return 'bar';
}
}
А наш класс Foo теперь выглядит так:
<?php
namespace App;
class Foo
{
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
public function hello()
{
return $this->bar->hello();
}
}
Сможет ли Laravel разрешить класс Foo с типовой подсказкой? ДА! Laravel по-прежнему сможет разрешить этот класс Foo.
Теперь проблема возникнет, когда нашему классу Foo потребуются более сложные зависимости, которые необходимо настроить. Представьте, что нашему классу Foo просто нужно имя нашего приложения. Конечно, вы можете просто использовать config('app.name') в методе класса, но представьте, что это может быть HTTP-клиент, которому требуется массив конфигурации для создания экземпляра.
<?php
namespace App;
class Foo
{
public function __construct($appName)
{
$this->appName = $appName;
}
public function hello()
{
return "Hello {$this->appName}";
}
}
Сможет ли Laravel решить этот класс сейчас? НЕА. Сервисный контейнер спешит на помощь! Вы можете научить Laravel разрешать этот класс Foo, привязав его к сервисному контейнеру. Вы можете определить привязку в методе register для файла app\Providers\AppServiceProvider.php:
public function register()
{
$this->app->bind(\App\Foo::class, function ($app) {
// Pass the application name
return new \App\Foo($app->config['app.name']);
});
}
А иногда вам не нужно создавать несколько экземпляров. Как, например, наш класс Foo, нет необходимости в нескольких экземплярах для этого типа класса. В этом случае мы можем привязать его с помощью одноэлементного метода.
$this->app->singleton(\App\Foo::class, function ($app) {
return new \App\Foo($app->config['app.name']);
});
Более важное использование
Но более важное использование этого сервисного контейнера заключается в том, что мы можем привязать интерфейс к его реализации. Допустим, у нас есть PaymentProcessorInterface с методом pay:
<?php
namespace App;
interface PaymentProcessorInterface
{
public function pay();
}
Затем у нас есть реализация этого интерфейса с именем StripeProcessor:
<?php
namespace App;
class StripeProcessor implements PaymentProcessorInterface
{
public function pay()
{
return 'pay with stripe';
}
}
С помощью сервисного контейнера мы можем привязать PaymentProcessorInterface к классу StripeProcessor:
$this->app->bind(\App\PaymentProcessorInterface::class, function () {
return new \App\StripeProcessor();
});
Затем мы можем ввести PaymentProcessorInterface в нашем коде:
Route::get('/pay', function (App\PaymentProcessorInterface $paymentProcessor) {
return $paymentProcessor->pay(); // pay with stripe
});
Таким образом, мы можем легко поменять местами реализацию PaymentProcessorInterface. Допустим, мы хотим изменить платежный процессор на Paypal, тогда у нас есть этот класс PaypalProcessor.
<?php
namespace App;
class PaypalProcessor implements PaymentProcessorInterface
{
public function pay()
{
return 'pay with paypal';
}
}
Все, что нам нужно сделать, это обновить привязку:
$this->app->bind(\App\PaymentProcessorInterface::class, function () {
return new \App\PaypalProcessor();
});
Надеюсь, это даст вам некоторые идеи.
Большое спасибо за подробный урок :)
Официальную документацию должны писать такие люди, как вы. Блестяще!
Идеальный хлопок в ладоши :)
Отлично, отлично!
прочтите это heera.it/laravel-repository-pattern#.VuJcVfl97cs