У меня есть контроллер и действие update, сгенерированное с помощью giiant:
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load($_POST) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
и я хотел бы переименовать файл, переопределив beforeSave в Model:
public function beforeSave($insert) {
if ($this->isAttributeChanged('name')) {
rename($this->getOldAttribute('name') . '.pdf', $this->name . '.pdf');
}
parent::beforeSave($insert);
}
похоже, что модель сохранена, но форма сохраняется после сохранения, чего не может быть на самом деле. Я уверен, что это из-за beforeSave
потому что, если я это закомментирую, все будет нормально. Как использование beforeSave может привести к такому непоследовательному поведению? Что мне не хватает? Большое спасибо!
Если вы просматриваете исходный код beforeSave
, вы обнаружите, что insertion
или же updating
процесс будет отменен, если ваш beforeSave
не возвращается true
, «похоже, что модель сохранена», на самом деле это не так.
Так что настройте свой код на это:
public function beforeSave($insert) {
if ($this->isAttributeChanged('name')) {
rename($this->getOldAttribute('name') . '.pdf', $this->name . '.pdf');
}
return parent::beforeSave($insert);
}
Yii и другие MVC-фреймворки имеют такие функции.
Хотя вы можете написать свой код «перед сохранением» в контроллере, перед функцией save () — более рекомендуется и полезно использовать функцию beforeSave ().
Причина 1: М в MVC
BeforeSave относится к модели, поэтому было бы логичнее иметь код, который обрабатывает свойства (поля) модели в файле модели, чем иметь этот код в контроллере.
Причина 2: сохранение для вставки & Обновить
Вы используете save () при вставке новой записи, а также при обновлении существующей записи. Без использования встроенной функции beforeSave у вас будет 2 экземпляра «руководства» перед сохранением кода. («Отходы» строк кода)
Причина 3: сохранение модели из другого контроллера
Что если вам будет предложено расширить ваше приложение, и теперь вам придется столкнуться с новым контроллером, которому необходимо сохранить ту же модель (по какой-то причине — просто возможный сценарий) — вам придется скопировать свое «перед сохранением» «код для этого контроллера. А если вы используете встроенную функцию beforeSave — вы этого не сделаете.
В заключение, основная цель фреймворков — сократить код, который вам нужно написать, сохраняя при этом что-нибудь логичное (разделение MVC). Хотя вы можете делать вещи по-другому, почему бы не использовать то, что уже существует?
Простой пример:
У меня есть таблица с двумя полями даты. Каждый раз, когда я пытаюсь выполнить вставку или обновление, мне нужно получить текущую системную дату и выполнить свою операцию в зависимости от типа операции.
public function beforeSave() {
if ($this->isNewRecord) {
$this->insertDate = new CDbExpression('NOW()');
} else {
$this->updateDate = new CDbExpression('NOW()');
}
return parent::beforeSave();
}
Я написал это один раз, поэтому мне не нужно писать каждый раз, когда я вызываю save () для этого объекта.
Также некоторые базы данных предпочитают разные форматы времени, поэтому вы можете справиться с ними здесь:
public function beforeSave() {
$this->date = date('Y-m-d', $this->date);
return parent::beforeSave();
}