我有两种模型:一种用于“专家”(基于其联系方式的数据库表),另一种用于“专业知识”(例如“PHP”、“JavaScript”、“Java”……也在数据库表中)。由于一个专家可以拥有不止一种专业知识,而一种专业知识可以由多个专家持有,因此这是在模型类中定义的多对多关系,请参见下文。该关系应存储在联结表中。
// in models/RcccExperts.php
class RcccExperts extends \yii\db\ActiveRecord
{
...
public function getRcccExpertise()
{
return $this->hasMany(RcccExpertise::className(), ['id' => 'expertise_id'])
->viaTable('rccc_experts_expertise', ['expert_id' => 'id']);
}
}
// in models/RcccExpertise.php
class RcccExpertise extends \yii\db\ActiveRecord
{
...
public function getRcccExperts()
{
return $this->hasMany(RcccExperts::className(), ['id' => 'expert_id'])
->viaTable('rccc_experts_expertise', ['expertise_id' => 'id']);
}
}
用户可以通过包含来自两个模型的数据的表单向专家数据库添加新条目。用户可以通过多选表单字段(使用 select2 标签实现)将专业知识分配给专家,他/她可以从现有的专业知识(已经在数据库中)中选择或添加新的专业知识标签。
当我尝试链接这两个模型以填充联结表(包含专家 ID 和专业知识 ID)时,我收到以下错误消息:
PHP Fatal Error – yii\base\ErrorException
Call to a member function getIsNewRecord() on array
in /Users/Sites/Yii/vendor/yiisoft/yii2/db/BaseActiveRecord.php at line 1248
我知道当使用 ->viaTable
链接两个模型时,两个模型都不能新建。在我的例子中,Expert 模型刚刚被保存并且有一个主键 id;我正在从数据库中检索为专家选择的专业知识 ID。
无论我尝试以何种方式链接这两个模型,问题似乎都不是将 Expertise 识别为现有模型,而是识别为 array()
。
我做错了什么?!
有关以下错误的更多详细信息:
* This parameter is only meaningful for a relationship involving a junction table
* (i.e., a relation set with [[ActiveRelationTrait::via()]] or [[ActiveQuery::viaTable()]].)
* @throws InvalidCallException if the method is unable to link two models.
*/
public function link($name, $model, $extraColumns = [])
{
$relation = $this->getRelation($name);
if ($relation->via !== null) {
if ($this->getIsNewRecord() || $model->getIsNewRecord()) {
throw new InvalidCallException('Unable to link models: the models being linked cannot be newly created.');
}
if (is_array($relation->via)) {
/* @var $viaRelation ActiveQuery */
list($viaName, $viaRelation) = $relation->via;
$viaClass = $viaRelation->modelClass;
// unset $viaName so that it can be reloaded to reflect the change
unset($this->_related[$viaName]);
} else {
...
在提交创建新 EA 交易的表单后,这是要执行的 Controller 代码:
// in controllers/ExpertsController.php
/**
* ExpertsController implements the CRUD actions for RcccExperts model.
*/
class ExpertsController extends Controller
{
...
public function actionCreate()
{
$model = new RcccExperts();
$expertise = new RcccExpertise();
if ($model->load(Yii::$app->request->post()) && $expertise->load(Yii::$app->request->post())) {
if ($model->validate() && $expertise->validate()) {
if ($model->save()) {
// Once the Expert's model data has been saved
// Go ahead and process the Expertise ids form the multiple select form field:
// First save the expertise (coming from a multiple select form field where the user can
// select existing expertise tags or add new ones) to the database
$array = $expertise->expertise;
$expertise_ids = array();
foreach ($array as $key => $value) {
$exp = new RcccExpertise();
// Check that the expertise does not exist yet
$check1 = $expertise->find()->where(['id' => $value])->one();
$check2 = $expertise->find()->where(['expertise' => $value])->one();
if ($check1 == null && $check2 == null) {
$exp->expertise = $value;
// Save new expertise
$exp->save();
$result = $expertise->find()->select('id')->where(['expertise' => $value])->one();
$expertise_ids[] = $result->id;
}
else $expertise_ids[] = $value;
}
$expertise->id = $expertise_ids;
// Put the new expertise IDs in a model instance
$expertises = RcccExpertise::find()->where(['id' => $expertise->id])->all();
// Link expert model with expertise model
// to populate the junction table
$model->link('rcccExpertise', $expertises);
}
return $this->redirect(['view', 'id' => $model->id]);
}
}
else {
return $this->render('create', [
'model' => $model,
'expertise' => $expertise,
'languages' => $languages,
'attachments' => $attachments
]);
}
}
保存此信息的 MySQL 表如下所示:
`CREATE TABLE `rccc_experts` (
`id` int(10) UNSIGNED NOT NULL,
`name` varchar(200) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(100) NOT NULL,
`skype` varchar(100) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `rccc_experts`ADD PRIMARY KEY (`id`);
ALTER TABLE `rccc_experts` MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;COMMIT;
CREATE TABLE `rccc_expertise` (
`id` int(10) UNSIGNED NOT NULL,
`expertise` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `rccc_expertise` ADD PRIMARY KEY (`id`);
ALTER TABLE `rccc_expertise` MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;COMMIT;
CREATE TABLE `rccc_experts_expertise` (
`id` int(10) UNSIGNED NOT NULL,
`expert_id` int(10) UNSIGNED NOT NULL,
`expertise_id` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `rccc_experts_expertise` ADD PRIMARY KEY (`id`);
ALTER TABLE `rccc_experts_expertise` MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;COMMIT;
最佳答案
关系 hasMany
返回对象数组。为了让它工作,你必须遍历这个数组,比如:
foreach ($model->rcccExperts as $expert) {
// do your stuff here on $expert variable
}
关于php - Yii2 从表单保存用户提交的数据时链接两个模型不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45076860/