Yii2模型加载未按预期工作 [英] Yii2 model load does not work as expected

查看:87
本文介绍了Yii2模型加载未按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题可能类似于以下问题:

My question may look like the following question:


yii2-模型加载功能未设置某些模型属性

但是,由于通过联结表处理多对多关系,这里的情况有所不同。

However, the case here is different due to dealing with Many to Many relation through junction table.

例如,我有三个表,职位 Eqtypes 和联结表 Eqtype_jobs 。我想使用简单的 activeform Eqtypes 与当前的 Job 相关联c>使用多个选择 dropDownList 。以下是我在其中的代码,控制器和视图:

For instance, I have three tables, Jobs, Eqtypes and the junction table Eqtype_jobs. I want to relate some Eqtypes to a current Job using simple activeform using multiple select dropDownList. The following is the code that I have in, the controller and the view:

//the controller code
public function actionEqtypeCreate($id)
{
  $eqtypes = \app\modules\crud\models\Eqtype::find()->all();
  $model = Job::findOne(['id' => $id]);
  if ($model->load(Yii::$app->request->post())){    
    var_dump($model->eqtypes);
    die(); // for debuging <<<<<<<<<<*>>>>>>>>
    foreach ($eqtypes as $eqt){
      $model->eqtypes->id = $eqt->id;
      $model->eqtypeJobs->eqtype_id = $eqt->eqtype_id;
      $model->save();
    }
    return $this->redirect(['index']);
  }
  return $this->render('eqtype-create', ['model' => $model, 'eqtypes' => $eqtypes]);  

}

此处视图:

//The view code i.e Form
<?php
//use Yii;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;

$form = ActiveForm::begin([
    'enableClientValidation' => true,
]);

echo $form->field($model, 'eqtypes')->dropDownList(ArrayHelper::map($eqtypes,'id','title'), ['multiple' => true]);

 echo Html::submitButton(
        '<span class="glyphicon glyphicon-check"></span> ' .
        ($model->isNewRecord ? Yii::t('cruds', 'Create') : Yii::t('cruds', 'Save')),
        [
        'id' => 'save-' . $model->formName(),
        'class' => 'btn btn-success'
        ]
        );      

$form->end();

这里我有一个问题: var_dump($ model-> ; eqtypes)在控制器代码中 die()之前,始终返回空数组 array(0){}

Here I have a problem: the output of var_dump($model->eqtypes), just before the die() in the controller code, always returns empty array array(0) { }.

实际上,是什么让我尝试使用 die(),在没有调试的情况下,出现以下错误:

Indeed, what's making me try to debug using die(), without the debug, I have got the following error:


间接修改重载属性
app\modules\crud\models\Job :: $ eqtypes在第149行无效

在我的情况下,第149行是控制器代码中 foreach 语句之后的第一行:

In my case line 149 is the first line after foreach statement in the controller code:

$model->eqtypes->id = $eqt->id;



编辑



所有模型均使用 yii2-giiant 。但是,以下是工作模型的部分副本:

Edit

All models are created using yii2-giiant. However the following is a partial copy of job model:

<?php
// This class was automatically generated by a giiant build task
// You should not change it manually as it will be overwritten on next build

namespace app\modules\crud\models\base;

use Yii;
abstract class Job extends \yii\db\ActiveRecord
{



    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'jobs';
    }


    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['machine_id', 'product_id', 'title', 'qty'], 'required'],
            [['machine_id', 'product_id', 'qty', 'updated_by' ,'created_by'], 'integer'],
            [['created', 'started', 'completed'], 'safe'],
            [['desc'], 'string'],
            [['title', 'speed'], 'string', 'max' => 255],
            [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => \app\modules\crud\models\Product::className(), 'targetAttribute' => ['product_id' => 'id']],
            [['machine_id'], 'exist', 'skipOnError' => true, 'targetClass' => \app\modules\crud\models\Machine::className(), 'targetAttribute' => ['machine_id' => 'id']]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => Yii::t('app', 'ID'),
            'machine_id' => Yii::t('app', 'Machine ID'),
            'created' => Yii::t('app', 'Created'),
            'started' => Yii::t('app', 'Started'),
            'completed' => Yii::t('app', 'Completed'),
            'product_id' => Yii::t('app', 'Product ID'),
            'title' => Yii::t('app', 'Title'),
            'qty' => Yii::t('app', 'Qty'),
            'speed' => Yii::t('app', 'Speed'),
            'created_by' => Yii::t('app', 'Created By'),
            'desc' => Yii::t('app', 'Desc'),
        ];
    }
 public function getEqtypeJobs()
    {
        return $this->hasMany(\app\modules\crud\models\EqtypeJob::className(), ['job_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getEqtypes()
    {
        return $this->hasMany(\app\modules\crud\models\Eqtype::className(), ['id' => 'eqtype_id'])->viaTable('eqtype_jobs', ['job_id' => 'id']);
    }

我确切不知道是由于未加载导致的问题 var_dump 的输出导致表单中的POST数据丢失,或者我的代码中缺少其他内容?!

I don't know, exactly, is the problem due to the miss loading of the POST data from the form due to the output of the var_dump or there is another thing missing in my code?!

所以,我想知道为什么 load 无法正常工作? 换句话说 var_dump($ model-> eqtypes)打印联接表中的存储值,而不是表单中的提交值,然后如果我们能够解决这个问题,为什么会出现有关间接修改的错误消息?

So, I would like to know, why load does not works as expected? In other words var_dump($model->eqtypes) prints the stored values in the conjunction table not the submitted values from the form, and then if we could able to solve this, why the error message about the indirect modification?

推荐答案

您拥有间接修改重载属性的错误是由于您试图修改 __get魔术方法返回的属性。看看 yii\db\BaseActiveRecord的 __get,简而言之,它首先检查您的模型是否具有属性 eqtypes,如果不是,则检查模型关系。

The error you are having "Indirect modification of overloaded property" is due to the fact that you are trying to modify a property returned by "__get" magic method. Take a look at the "__get" of "yii\db\BaseActiveRecord", in short it first checks if your model has a property "eqtypes" and if not checks your model relations.

如您所知,您不能从帖子中加载模型中的关系,而只能保存它。
我认为在您的解决方案中,您正在解决问题,并使您的代码过于复杂。

As you understood, you cannot load relations in a model from a post and simply save it. I think in your solution, you are overshooting the problem and make your code too complex.

我建议您使用以下模块: https://github.com/cornernote/yii2-linkall
安装此程序并将您的操作更改为:

I suggest you use this module: https://github.com/cornernote/yii2-linkall Install this and change your action to:

$model = Job::findOne(['id' => $id]);
    if ($model->load(Yii::$app->request->post())){
        $postData = Yii::$app->request->post();
        $eqtypesIds = $postData['Job']['eqtypes'];
        $eqtypes = \app\models\Eqtype::findAll($eqtypesIds);
        $transaction = Yii::$app->db->beginTransaction();
        $extraColumns = []; // extra columns to be saved to the many to many table
        $unlink = true; // unlink tags not in the list
        $delete = true; // delete unlinked tags
        try {
            $model->linkAll('eqtypes', $eqtypes, $extraColumns, $unlink, $delete);
            $model->save();

            $transaction->commit();
        } catch (Exception $e) {

            $transaction->rollBack();

        }
        return $this->redirect(['index']);
    }
    $eqtypes = \app\models\Eqtype::find()->all();
    return $this->render('eqtype', ['model' => $model, 'eqtypes' => $eqtypes]);

并添加您的工作模型:

public function behaviors()
{
    return [
        \cornernote\linkall\LinkAllBehavior::className(),
    ];
}

如果您不想使用此模块,则应覆盖默认负载()和save()方法,包括加载和保存关系。

If you do not want to use this module, you should override the default load() and save() methods of your model to include loading and saving your relations.

这篇关于Yii2模型加载未按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆