Intereting Posts
Как вставить репозиторий в службу в Symfony2? PHP: как я могу заблокировать прямой доступ к URL-адресу для файла, но все-таки разрешить его загрузку вошедшим в систему пользователям? TCPDF ERROR: некоторые данные уже выведены, не удается отправить файл PDF CodeIgniter: удаление 'index.php' из URL-адреса Вызов статического метода из класса B (который расширяет класс A) класса A PHP захват печати / требуется вывод в переменной объекты, бросающие исключения внутри объектов PHP – Как вы находите дубликаты групп значений в массиве Получить услугу запроса из класса DataTransformer Opencart: изменение макетов электронной почты SalesForce.com: получение настраиваемых полей через PHP Имена файлов с пробелами, возвращающими ошибку несоответствия подписи для подписанных URL-адресов в облачном хранилище Google Игнорирование предупреждений PHP в PHPUnit Системы на базе Debian Сессия убита через 30 минут в специальном cron, как переопределить? Как выполнить интеграционное тестирование в PHP?

Автоматическое разрешение Laravel ioc – работает от контроллера, но не от пользовательского класса

Пространства имен опущены для краткости …

Я написал следующий поставщик услуг и зарегистрирован в config / app.php:

class OfferServiceProvider extends ServiceProvider { public function register() { $this->registerLossControlManager(); } protected function registerLossControlManager() { $this->app->bind('LossControlInterface', 'LossControl'); } } 

Вот мой LossControlInterface

 interface LossControlInterface { /** * @param int $demandId * @param float $offerTotal * @param float $productTotal * @param null|int $partnerId * @return mixed */ public function make($demandId, $offerTotal, $productTotal, $partnerId = null); /** * @return float */ public function getAcceptableLoss(); /** * @return bool */ public function isAcceptable(); /** * @return bool */ public function isUnacceptable(); /** * @return null */ public function reject(); } 

Теперь в контроллере я могу ввести LossController следующим образом:

 use LossControlInterface as LossControl; class HomeController extends BaseController { public function __construct(LossControl $lossControl) { $this->lossControl = $lossControl; } public function getLossThresholds() { $lossControl = $this->lossControl->make(985, 1000, null); var_dump('Acceptable Loss: ' . $lossControl->getAcceptableLoss()); var_dump('Actual Loss: ' . $lossControl->calculateLoss()); var_dump('Acceptable? ' . $lossControl->isAcceptable()); } } 

Однако, если я пытаюсь зависеть, вставьте LossControlInterface из пользовательского класса, вызванного командой:

 [2014-09-02 13:09:52] development.ERROR: exception 'ErrorException' with message 'Argument 11 passed to Offer::__construct() must be an instance of LossControlInterface, none given, called in /home/vagrant/Code/.../ProcessOffer.php on line 44 and defined' in /home/vagrant/Code/.../Offer.php:79 

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

Любые мысли о том, что я делаю неправильно или не принимали автоматическое разрешение?

    IoC является автоматическим в контроллерах, и вы не видите инъекцию, потому что Laravel обрабатывает для вас конструкцию контроллеров. При создании любого другого пользовательского класса с помощью new ключевого слова вам все равно придется отправлять все параметры, необходимые для его конструктора:

     $myClass = new ClassWithDependency( app()->make('Dependency') ); 

    Вы можете скрыть это, в определенной степени, путем создания вашего пользовательского класса через поставщика услуг:

     // Your service provider public function register() { $this->app->bind('ClassWithDependency', function($app) { return new ClassWithDependency( $app->make('Dependency') ); }); } 

    Тогда просто сделайте IoC, когда вам это нужно:

     $myClass = app()->make('ClassWithDepenency'); 

    В вашем случае вы можете изменить свой код так, чтобы он выглядел следующим образом:

     private function setOffer(Offer $offer = null) { $this->processOffer = $offer ?: new Offer( app()->make('LossControlInterface') ); } 

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

     // Controller public function __construct(OfferFactory $offerFactory) { $this->offerFactory = $offerFactory; } public function setOffer(Offer $offer = null) { $this->processOffer = $offer ?: $this->offerFactory->createOffer(); } // OfferFactory class OfferFactory { public function createOffer() { return app()->make('Offer'); } } 

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

    В Laravel 5.2 самым простым решением для вашей конкретной проблемы было бы заменить

     new Offer(); 

    с

     App::make('Offer'); 

    или даже короче

     app('Offer'); 

    который будет использовать Laravel Container, чтобы заботиться о зависимостях.

    Если вы хотите передать дополнительные параметры в конструктор Offer , необходимо связать его с поставщиком услуг

     App::bind('Offer', function($app, $args) { return new Offer($app->make('LossControl'), $args); }); 

    И вуаля, теперь вы можете написать

     app('Offer', [123, 456]); 

    В laravel 5.4 ( https://github.com/laravel/framework/pull/18271 ) вам нужно использовать новый метод makeWith контейнера IoC.

     App::makeWith( 'App\MyNameSpace\MyClass', [ $id ] ); 

    если вы все еще используете 5.3 или ниже, приведенные выше ответы будут работать.