2013-06-10 3 views
2

Моя команда любит идею зависимых от конструктора зависимостей, потому что она делает снимки очень ясными при взгляде на класс. С помощью фасадов я знаю, что их можно издеваться и swap педалей, но нужно было бы изучить каждую линию класса, чтобы выяснить, от чего это зависит! Я обнаружил, что могу найти истинный класс за фасадом, например, Form::getFacadeRoot().Как я могу создать зависимости от конструктора в Laravel 4?

код контроллера, который я закончил с это:

use Illuminate\Html\FormBuilder as Form; 
use Illuminate\Validation\Factory as Validator; 
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage as Session; 
use Illuminate\Http\Request as Input; 
use Illuminate\Routing\Redirector as Redirect; 
use Illuminate\View\Environment as View; 

class HomeController extends BaseController { 

    protected $form; 
    protected $validator; 
    protected $session; 
    protected $input; 
    protected $redirect; 
    protected $view; 

    protected $layout = 'layouts.master'; 

    protected $validationRules = array(
     'name' => array('required', 'min:3'), 
     'email' => array('required', 'regex:/^[email protected]+\..{2,4}$/') 
    ); 

    public function __construct(Form $form, Validator $validator, Session $session, 
     Input $input, Redirector $redirect, View $view 
    ) { 
     $this->form  = $form; 
     $this->validator = $validator; 
     $this->session = $session; 
     $this->input  = $input; 
     $this->redirect = $redirect; 
     $this->view  = $view; 
    } 

     ... 
} 

Когда мой тест делает $this->client->request('Get', '/');, оно ошибки вне:

Illuminate\Container\BindingResolutionException: Unresolvable dependency resolving [Parameter #2 [ <required> $csrfToken ]]. 

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

Спасибо!

ответ

7

Вам нужно сопоставить зависимости классов с классом, используя контейнер IoC Laravel. Это можно сделать, используя фасад приложения. Таким образом, в вашем примере выше с конструктором

public function __construct(Form $form, Validator $validator, Session $session, Input $input, Redirector $redirect, View $view) 

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

App::bind('Form', function(){ 
    return new Illuminate\Html\FormBuilder() 
}); 

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

Для контроллера:

use Namespace\For\FormInterface; 

class HomeController extends BaseController { 

    public function __construct(FormInterface $form) 
    { 
     $this->form = $form; 
    } 

    public function myHomePage() 
    { 
     $this->form->myFormFunction() 
    } 
} 

Для интерфейса:

namespace Namespace\For; 

interface FormInterface(){ 

    public function myFormFunction() 
} 

Класс, который будет введен:

use Namespace\For\FormInterface; 

class MyFormClass implements FormInterface{ 

    public function myFormFunction() 
    { 
     // Do some stuff here 
    } 
} 

И, наконец, вы создаете привязку, которая приносит все это вместе:

App::bind('Namespace\For\FormInterface', function() 
{ 
    return new MyFormClass(); 
}); 

Что происходит здесь, каждый раз, когда Laravel видит экземпляр типа FormInterface, намеченного в контроллере, если он создает новый myFormFunction() и передает его в качестве параметра. Используя интерфейсы, он дает вашим зависимостям классов контракт, чтобы следить за тем, чтобы их можно было легко поменять местами, не вызывая ошибок. Так говорит, что ваша команда позже разрабатывает новый и улучшенный класс формы вы бы просто обновить ваше связывание, как так:

App::bind('Namespace\For\FormInterface', function() 
{ 
    return new MyNewFormClass(); 
}); 

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

http://fideloper.com/laravel-4-where-to-put-bindings

И вы можете прочитать больше о IoC контейнера Laravel здесь:

http://laravel.com/docs/ioc

Кроме того, если вы можете получить на руки копию книги «От ученика к ремесленнику». Продвинутая архитектура приложений с Laravel 4, Taylor Otwell, я настоятельно рекомендую прочитать. Его легко следить и действительно подробно разбирается в управлении инъекцией зависимостей.

Надеюсь, что это поможет.

2

Я думаю, что вы собираетесь немного пожертвовать читабельностью, если вы выберете этот маршрут.

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