CakePHP 3.x: загрузка компонентов на лету на контроллере

Я пытаюсь загрузить компонент на лету на контроллер. У компонента есть метод startup() и я знаю, что его нужно вызывать вручную, потому что компонент загружается в действие.

public function startup(\Cake\Event\Event $event) {
    //do something...
}

В контроллер:

$this->loadComponent('MyComponent');
$this->MyComponent->startup();

Однако это создает предупреждение, поскольку аргумент $event не передается. Как пройти?


person Mirko Pagliai    schedule 05.08.2016    source источник


Ответы (3)


Загрузить компонент на основе текущего действия

Для чего-то более простого и, возможно, менее подверженного ошибкам, вы можете захотеть загрузить компонент в метод контроллеров initialize() на основе текущего действия, т.е. что-то вроде

if ($this->request->param('action') === 'theAction') {
    $this->loadComponent('TheComponent');
}

Подделка событий контроллера

Лично я бы не рекомендовал делать это, но для полноты картины...

startup() — это обратный вызов для события Controller.startup. Вы можете легко подделать это событие, но это может быть не очень хорошей идеей, поскольку операции над событием не будут иметь такого же эффекта, как если бы это было реальное, реальное событие, инициированное контроллером Controller.startup. Видеть

\Cake\Controller\Controller:: процесс запуска()

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

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

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

$event = new \Cake\Event\Event('Controller.initialize', this);
$this->TheComponent->beforeFilter($event);
if ($event->result instanceof \Cake\Network\Response) {
    return $event->result;
}

$event = new \Cake\Event\Event('Controller.startup', this);
$this->TheComponent->startup($event);
if ($event->result instanceof \Cake\Network\Response) {
    return $event->result;
}
person ndm    schedule 09.08.2016
comment
Мой Бог. Поэтому я думаю, что лучше загрузить его в методе initialize() и забыть обо всем остальном. Спасибо @ndm, вы были очень ясны - person Mirko Pagliai; 09.08.2016

Попробуйте передать $this.

$this->MyComponent->startup($this);

Я думаю, что эта тема объясняет вашу проблему.

https://github.com/chronon/CakePHP-StripeComponent-Plugin/issues/4#issuecomment-30599742

person bill    schedule 05.08.2016
comment
Это для CakePHP 2.x - person ndm; 05.08.2016
comment
Нет, извини @bill, @ndm прав, $this — это экземпляр контроллера :-( - person Mirko Pagliai; 09.08.2016

Решение проходит $this. Спасибо.

Итак, в контроллер:

$this->loadComponent('MyComponent');
$this->MyComponent->startup($this);
person Mirko Pagliai    schedule 06.08.2016
comment
Я восстановил свой ответ, так как вы сказали, что это сработало для вас. - person bill; 06.08.2016
comment
С сигнатурой startup(\Cake\Event\Event $event) это не сработает (по крайней мере, без предупреждения), контроллер не является экземпляром/подклассом события. - person ndm; 07.08.2016
comment
@ndm прав, $this — это экземпляр контроллера :-( - person Mirko Pagliai; 09.08.2016
comment
Может быть, это? $this->MyComponent->startup(new \Cake\Event\Event(NULL)); - person Mirko Pagliai; 09.08.2016