Предположим, что наша онлайн программа должна выполнять комплекс математических действий в различных частях приложения. Мы можем создать компонент, который позволит использовать наш код в разных контроллерах.
Первый шаг – это создать новый файл и класс компонента. Создадим файл в /app/controllers/components/math.php. Базовая структура для компонента будет выглядеть примерно так:
<?php
class MathComponent extends Object {
function doComplexOperation($amount1, $amount2) {
return $amount1 + $amount2;
}
}
?>
После того, как наш компонент создан, мы можем использовать его в контроллерах приложения, разместив имя компонента (без слова Component) в массив контроллера $components.
<?php
/* Сделайте новый компонент доступным через $this->Math,
так же как и стандартный $this->Session */
var $components = array('Math', 'Session');
?>
Компоненты, определенные в AppController, будут доступны в других контроллерах. Так что, нет необходимости переопределять один и тот же компонент дважды.
Когда подключаете компоненты в контроллер, вы также можете определить множество параметров, которые будут передаваться в метод компонента initialize(). Эти параметры в дальнейшем могут использоваться компонентом.
<?
var $components = array(
'Math' => array(
'precision' => 2,
'randomGenerator' => 'srand'
),
'Session', 'Auth'
);
?>
Код, приведенный выше, передаст массив, содержащий precision и randomGenerator в метод initialize() компонента MathComponent вторым параметром.
Для получения доступа к экземпляру контроллера с помощью созданного компонента, вам необходимо использовать метод initialize() или startup(). Эти специальные функции принимают ссылку к контроллеру в качестве своего первого параметра и автоматически вызываются. Метод initialize() вызывается перед методом контроллера beforeFilter(), а startup() метод – после beforeFilter(). Если, по каким-то причинам, вы не хотите, чтобы startup() метод вызывался, то присвойте переменной класса $disableStartup значение true.
Если вы хотите вставить какой-то код перед тем, как beforeFilter() вызовется, вам необходимо использовать метод компонента initialize().
<?php
class CheckComponent extends Object {
//вызывается перед Controller::beforeFilter()
function initialize(&$controller) {
// сохранение ссылки на контроллер для последующего использования
$this->controller =& $controller;
}
//вызывается после Controller::beforeFilter()
function startup(&$controller) {
}
function redirectSomewhere($value) {
// вызов метода контроллера
$this->controller->redirect($value);
}
}
?>
Вы можете захотеть использовать другие компоненты внутри вашего компонента. Для этого создайте переменную класса $components в виде массива, который содержит имена нужных вам компонентов.
Только метод initialize вызывается автоматически для вложенных компонентов!
<?php
class MyComponent extends Object {
// Этот компонент использует другие компоненты
var $components = array('Session', 'Math');
function doStuff() {
$result = $this->Math->doComplexOperation(1, 2);
$this->Session->write('stuff', $result);
}
}
?>
Использовать модели в компонентах, в общем случае, не рекомендуется; однако, если после взвешивания всех возможностей, вы захотите это сделать, то вам необходимо инициализировать класс модели в какую-либо переменную и использовать ее.
Вот пример:
<?php
class MathComponent extends Object {
function doComplexOperation($amount1, $amount2) {
return $amount1 + $amount2;
}
function doUberComplexOperation ($amount1, $amount2) {
$userInstance = ClassRegistry::init('User');
$totalUsers = $userInstance->find('count');
return ($amount1 + $amount2) / $totalUsers;
}
}
?>
Иногда один из ваших компонентов может зависеть от другого. Если функциональность этих компонентов не связана иначе, кроме этой зависимости, то вы не захотите объединить их в один компонент. Вместо этого вы можете сделать ваш компонент родителем, создав массив $components со списком потомков. Компоненты-родители загружаются перед их потомками и у потомков есть доступ к родителям.
Родитель:
<?php
class ParentComponent extends Object {
var $name = "Parent";
var $components = array( "Child" );
function initialize(&$controller) {
$this->Child->foo();
}
function bar() {
// ...
}
}
Потомок:
<?php
class ChildComponent extends Object {
var $name = "Child";
function initialize(&$controller) {
$this->Parent->bar();
}
function foo() {
// ...
}
}