web-dev-qa-db-ja.com

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,
        ]);
    }
}
12
Tal V.

わかりました、私はそれを理解しました。 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';
    }
}
17
Tal V.

試す

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

使用する

$Prompt->save(false);

これが機能する場合、一部の検証ルールが失敗することを意味します。

1
NSukonny

コントローラで、次のようにif条件を変更します。

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

これにより、返される値がnullではないことが検証されます。
現在の検証条件は、値が変数$ Promptに割り当てられているかどうかのみを検証しています。そして、それが常にtrueを返す理由です。

0
Akshay Vanjare

Active RecordクラスをModelクラスと組み合わせると、最近同じ問題に遭遇しました。 ARが実際にYii2のモデルを拡張していることを知っているからです。少ないコードを書いてみませんか。モデルからARにコードを移動します。

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

しかし、ARの_attributeはフォームに投稿データを取得しませんでした。フォームデータは実際には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"] => string(32) "4XggNakVd-oeU28ny7obdw7gOmZJ-Rbu"}

aRインスタンスに一括で割り当てたいパブリック属性を削除するだけで機能します。

0
tyan

トラブルシューティングの方法

開発中に最初に追加する必要があるのは、_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
        ],
    ];
}   
0
Jairus Martin

この問題に苦しんでいる人のために、存在する場合はbeforeSaveメソッドを忘れずに確認します。誤ってreturnステートメントをコメントにしました。

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