从多个表中填充表单yii2 mysql

时间:2017-03-06 16:06:22

标签: php mysql forms yii2 action

我刚学会了如何使用多个模型创建复杂的表单。

 public function actionCreate()
{
    $model = new Company();
    $contact = new Contact();
    $address = new Address();
    $company_contact = new CompanyContact();
    $company_address = new CompanyAddress();

    if ($model->load(Yii::$app->request->post()) && $contact->load(Yii::$app->request->post()) && $address->load(Yii::$app->request->post())) {
        $model->save();
        $address->save();
        $contact->save();

        // we need to insert the index from each key to the table Company_Contact to associate them
        $company_contact->id_company = $model->id_company;
        $company_contact->id_contact = $contact->id_contact;

        // same procedure for Company_Address
        $company_address->id_company = $model->id_company;
        $company_address->id_address = $address->id_address;

        $company_address->save();
        $company_contact->save();

        return $this->redirect(['index']);
    } else {
        return $this->render('create', [
            'model' => $model,
            'contact' => $contact,
            'address' => $address
        ]);
    }
}

现在的问题是我不知道如何回调每个表数据,所以我可以填充我的表单,然后保存更改。我有使用JOIN的想法,但我没有必要知道如何在yii2框架上工作。

1 个答案:

答案 0 :(得分:0)

首先,您需要确保声明公司与联系人和地址的关系的方法是正确的。

public function getContact() {
    return $this->hasOne(Contact::className(), ['id_contact' => 'id_contact'])
        ->viaTable('Company_Contact', ['id_company' => 'id_company']);
}

public function getAddress() {
    return $this->hasOne(Address::className(), ['id_address' => 'id_address'])
        ->viaTable('Company_Address', ['id_company' => 'id_company']);
}

现在我们知道我们的关系是正确的,我们可以对控制器内的actionCreate()进行一些修改:

public function actionCreate() {
    $model = new Company();
    $contact = new Contact();
    $address = new Address();

    // Check if the request was made using post, otherwise skip and render 'create' view
    if(Yii::$app->request->isPost) {
        // Begin a transaction, so we only make changes to the Database when we can save all the needed records.
        $transaction = Company::getDb()->beginTransaction();
        try {
            $post = Yii::$app->request->post();

            // We try to load $model, $contact and $address. If we can't then we throw an Exception that will be caught.
            if(!($model->load(Yii::$app->request->post()) && $contact->load(Yii::$app->request->post()) && $address->load(Yii::$app->request->post()))) {
                throw new \Exception('Could not load post data to models');
            }

            // Now we try to save them, each by itself. If any of them fail to save then we throw an Exception.

            if(!$model->save()) {
                throw new \Exception('Could not save $model');
            }

            if(!$address->save()) {
                throw new \Exception('Could not save $address');
            }

            if(!$contact->save()) {
                throw new \Exception('Could not save $contact');
            }

            // Now we populate the relationships.

            // First parametter is the name of the relationship, Second is the model we want to link to.
            $model->link('address', $address);
            $model->link('contact', $contact);

            // With the relationships correctly declared, we don't need to populate the juncture table ourselves, just link both models.
            // If the 'link' method cannot link the models, then it will throw an Exception that will be caught.

            // If we managed to save all the records and link them, now we commit the transaction so the changes made in the database are not reverted.
            $transaction->commit();

            return $this->redirect(['index']);
        }
        catch(\Exception $e) {
            // If there are any problems then we will do a rollBack to the transaction, reverting the changes made during the transaction.
            $transaction->rollBack();
        }
    }

    return $this->render('create', [
        'model' => $model,
        'contact' => $contact,
        'address' => $address,
    ]);
}

现在对于actionUpdate,我们只需要获取$ id作为PK来搜索公司。

public function actionUpdate(&id) {
    $model = Company::findOne($id);

    // If $model is null, then throw a NotFoundHttpException.
    if($model === null) {
        throw new \yii\web\NotFoundHttpException('The requested page does not exist.');
    }

    // We can get the $contact and $address models by using the relationships we already declared.
    $contact = $model->contact;
    $address = $model->address;

    // Now we don't need to change much from actionCreate,
    // except we don't need to link $model with $contact or $address because they are already linked,
    // we just need to save changes made to them.
    if(Yii::$app->request->isPost) {
        $transaction = Company::getDb()->beginTransaction();
        try {
            $post = Yii::$app->request->post();

            if(!($model->load(Yii::$app->request->post()) && $contact->load(Yii::$app->request->post()) && $address->load(Yii::$app->request->post()))) {
                throw new \Exception('Could not load post data to models');
            }

            if(!$model->save()) {
                throw new \Exception('Could not save $model');
            }

            if(!$address->save()) {
                throw new \Exception('Could not save $address');
            }

            if(!$contact->save()) {
                throw new \Exception('Could not save $contact');
            }

            $transaction->commit();

            return $this->redirect(['index']);
        }
        catch(\Exception $e) {
            $transaction->rollBack();
        }
    }

    return $this->render('update', [
        'model' => $model,
        'contact' => $contact,
        'address' => $address,
    ]);
}