Модель активной записи Yii2 не сохраняет данные
Я построил простую модель модели и представление, простую модель AR и простой контроллер. Модель формы присваивает правильные значения экземпляру AR, но когда я вызываю save(), ни одно из этих значений не сохраняется в БД. Любые идеи?
Модель формы:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class PromptForm extends Model
{
public $name;
public $intro;
public $prompt;
public $notes;
public $questions;
public function attributeLabels()
{
return [
'name' => 'Prompt title',
'intro' => 'Intro',
'prompt' => 'Prompt body',
'notes' => 'Closing notes',
'questions' => 'Exploration questions',
];
}
/**
* @return array the validation rules.
*/
public function rules()
{
return [
[['name', 'prompt'], 'required'],
['name', 'filter', 'filter' => 'trim'],
['name', 'string', 'max' => 255],
[['intro', 'prompt', 'notes', 'questions'], 'default'],
];
}
public function post()
{
if ($this->validate()) {
$prompt = new Prompt();
$prompt->name = $this->name;
$prompt->intro = $this->intro;
$prompt->prompt = $this->prompt;
$prompt->notes = $this->notes;
$prompt->questions = $this->questions;
$prompt->author = \Yii::$app->user->getId();
//die(print_r($prompt, TRUE));
$prompt->save();
return $prompt;
}
return null;
}
}
Модель AR:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
/**
* Prompt is the model behind the prompt item.
*/
class Prompt extends ActiveRecord
{
public $name;
public $intro;
public $prompt;
public $notes;
public $questions;
public $status;
public $author;
public $id;
/**
* @return string the name of the table associated with this ActiveRecord class.
*/
public static function tableName()
{
return 'prompt';
}
/**
* @return array the attribute labels.
*/
public function attributeLabels()
{
return [
'name' => 'Prompt title',
'intro' => 'Intro',
'prompt' => 'Prompt body',
'notes' => 'Closing notes',
'questions' => 'Exploration questions',
'status' => 'Status',
'author' => 'Author ID',
];
}
}
Контроллер:
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use app\models\PromptForm;
use app\models\Prompt;
class PromptsController extends Controller
{
public function actionIndex()
{
// Return a list of all prompts:
return $this->render('index');
}
public function actionNew()
{
if (\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new PromptForm();
if ($model->load(Yii::$app->request->post())) {
if ($prompt = $model->post()) {
Yii::$app->getSession()->setFlash('success', 'Your prompt was created successfully!');
return $this->goHome();
} else {
Yii::$app->getSession()->setFlash('error', 'Error while submitting your prompt.');
}
}
return $this->render('create', [
'model' => $model,
]);
}
}
Ответы
Ответ 1
Хорошо, я понял это. Оказывается, что если вы объявляете публичные атрибуты в своей модели ActiveRecord, они скрывают автоматические атрибуты, созданные AR. Данные присваиваются вашим скрытым атрибутам, но не отправляются в базу данных.
Правильная модель AR должна была быть просто следующей:
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
class Prompt extends ActiveRecord
{
/**
* @return string the name of the table associated with this ActiveRecord class.
*/
public static function tableName()
{
return 'prompt';
}
}
Ответ 2
Попробуйте
if ($model->load(Yii::$app->request->post())) {
if ($prompt = $model->post()) {
$model->save()
Yii::$app->getSession()->setFlash('success', 'Your prompt was created successfully!');
return $this->goHome();
} else {
Yii::$app->getSession()->setFlash('error', 'Error while submitting your prompt.');
}
}
Ответ 3
Используйте
$prompt->save(false);
Если это работает, это означает, что какое-то правило проверки не срабатывает.
Ответ 4
В контроллере измените условие if следующим образом:
if ($prompt = $model->post() !== null) {
Это подтвердит, что значение, которое является возвратом, не является нулевым.
Ваше текущее условие проверки только подтверждает, где значение присваивается переменной $prompt или нет. И поэтому он всегда возвращает true.
Ответ 5
Я столкнулся с той же проблемой в последнее время, когда я совмещаю класс Active Record с классом Model. Потому что я знаю, что AR фактически расширяет модель в Yii2. Почему бы не написать меньше кода. Поэтому я перемещаю код из модели в AR.
$model = new User();
$model->load(Yii::$app->request->post())
Но атрибут AR _ не получил данные сообщения в форме. данные формы фактически находятся в объекте Model.
object (app\models\User) # 39 (12) {[ "password" ] = > string (6) "google" [ "newpass" ] = > NULL [ "name" ] = > string (5) "Jane1" [ "email" ] = > string (16) "[email protected]" [ "_attributes": "yii\db\BaseActiveRecord": private] = > array (2) {[ "password_hash" ] = > string (60) "$ 2y $13 $.vNKpmosLjW/oYAhIezOZOj8rIG6QJvQj8tGHN2x78.75poXVn6Yi" [ "auth_key" ] = > строка (32) "4XggNakVd-oeU28ny7obdw7gOmZJ-Rbu" }
просто удалите общедоступный атрибут, который вы хотите присвоить массовому назначению экземпляру AR, чтобы он работал.
Ответ 6
Для тех, кто борется с этой проблемой, я не забудьте проверить метод beforeSave
, если таковой имеется. Я по ошибке закомментировал return
выражение.
public function beforeSave($insert)
{
// never toggle comment on this!!!
return parent::beforeSave( $insert);
}
Ответ 7
Как устранить неполадки
Первое, что вы должны добавить при разработке вашего _form.php
это errorSummary():
<?php $form = ActiveForm::begin(); ?>
// Some input fields
...
<?= $form->errorSummary($model); ?> // <--- Add this
...
<?php ActiveForm::end(); ?>
упрощать
Почему бы не использовать сценарии вместо этого, если есть некоторая форма минимальной вариации для формы:
В вашей модели:
public function rules()
{
return [
[['field_1'], 'required', 'on' => self::SCENARIO_ADD], // only on add
[['field_2'], 'required', 'on' => self::SCENARIO_UPDATE], // only on update
[['field_3', 'field_4'], 'required'], // required all the time
];
}
В вашем контроллере:
public function actionAdd()
{
$model = new Model();
$model->scenario = Model::SCENARIO_ADD;
if ($model->load(Yii::$app->request->post())) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('add', ['model' => $model]);
}
поведения
В качестве альтернативы, вместо того, чтобы назначать пользователя непосредственно в вашей модели, вы можете использовать такое поведение:
https://www.yiiframework.com/doc/api/2.0/yii-behaviors-blameablebehavior
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
[
'class' => \yii\behaviors\BlameableBehavior::className(),
'value' => Yii::$app->user->identity->username,
],
[
'class' => \yii\behaviors\TimestampBehavior::className(),
'value' => new \yii\db\Expression('NOW()'),
],
[
'class' => 'sammaye\audittrail\LoggableBehavior',
'userAttribute' => 'updated_by', //blameable attribute of the current model.
'ignored' => ['updated_by', 'updated_at'], // This ignores fields from a selection of all fields, not needed with allowed
],
];
}