Компоненты представляют собой пакеты логики, которые совместно используются контроллерами. CakePHP поставляется с фантастическим набором основных компонентов, которые вы можете использовать для различных общих задач. Вы также можете создавать свои собственные компоненты. Если у вас есть одинаковые участки кода, которые нужно скопировать и вставить в разные контроллеры, то, вы должны подумать над созданием своего собственного компонента для обеспечения этой функциональности. Создание компонента сохраняет код контроллера чистым и позволяет повторно использовать код в разных контроллерах.
Для получения дополнительной информации о компонентах, включенных в CakePHP, посмотрите главы для каждого компонента:
Многие из основных компонентов требуют конфигурации. Вот некоторые примеры компонентов
требующие конфигурации Аутентификация и
Куки. Конфигурация для этих компонентов,
и для компонентов в целом обычно выполняется с помощью loadComponent()
в
методе initialize()
вашего контроллера или в массиве $components
:
class PostsController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'authorize' => 'Controller',
'loginAction' => ['controller' => 'Users', 'action' => 'login']
]);
$this->loadComponent('Cookie', ['expires' => '1 day']);
}
}
Вы можете настроить компоненты во время выполнения с помощью метода config()
. Часто,
это делается в методе beforeFilter()
вашего контроллера. Вышеизложенное может
выражаться так:
public function beforeFilter(Event $event)
{
$this->Auth->config('authorize', ['controller']);
$this->Auth->config('loginAction', ['controller' => 'Users', 'action' => 'login']);
$this->Cookie->config('name', 'CookieMonster');
}
Как и помощники(хелперы), компоненты реализуют метод config()
, который используется для установики и
получения любых данных конфигурации для компонента:
// Чтение данных конфигурации.
$this->Auth->config('loginAction');
// Установка конфигурации
$this->Csrf->config('cookieName', 'token');
Как и с помощниками, компоненты автоматически объединяют своё свойство $_defaultConfig
с конфигурацией конструктора для создания свойства $_config
,
которое доступно с помощью метода config()
.
Одной из общих настроек для использования является опция className
, которая позволяет вам
использовать псевдонимы. Эта функция полезна, если вы хотите заменить $this->Auth
или другую общую ссылку
на компонент - своей пользовательской реализацией:
// src/Controller/PostsController.php
class PostsController extends AppController
{
public function initialize()
{
$this->loadComponent('Auth', [
'className' => 'MyAuth'
]);
}
}
// src/Controller/Component/MyAuthComponent.php
use Cake\Controller\Component\AuthComponent;
class MyAuthComponent extends AuthComponent
{
// Добавьте сюда свой код для переопределения ядра AuthComponent
}
Вышеупомянутый псевдоним MyAuthComponent
для $this->Auth
бедет доступен во всех ваших
контроллерах.
Примечание
Псевдоним компонента заменяет этот экземпляр в любом месте этого компонента, включая другие компоненты.
Возможно, вам не нужно, чтобы все ваши компоненты, были доступны во всех методах(экшенах)
контроллера. В таких ситуациях вы можете загрузить компонент во время выполнения, используя
метод loadComponent()
в вашем контроллере:
// В определённом методе контроллера
$this->loadComponent('OneTimer');
$time = $this->OneTimer->getTime();
Примечание
Имейте в виду, что компоненты, загруженные «на лету», не будут пропущены через обратные вызовы. Если вы нуждаетесь в обратных вызовах (колбэках) beforeFilter
или startup
, вам может потребоваться вызвать их вручную, в зависимости от того, когда вы загружаете свой компонент.
После того, как вы подключили некоторые компоненты в свой контроллер, использование их довольно
просто. Каждый компонент, который вы используете, отображается как свойство в вашем контроллере. Если
вы загрузили Cake\Controller\Component\FlashComponent
в вашем контроллере, вы можете получить доступ к нему следующим образом:
class PostsController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('Flash');
}
public function delete()
{
if ($this->Post->delete($this->request->getData('Post.id')) {
$this->Flash->success('Post deleted.');
return $this->redirect(['action' => 'index']);
}
}
Примечание
Поскольку как модель, так и компонент добавляются к контроллерам как свойства и имеют одно и то же „namespace“ (пространство имён), важно не дать компоненту и модели одинаковое имя.
Предположим, что нашему приложению необходимо выполнить сложную и одинаковую математическую операцию во многих разных частях приложения. Мы можем создать компонент для размещения этой общей логики для использования во многих разных контроллерах.
Первый шаг - создать новый компонентный файл и класс. Создайте файл в src/Controller/Component/MathComponent.php. Основная структура компонента будет выглядеть примерно так:
namespace App\Controller\Component;
use Cake\Controller\Component;
class MathComponent extends Component
{
public function doComplexOperation($amount1, $amount2)
{
return $amount1 + $amount2;
}
}
Примечание
Все компоненты должны размещаться в Cake\Controller\Component
.
Ошибка размещения компонента вызовет исключение.
Как только ваш компонент будет закончен, вы сможем использовать его в
контроллерах, загрузив его в методе initialize()
.
После загрузки контроллеру будет присвоен новый атрибут, названный в честь
компонента, через который мы можем получить доступ к его экземпляру:
// В контроллере
// Создаем новый компонент в $this->Math,
// а также стандартный $this->Csrf
public function initialize()
{
parent::initialize();
$this->loadComponent('Math');
$this->loadComponent('Csrf');
}
При включении компонентов в контроллер, вы также можете объявить набор параметров, которые будут переданы компоненту конструктором. Эти параметры затем могут обрабатываться компонентом:
// В вашем контроллере
public function initialize()
{
parent::initialize();
$this->loadComponent('Math', [
'precision' => 2,
'randomGenerator' => 'srand'
]);
$this->loadComponent('Csrf');
}
Вышеизложенное передало бы массив, содержащий точность и randomGenerator в
метод MathComponent::initialize()
, в параметре $config
.
Иногда, одному из ваших компонентов может понадобиться использование другого компонента.
В этом случае вы можете включить другие компоненты в свой компонент точно так же, как
вы включаете их в контроллеры - с помощью переменной $components
:
// src/Controller/Component/CustomComponent.php
namespace App\Controller\Component;
use Cake\Controller\Component;
class CustomComponent extends Component
{
// Другой компонент, используемый вашим компонентом
public $components = ['Existing'];
// Выполните любую другую дополнительную настройку для своего компонента.
public function initialize(array $config)
{
$this->Existing->foo();
}
public function bar()
{
// ...
}
}
// src/Controller/Component/ExistingComponent.php
namespace App\Controller\Component;
use Cake\Controller\Component;
class ExistingComponent extends Component
{
public function foo()
{
// ...
}
}
Примечание
В отличие от компонента, включенного в контроллер, никакие обратные вызовы не будут инициированы на компоненте компонента.
Внутри компонента вы можете получить доступ к текущему контроллеру через „реестр“:
$controller = $this->_registry->getController();
Вы можете получить доступ к контроллеру в любом методе обратного вызова из события объекта:
$controller = $event->getSubject();
Компоненты также предлагают несколько обратных вызовов жизненного цикла запроса, которые позволяют им увеличить цикл запроса.
beforeFilter
(Event $event)¶Вызывается перед методом beforeFilter() контроллеров, но после метода initialize().
startup
(Event $event)¶Вызывается после метода beforeFilter() контроллеров, но до того, как контроллер выполнит текущее действие обработчика.
beforeRender
(Event $event)¶Вызывается после того, как контроллер выполняет логику запрошенного действия, но до того, как контроллер отобразит представления и макет.
shutdown
(Event $event)¶Вызывается до вывода в браузер.
beforeRedirect
(Event $event, $url, Response $response)¶Вызывается когда методом контроллера осуществляет перенаправление, но перед любым
дальнейшим действием. Если этот метод возвращает false
, контроллер не будет
продолжать перенаправлять запрос. Параметры $url и $response позволяют вам проверять
и изменять местоположение или любые другие заголовки в ответе.