Как создать Behavior для CakePHP
Автор 

Владимир Лучанинов
Я люблю выносить обработку данных в модели. При этом у меня часто получаются модели со схожими функциями, как в одном проекте так и в разных. А меня очень удручает, когда надо писать один и тот же код по несколько раз, а от копирования кода меня просто передёргивает, потому что я уже вижу как через полгода буду себя проклинать. До CakePHP я в таких случаях просто создавал общего потомка и там реализовал общую функциональность. Недостаток этого метода — это то, что в PHP можно наследовать можно только один класс.
К счастью, разработчики CakePHP придумали как удобнее выносить одинаковую функциональность из моделей. Эта возможность появилась в 
Cake PHP 1.2 и называется behaviors.
Возьмём, нашу модель 
Word. У меня часто бывают такие таблицы, которые состоят из 
id и 
name. Я покажу как сделать так, чтобы к другим моделям такого типа можно было применять общую функциональность. Но при этом мы можем указать в каждой конкретной модели, какие behaviors к ней подключать. Самое удобное, что можно подключать их несколько, а не только одну.
Модель выглядела так
app/models/word.php
<?php
class Word extends AppModel {
    var $name = 'Word';
    var $validate = array(
        'id' => VALID_NUMBER,
        'name' => VALID_NOT_EMPTY,
    );
    /**
     * Adds a word and returns id
     *
     * @param string $name
     * @return integer If failed to save returns false
     */
    function add($name) {
        $item = array(
            'name'  => $name,
        );
        $this->create();
        if ($this->save($item)) {
            return $this->getInsertId();
        } else {
            return false;
        }
    }
    /**
     * Generates list of lowercase names and its ids
     *
     * @return array (a(name=>id), ...)
     */
    function generateListFlipLow(&$model) {
        $items = $this->generateList();
        foreach ($items as $id=>$name) {
            $items[$id] = low($name);
        }
        return array_flip($items);
    }
}
?>
С применением behavior этот же класс будет выглядеть так
<?
class Word extends AppModel {
    var $name = 'Word';
    var $validate = array(
        'id' => VALID_NUMBER,
        'name' => VALID_NOT_EMPTY,
    );
    var $actsAs = array('NameList');
}
?>
И всё. Через запятую можно указать несколько behaviors. Если надо передать настройки в behavior, то надо писать
var $actsAs = array('NameList'=>array('setting1'=>'value1', 'setting2'=>'value2'));
Сами behaviors находятся в 
app/models/behaviors. Для нашей модели — это 
app/models/behaviors/name_list.php
<?
class NameListBehavior extends ModelBehavior {
    var $settings = array();
    function setup(&$model, $config = array()) {
        $this->settings = $config;
    }
    /**
     * Adds a word and returns id
     *
     * @param string $name
     * @return integer If failed to save returns false
     */
    function add(&$model, $name) {
        $item = array(
            'name'  => $name,
        );
        $model->create();
        if ($model->save($item)) {
            return $model->getInsertId();
        } else {
            return false;
        }
    }
    /**
     * Generates list of lowercase names and its ids
     *
     * @return array (a(name=>id), ...)
     */
    function generateListFlipLow(&$model) {
        $items = $model->generateList();
        foreach ($items as $id=>$name) {
            $items[$id] = low($name);
        }
        return array_flip($items);
    }
}
?>
В методе 
setup мы настраиваем behavior. В 
$config передаются настройки, которые можно указать в модели.
Во всех методах добавляется первый параметр 
$model. Если вы переносите методы из модели, то надо не забыть все 
$this поменять на 
$model.
Как видите, создавать 
behaviors очень просто. Особенно, если мы заранее создали тест и можем автоматически убедиться, что всё по-прежнему работает.