9.4. Zend_Db_Table
Пред. | Глава 9. Zend_Db | След.

## 9.4. Zend_Db_Table

### 9.4.1. Введение

`Zend_Db_Table` является модулем Zend Framework для таблиц. Он устанавливает соединение с вашей базой данных посредством `Zend_Db_Adapter`, исследует структуру таблицы, далее помогает вам в манипулировании и извлечении строк из этой таблицы.

### 9.4.2. Начало работы

Первое, что нужно сделать — установить для абстрактного класса `Zend_Db_Table` адаптер БД по умолчанию. Все экземпляры класса `Zend_Db_Table` будут использовать этот адаптер по умолчанию, пока вы не укажете другое.

    <?php
    // создание адаптера
    require_once 'Zend/Db.php';
    $params = array (
        'host'     => '127.0.0.1',
        'username' => 'malory',
        'password' => '******',
        'dbname'   => 'camelot'
    );

    $db = Zend_Db::factory('PDO_MYSQL', $params);

    // установка адаптера по умолчанию для всех объектов Zend_Db_Table
    require_once 'Zend/Db/Table.php';
    Zend_Db_Table::setDefaultAdapter($db);
    ?>

Теперь предположим, что вы имеете в своей БД таблицу, которая называется "round_table". Чтобы использовать `Zend_Db_Table` с этой таблицей, просто унаследуйте класс `Zend_Db_Table`, чтобы создать дочерний класс под именем `RoundTable` (обратите внимание, что имя класса копирует имя таблицы). Далее мы можем изучать, манипулировать строками и извлекать результаты из таблицы 'round_table' в БД с помощью этого класса.

    <?php
    class RoundTable extends Zend_Db_Table {}
    $table = new RoundTable();
    ?>

### 9.4.3. Имя таблицы и первичные ключи

По умолчанию `Zend_Db_Table` ожидает, что имя данной таблицы в БД будет таким же, как и имя ее собственного класса (в котором разделение слов ЗаглавнымиБуквами заменено разделением знаками_подчеркивания). Таким образом, класс `Zend_Db_Table` с именем SomeTableName соответствует SQL таблице с именем 'some_table_name'. Если вы желаете, чтобы ваш класс соответствовал чему-либо иному, чем имя класса в форме со знаком подчеркивания, переопределите свойство `$_name`, когда описываете свой класс.

    <?php
    class ClassName extends Zend_Db_Table
    {
        // имя таблицы по умолчанию - 'class_name',
        // но мы хотим установить соответствие с чем-то другим
        protected $_name = 'another_table_name';
    }
    ?>

По умолчанию `Zend_Db_Table` ожидает, что ваша таблица имеет первичный ключ с именем 'id'. (Лучше, если этот столбец является автоинкрементным, но это не обязательно.) Если ваш первичный ключ назван по-другому, вы можете переопределить свойство `$_primary`, когда описываете свой класс.

    <?php
    class ClassName extends Zend_Db_Table
    {
        // первичный ключ по умолчанию - 'id',
        // но мы хотим использовать другой
        protected $_primary = 'another_column_name';
    }
    ?>

Также вы можете установить их в методе `_setup()` вашего унаследованного класса — только убедитесь, что после этого вызывается `parent::_setup()`.

    <?php
    class ClassName extends Zend_Db_Table
    {
        protected function _setup()
        {
            $this->_name = 'another_table_name';
            $this->_primary = 'another_column_name';
            parent::_setup();
        }
    }
    ?>

### 9.4.4. Вставка строк

Для того, чтобы вставить новую строку в свою таблицу, просто вызывайте `insert()` с ассоциативным массивом из пар "имя столбца": "значение". В данные будут автоматически добавлены кавычки; метод возвращает последний добавленный ID. (Обратите внимание на то, что этим он отличается от `Zend_Db_Adapter::insert()`, который возвращает количество затронутых строк.)

    <?php
    //
    // INSERT INTO round_table
    //     (noble_title, first_name, favorite_color)
    //     VALUES ("King", "Arthur", "blue")
    //

    class RoundTable extends Zend_Db_Table {}

    $table = new RoundTable();

    $data = array(
        'noble_title' => 'King',
        'first_name'  => 'Arthur',
        'favorite_color' => 'blue',
    )

    $id = $table->insert($data);
    ?>

### 9.4.5. Обновление строк

Для того, чтобы обновить любое количество строк в своей таблице, вызывайте `update()` с ассоциативным массивом из пар "имя столбца": "значение для установки", наряду с этим передается условие WHERE для определения, какие строки дожны быть обновлены. Метод обновит таблицу и вернет количество затронутых строк.

В данные для установки будут автоматически добавлены кавычки, но это не относится к условию WHERE, поэтому вам нужно самим добавить кавычки с помощью принадлежащего таблице объекта `Zend_Db_Adapter`.

    <?php
    //
    // UPDATE round_table
    //     SET favorite_color = "yellow"
    //     WHERE first_name = "Robin"
    //

    class RoundTable extends Zend_Db_Table {}

    $table = new RoundTable();
    $db = $table->getAdapter();

    $set = array(
        'favorite_color' => 'yellow',
    )

    $where = $db->quoteInto('first_name = ?', 'Robin');

    $rows_affected = $table->update($set, $where);
    ?>

### 9.4.6. Удаление строк

Для того, чтобы удалить любое количество строк в своей таблице, вызывайте `delete()` с условием WHERE для определения, какие строки должны быть удалены. Метод будет возвращать количество удаленных строк.

В условие WHERE не добавляются кавычки за вас, поэтому вам нужно самим добавить кавычки с помощью объекта `Zend_Db_Adapter` таблицы.

    <?php
    //
    // DELETE FROM round_table
    //     WHERE first_name = "Patsy"
    //

    class RoundTable extends Zend_Db_Table {}

    $table = new RoundTable();
    $db = $table->getAdapter();

    $where = $db->quoteInto('first_name = ?', 'Patsy');

    $rows_affected = $table->delete($where);
    ?>

### 9.4.7. Поиск строк по первичному ключу

Вы можете легко извлекать строки из таблицы, используя значения первичного ключа через метод `find()`. Этот метод возвращает объект `Zend_Db_Table_Row`, если вы пытаетесь найти только один ключ, или `Zend_Db_Table_Rowset`, если вы пытаетесь найти несколько ключей.

    <?php
    class RoundTable extends Zend_Db_Table {}

    $table = new RoundTable();

    // SELECT * FROM round_table WHERE id = "1"
    $row = $table->find(1);

    // SELECT * FROM round_table WHERE id IN("1", "2", 3")
    $rowset = $table->find(array(1, 2, 3));
    ?>

### 9.4.8. Извлечение одной строки

Несмотря на то, что вы можете использовать метод `find()` для поиска строк по их первичным ключам, часто вам нужно добавлять различные условия, когда извлекаете строки. `Zend_Db_Table` предоставляет `fetchRow()` только для этой цели. Вызывайте `fetchRow()` с условием WHERE (и необязательно условием ORDER), и `Zend_Db_Table` вернет `Zend_Db_Table_Row`, который будет с первой строкой, удовлетворяющей вашим условиям.

Заметьте, что в условие WHERE не добавляются кавычки за вас, поэтому вам нужно самим добавить кавычки с помощью объекта `Zend_Db_Adapter` таблицы.

    <?php
    //
    // SELECT * FROM round_table
    //     WHERE noble_title = "Sir"
    //     AND first_name = "Robin"
    //     ORDER BY favorite_color
    //

    class RoundTable extends Zend_Db_Table {}

    $table = new RoundTable();
    $db = $table->getAdapter();

    $where = $db->quoteInto('noble_title = ?', 'Sir')
           . $db->quoteInto('AND first_name = ?', 'Robin');

    $order = 'favorite_color';

    $row = $table->fetchRow($where, $order);
    ?>

### 9.4.9. Извлечение множества строк

Если вам нужно получить больше одной строки за раз, используйте метод `fetchAll()`. Как и `fetchRow()`, он принимает условия WHERE и ORDER, но, кроме этого, принимает еще количество строк и смещение для ограничения количества возвращаемых строк. Метод будет возвращать объект `Zend_Db_Table_Rowset` с выбранными строками.

Заметьте, что в условие WHERE не добавляются кавычки, поэтому вам нужно самим добавить кавычки с помощью объекта `Zend_Db_Adapter` таблицы.

    <?php
    class RoundTable extends Zend_Db_Table {}

    $table = new RoundTable();
    $db = $table->getAdapter();

    // SELECT * FROM round_table
    //     WHERE noble_title = "Sir"
    //     ORDER BY first_name
    //     LIMIT 10 OFFSET 20

    $where = $db->quoteInto('noble_title = ?', 'Sir');
    $order = 'first_name';
    $count = 10;
    $offset = 20;

    $rowset = $table->fetchAll($where, $order, $count, $offset);
    ?>

### 9.4.10. Добавление логики предметной области

`Zend_Db_Table` дает возможность инкапсулировать свою собственную логику предметной области. Например, вы можете переопределить методы `insert()` и `update()` для проверки отправляемых данных или манипуляций с ними перед тем, как они будут отправлены БД.

    <?php
    class RoundTable extends Zend_Db_Table
    {
        public function insert($data)
        {
            // add a timestamp
            if (empty($data['created_on'])) {
                $data['created_on'] = time();
            }
            return parent::insert($data);
        }

        public function update($data)
        {
            // add a timestamp
            if (empty($data['updated_on'])) {
                $data['updated_on'] = time();
            }
            return parent::update($data);
        }
    }
    ?>

Аналогичным образом вы можете добавить свои собственные методы для поиска записей по чему-либо иному, чем первичные ключи.

    <?php
    class RoundTable extends Zend_Db_Table
    {
        public function findAllWithName($name)
        {
            $db = $this->getAdapter();
            $where = $db->quoteInto("name = ?", $name);
            $order = "first_name";
            return $this->fetchAll($where, $order);
        }
    }
    ?>

Пред. | Уровень выше | След.
9.3. Zend_Db_Select | Начало | 9.5. Zend_Db_Table_Row