Home PageКаталог Изменения НовыеКомментарии Пользователи Регистрация
CakePHP: Manual/Developing/Models/Saving ...
Это старая версия Manual/Developing/Models/Saving за 2009-02-20 18:59:21..

Сохранение данных


CakePHP делает сохранение данных модели в один щелчок. Данные, готовые к сохранению, должны быть переданы в метод save(), используя базовый формат:


Array
(
    [ModelName] => Array
        (
            [fieldname1] => 'value'
            [fieldname2] => 'value'
        )
)


В большинстве случаев вам даже не надо будет беспокоится о формате: хелперы HtmlHelper, FormHelper, и find-методы все пакуют данные в этот формат. Если вы используете любой из хелперов, данные также удобно доступны в $this->data для быстрого использования.


Здесь пример действия контроллера, который использует модель CakePHP для сохранения данных в таблицу базы данных:


<?
function edit($id) {
    
//Есть ли данные из формы для сохранения?
    
if(!empty($this->data)) {
        
//Если данные из формы прошли валидацию и сохранены ...
        
if($this->Recipe->save($this->data)) {
            
//Вывести flash-сообщение и перенаправить в '/recipes'.
            
$this->Session->setFlash("Рецепт сохранен!");
            
$this->redirect('/recipes');
        }
    }
 
    
//Если нет данных из формы, то найти рецепт для редактирования
    //и передать его в отображение.
    
$this->set('recipe'$this->Recipe->findById($id));
}
?>


Одно дополнительно замечание: когда save() вызван, то данные, переданные в него первым параметром, проходят проверку через механизм валидации CakePHP (смотрите главу «Валидация данных»). Если по каким-то причинам ваши данные не сохраняются, то убедитесь не нарушаются ли правила валидации.


В модели есть несколько методов, касающихся сохранения данных:


save(array $data = null, boolean $validate = true, array $fieldList = array())

Этот метод сохраняет данные из массивов. Второй параметр позволяет вам отклонить валидацию, и с помощью третьего параметра вы можете передать перечень полей модели для сохранения. Для дополнительной безопасности вы можете ограничить сохраняемые поля в этом списке $fieldList.


Метод save также имеет альтернативный синтаксис:


save(array $data = null, array $params = array())

Массив $params может иметь любые, из следующих опций, в качестве индекса массива:


<?
array(
    
'validate' => true,
    
'fieldList' => array(),
    
'callbacks' => true //other possible values are false, 'before', 'after'
)
?>


Дополнительная информация о колбэках модели доступна здесь.


После того, как сохранение завершено, ID для объекта может быть найдено в переменной $id объекта модели – это особенно удобно, когда создаете новые объекты.


<?
$this
->Ingredient->save($newData);

$newIngredientId $this->Ingredient->id;

?>



create(array $data = array())

Этот метод возвращает модель в исходное состояние для сохранения новой информации.


Если параметр $data (используя формат массива, приведенный выше) передан, экземпляр модели будет готов сохранить с этим данные (доступные через $this->data).


saveField(string $fieldName, string $fieldValue, $validate = false)

Используется для сохранения значений отдельных полей. Просто установите ID ($this->ModelName->id = $id) перед вызовом saveField(). Когда используете этот метод, то $fieldName должно содержать только имя поля, а не имя модели и поля.


Например, для обновления заголовка поста блога, вызов saveField из контроллера может выглядить так:


<? this->Post->saveField('title''A New Title for a New Day'); ?>


updateAll(array $fields, array $conditions)

Обновляет много записей за один вызов. Записи, которые следует обновить определяются массивом $conditions, а поля для обновления, вместе с их значениями, – массивом $fields .


Например, для поощрения всех пекарей, которые работают больше года, update-вызов может выглядеть так:


<?
$this_year 
date('Y-m-d h:i:s'strtotime('-1 year'));

$this->Baker->updateAll(
    array(
'Baker.approved' => true),
    array(
'Baker.created <=' => "$this_year")
);
?>



Например, для бронирования всех билетов для конкретного заказчика можно написать такой код:


<?
$this
->Ticket->updateAll(
    array(
'Ticket.status' => "'closed'"),
    array(
'Ticket.customer_id' => 453)
);
?>


saveAll(array $data = null, array $options = array())

Исользуется для сохранения
– многочисленных записей для одной модели
– текущей записи со всеми ассоциированными записями


Следующие опции могут быть использованы:


validate: Установите в false для отключения проверки валидности, true – для проверки валидности каждой записи перед сохранением, 'first' – для проверки *all* записей перед началом сохранения, или 'only' – только для проверки, но без их последующего сохранения.


atomic: Если true (по умолчанию), то попытается сохранить все записи в одной транзакции. Должен быть установлен в false, если база данных/таблица не поддерживает транзакции. Если false, то будет возвращен массив, похожий на переданный массив $data, но значения будут установлены в true/false, в зависимости от того успешно была сохранена данная запись или нет.


fieldList: Эквивалент параметра $fieldList в Model::save()


Для сохранения множества записей одной модели, $data должен быть численно проиндексирован:


Array
(
    [0] => Array
        (
            [title] => title 1
        )
    [1] => Array
        (
            [title] => title 2
        )
)


Команда для сохранения данных, приведенных выше, будет выглядеть так:


<? $this->Article->saveAll($data['Article']); ?>


Для сохранения записи вместе со связанной записью, имеющей ассоциации hasOne или belongsTo, массив данных должен выглядеть так:


Array
(
    [User] => Array
        (
            [username] => billy
        )
    [Profile] => Array
        (
            [sex] => Male
        [occupation] => Programmer
        )
)


Команда для сохранения этих данных будет выглядеть так:


<? $this->Article->saveAll($data); ?>


Для сохранения записи вместе с связанными записями, имеющих hasMany ассоциацию, массив данных должен выглядеть так:


Array
(
    [Article] => Array
        (
            [title] => My first article
        )
    [Comment] => Array
        (
            [0] => Array
                (
                    [comment] => Comment 1
            [user_id] => 1
                )
        [1] => Array
                (
                    [comment] => Comment 2
            [user_id] => 2
                )
        )
)


Команда для сохранения этого массива $data будет выглядеть так:


<? $this->Article->saveAll($data); ?>

Сохранение данных ассоциированных моделей (hasOne, hasMany, belongsTo)


Когда работаете с ассоциированными моделями, то важно осознавать, что сохранение данных модели должно быть сделано соответствующей моделью. Если вы сохраняете новый пост (Post) и ассоциированные ему комментарии (Comments), то вы будете использовать обе модели Post и Comment.


Если ни одна запись ассоциированных моделей еще не существует (например, вы хотите сохранить нового пользователя (User) и его записи профиля (Profile) в одно и то же время), то вам надо сначала сохранить первичную, или родительскую модель.


Для того, чтобы представить, как это работает, предположим, что у нас есть действие в нашем UsersController, которое управляет сохранением нового пользователя (User) и относящегося к нему профиля (Profile). Пример действия, представленный ниже, предполагает, что вы внесли достаточно данных (используюя FormHelper) для создания пользователя и профиля.


<?php
function add() {
    if (!empty(
$this->data)) {
        
// Мы можем сохранить данные о пользователе:
        // они будут в $this->data['User']
 
        
$user $this->User->save($this->data);

        
// Если пользователь был сохранен, то мы добавляем эту информацию
        // в данные и сохраняем профиль.
      
        
if (!empty($user)) {
            
// ID только что созданного пользователя хранится
            // в $this->User->id.
            
$this->data['Profile']['user_id'] = $this->User->id;

            
// Поскольку наш пользователь имеет один (hasOne) профиль , то 
            // у нас есть доступ к модели Profile через модель User:
            
$this->User->Profile->save($this->data);
        }
    }
}
?>


Основная идея при сохранении данных ассоциированных моделей заключается в том, чтобы получить значение первичного ключа одной модели и поместить его в качестве значения вторичного (внешнего) ключа в другую модель. Иногда, это включает использование переменной модели $id после save(). В других случаях можно получить ID из скрытого инпута в форме, значение которого передается в действие контроллера.


В дополнение к базовому подходу CakePHP также предлагает очень удобный метод saveAll(), который позволяет вам проверить валидность и сохранить множество моделей за раз. Также, saveAll() поддерживает транзакции для обеспечения целостности данных в 
вашей БД (например, если одна модель не сохранилась, то другие модели тоже не будут сохраняться.)


Для того, чтобы транзакции корректно работали в MySQL, ваши таблицы должны использовать механизм InnoDB. 
Помните, что MyISAM таблицы не поддерживают транзакции.


Давайте посмотрим, как мы можем использовать saveAll() для сохранения моделей Company и Account одновременно.


Во-первых, вам необходимо создать формы для этих моделей (мы предполагаем, что Company hasMany Account).


<?
echo $form->create('Company', array('action'=>'add'));
echo 
$form->input('Company.name', array('label'=>'Имя компании'));
echo 
$form->input('Company.description');
echo 
$form->input('Company.location');

echo 
$form->input('Account.0.name', array('label'=>'Имя счета'));
echo 
$form->input('Account.0.username');
echo 
$form->input('Account.0.email');

echo 
$form->end('Add');
?>


Обратите внимание на способ названия полей формы для модели Account. Если Company – это наша главная модель, то saveAll() будет ожидать данные связанной модели в особом формате. И Account.0.fieldName – это то, что нужно.


Именование полей, приведенное выше, требуется для ассоциаций hasMany. 
Если ассоциация между моделями - hasOne, то вы должны использовать нотацию ModelName.fieldName для этих моделей.


Теперь в нашем файле companies_controller мы можем создать действие add():


<?
function add() {
   if(!empty(
$this->data)) {
      
$this->Company->saveAll($this->data, array('validate'=>'first'));
   }
}
?>


Это все. Теперь наши модели Company и Account будут проверены на валидность данных и одновременно сохранены. Опция array('validate'=>'first') гарантирует, что обе модели проверены на валидность перед началом сохранения.

counterCache – Кэширование count()


Эта функция помогает вам кэшировать count связанных данных.


 
Комментарии


а если нет значений.. т.е. при добавлении данных нет id для связи.
240-204-113-92.pool.ukrtel.net (2009-11-05 02:25:31)
Добавить комментарий:

Файлов нет. [Показать файлы/форму]