Yii2活动记录模型不保存数据

时间:2014-11-09 09:54:17

标签: activerecord yii2

我已经构建了一个简单的表单模型&视图,简单的AR模型和简单的控制器。表单模型为AR实例分配正确的值,但是当我调用save()时,这些值都不会保存在DB中。有什么想法吗?

表单模型:

<?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,
        ]);
    }
}

7 个答案:

答案 0 :(得分:16)

好的,我明白了。事实证明,如果在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';
    }
}

答案 1 :(得分:1)

尝试

    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.');
                }
            }

答案 2 :(得分:1)

使用

$prompt->save(false);

如果有效则意味着某些验证规则失败。

答案 3 :(得分:0)

在控制器中,更改您的if条件如下:

if ($prompt = $model->post() !== null) {

这将验证返回的值不为空 您当前的验证条件仅验证将值分配给变量$ prompt的位置。这就是为什么它总是回归真实的原因。

答案 4 :(得分:0)

当我将Active Record类与Model类结合使用时,我最近遇到了同样的问题。因为我知道AR实际上在Yii2中扩展了Model。为什么不写更少的代码。所以我将代码从模型移动到AR。

$model = new User();  
$model->load(Yii::$app->request->post())

但AR的_attribute并没有获得表单中的帖子数据。表单数据实际上在Model对象中。

  

对象(app \ models \ User)#39(12){[&#34;密码&#34;] =&gt; string(6)&#34; google&#34;   [&#34; newpass&#34;] =&GT; NULL [&#34; name&#34;] =&gt; string(5)&#34; Jane1&#34; [&#34;电子邮件&#34;] =&GT;串(16)   &#34; jane@outlook.com" [&#34; _attributes&#34;:&#34; YII \分贝\ BaseActiveRecord&#34;:私人] =&GT;   array(2){[&#34; password_hash&#34;] =&gt;串(60)   &#34; $ $ 2Y $ 13 .vNKpmosLjW / oYAhIezOZOj8rIG6QJvQj8tGHN2x78.75poXVn6Yi&#34;   [&#34; AUTH_KEY&#34;] =&GT; string(32)&#34; 4XggNakVd-oeU28ny7obdw7gOmZJ-Rbu&#34; }

只需删除您希望批量分配给AR实例的公共属性即可使其正常工作。

答案 5 :(得分:0)

对于正在为这个问题苦苦挣扎的人,我会记得检查beforeSave方法(如果存在)。我错误地注释了return声明。

public function beforeSave($insert)
{
    // never toggle comment on this!!!
    return parent::beforeSave( $insert); 
}

答案 6 :(得分:0)

如何解决

在开发到_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
        ],
    ];
}