Yii2模型加载未按预期工作 [英] Yii2 model load does not work as expected
问题描述
我的问题可能类似于以下问题:
My question may look like the following question:
但是,由于通过联结表处理多对多关系,这里的情况有所不同。
However, the case here is different due to dealing with Many to Many relation through junction table.
例如,我有三个表,职位
, Eqtypes
和联结表 Eqtype_jobs
。我想使用简单的 activeform $ c $将某些
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屋!