2013-04-02 2 views
4

Я копал в ядре Laravel, потому что хотел бы понять, как это работает. Но я придумал метод, который я просто не могу окутать в голову даже через 3 дня. В start.php приложение привязывается к самому себе. Все идет нормально. Но когда я проверяю метод $ app-> share, я теряюсь.Laravel core method confusion

public function share(Closure $closure) 
{ 
    return function($container) use ($closure) 
    { 

     // We'll simply declare a static variable within the Closures and if 
     // it has not been set we'll execute the given Closure to resolve 
     // the value and return it back to the consumers of the method. 
     static $object; 
     if (is_null($object)) 
     { 
      $object = $closure($container); 
     } 

     return $object; 
    }; 
} 

Этот метод возвращает анонимную функцию, которая при выполнении возвращает экземпляр приложения. Правильно ли я это вижу? Почему это? Почему вы хотите вернуть закрытие, а не только экземпляр. Это кажется странным, но я совершенно уверен, что есть причина;) ??

UPDATE Строка в start.php:

$app['app'] = $app->share(function($app) { return $app; }); 

Так что я думаю, что $ приложение [ 'приложение'] является объектом закрытия. Однако, если я делаю get_class, класс Illuminate \ Foundation \ Application. Кроме того, нет возможности выполнить его, так как $ app'app 'не будет работать явно.

+0

Это, кажется, комбинация шаблонов проектирования Singleton и Inversion of Control (IoC). Конечно, это для расширяемости, но я не уверен, почему он был построен именно так. –

ответ

3

$app нет нормального массива, это на самом деле является экземпляром Illuminate\Foundation\Application1, расширение Illuminate\Container\Container2, который реализует ArrayAccess. Но вы уже знаете это, так как там живет метод share().

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

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

Почему приложение не зарегистрировано в контейнере с использованием instance() Я не знаю, хотя - возможно, он производит рекурсивные ссылки в выводе trace и dump.

+0

Спасибо большое !. Действительно хороший ответ. Когда я прочитал это, я понял, что я близок с моей теорией, но ваш ответ определенно дал ей ясность! – driechel