Предположим, что наша онлайн программа должна выполнять комплекс математических действий в различных частях приложения. Мы можем создать компонент, который позволит использовать наш код в разных контроллерах.
Первый шаг – это создать новый файл и класс компонента. Создадим файл в /app/controllers/components/math.php. Базовая структура для компонента будет выглядеть примерно так:
<?phpclass 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().
<?phpclass 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 вызывается автоматически для вложенных компонентов!
<?phpclass MyComponent extends Object {
// Этот компонент использует другие компоненты
var $components = array('Session', 'Math'); function
doStuff() {
$result = $this->Math->doComplexOperation(1, 2);
$this->Session->write('stuff', $result); }
}
?>
Использовать модели в компонентах, в общем случае, не рекомендуется; однако, если после взвешивания всех возможностей, вы захотите это сделать, то вам необходимо инициализировать класс модели в какую-либо переменную и использовать ее.
Вот пример:
<?phpclass 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 со списком потомков. Компоненты-родители загружаются перед их потомками и у потомков есть доступ к родителям.
Родитель:
<?phpclass ParentComponent extends Object { var
$name = "Parent"; var
$components = array( "Child" ); function
initialize(&$controller) {
$this->Child->foo(); }
function
bar() {
// ...
}}
Потомок:
<?phpclass ChildComponent extends Object { var
$name = "Child"; function
initialize(&$controller) {
$this->Parent->bar(); }
function
foo() {
// ...
}}