CakePHP: Articles/Tutorials/CreateBehavior

Как создать 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 очень просто. Особенно, если мы заранее создали тест и можем автоматически убедиться, что всё по-прежнему работает.