Сохранение модели в afterSave () в cakePHP - PullRequest
4 голосов
/ 29 ноября 2010

У меня есть форма с полем загрузки файла, и я создал файл модели поведения для обработки файла.

У меня есть две функции: beforeSave и afterSave:

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

В afterSave я генерирую новое имя файла на основе некоторых текстовых полей в форме и добавляю lastInsertId напротив него. Я также перемещаю файл из временного каталога в нужное место. Это все работает нормально, но когда я пытаюсь сохранить новое имя файла в модели, оно просто не работает.

Я провел много тестов и отладок, а также часами искал в Интернете. Вывод заключается в том, что вы не можете сохранить в afterSave, он запускается сам и снова запускается перед сохранением.

Итак, мой вопрос, как я могу обновить недавно вставленную модель? У введенного имени файла должен быть первичный ключ в его имени, и он неизвестен во время beforeSave.

благодарен за любую помощь! Ясон

Ответы [ 4 ]

15 голосов
/ 03 мая 2012

Если вы хотите обойти все обратные вызовы (afterSave / beforeSave) в самом afterSave (), я обнаружил, что этот синтаксис работает для меня:

$this->save($data, array('callbacks'=>false));

Чтобы отключить триггеры , руководство действительно заявляет, что:

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

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

array(
     'validate' => true,
     'fieldList' => array(),
     'callbacks' => true //other possible values are false, 'before', 'after' )
6 голосов
/ 29 ноября 2010

Это можно сделать следующим образом

// Its your model Image.php
function afterSave($created) {
    if($created) {
         // its new record
         // do your work here
    }
}

Небольшой твик ( не рекомендуется )

Если вы хотите обойти перед сохранением на БДоперации в afterSave () используют $this->Model->query() вместо $this->Model->save();

// little hack to bypass beforeSave
$this->Model->query('UPDATE listings SET name="xx" WHERE id="1"');
0 голосов
/ 30 ноября 2010

В идеале, если ваше имя файла зависит от других столбцов в базе данных, вам не нужно повторно сохранять данные модели снова. Фактически, в схему вашей таблицы будут добавлены столбцы, которые зависят друг от друга, что противоречит нормализации.

Например. Если ваше имя файла имеет форму «textfield1-textfield2-yourid.ext», вы должны хранить значения textfield1, textfield2 и ext в базе данных. Затем в методе afterFind() вашей модели вы можете просмотреть свои результаты, создав сгенерированное имя файла в качестве нового поля в массиве данных.

Пример схемы таблицы:

id | textfield1 | textfield2 | extension | created | modified

Пример кода:

echo $this->Html->image("{$data['Picture']['textfield1']}-{$data['Picture']['textfield2']}-{$data['Picture']['id']}.{$data['Picture']['extension']}");

Конечно, как я уже упоминал ранее, это можно упростить, если вы переопределите afterFind () в вашей модели и создадите новое поле с именем "filename". Подробнее об этом здесь .

Это сократит ваш код до:

echo $this->Html->image($data['Picture']['filename']);

А также упростит универсальное изменение в любой точке.

0 голосов
/ 29 ноября 2010

Лично вся обработка файла должна выполняться в контроллере (или компоненте) после сохранения вашей модели. Я не думаю, что модель должна управлять файлом в соответствии с дизайном MVC.

В вашем контроллере

// Save model
if ($model->save()) {
    // Save your file
    ...
    // Update the model
    $model->updateField();
} 

$model->save();

Надеюсь, эта помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...