简体   繁体   中英

Two Models Displaying to Same View in Yii2

I am trying to get information from two models that are related, displayed in one view.

So what I am trying to accomplish is have the index view to show the list of people, if I then go into detail view of that particular person I want a list of attributes relevant to that person to appear.

I have the database setup so that when I create a new person a default row gets inserted into the attributes table with the id of the person under the column called person_id.

See my two model classes

People:

class People extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'people';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['dob', 'CURDATE'], 'safe'],
            [['age'], 'integer'],
            [['firstname', 'surname'], 'string', 'max' => 50]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'firstname' => 'Firstname',
            'surname' => 'Surname',
            'dob' => 'Dob',
            'age' => 'Age',
            'CURDATE' => 'Curdate',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getId0()
    {
        return $this->hasOne(Attributes::className(), ['person_id' => 'id']);
    }
}

Attributes:

class Attributes extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'attributes';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['haircolor', 'eyecolor', 'weight', 'height', 'person_id'], 'required'],
            [['weight', 'height', 'person_id'], 'integer'],
            [['haircolor', 'eyecolor'], 'string', 'max' => 50]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'haircolor' => 'Haircolor',
            'eyecolor' => 'Eyecolor',
            'weight' => 'Weight',
            'height' => 'Height',
            'person_id' => 'Person ID',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getPeople()
    {
        return $this->hasOne(People::className(), ['id' => 'person_id']);
    }
}

I have generated CRUD through Gii for both of these models.

What I would like to know is how to setup my people controller and people view so that this may work properly.

Just to recap, my index.php view will just show the list of people, if a record exists, you can view that specific record, if you view the record - which will be the view.php file, I want to show the attributes(These will be the default values) of that particular person where the id of the person is the same as the person_id in the attributes table

The user will then be able to update the attributes relating to that person.

Kind Regards.

Here an example :

public function actionCreate()
{   
    $user = new User;
    $profile = new Profile;

    if ($user->load(Yii::$app->request->post()) && $profile->load(Yii::$app->request->post()) && Model::validateMultiple([$user, $profile])) {

        $user->save(false); // skip validation as model is already validated
        $profile->user_id = $user->id; // no need for validation rule on user_id as you set it yourself
        $profile-save(false); 

        return $this->redirect(['view', 'id' => $user->id]);
    } else {
        return $this->render('create', [
            'user' => $user,
            'profile' => $profile,
        ]);
    }
}

More informations :

http://www.yiiframework.com/forum/index.php/topic/53935-solved-subforms/page__p__248184

http://www.yiiframework.com/doc-2.0/guide-input-tabular-input.html

To display related information in a view, you get the best performance with eager loading. I'll provide an example:

public function actionView($id)
{
    $model = Person::find()
        ->where(['id' => $id])
        ->with('id0')
        ->one();

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

Now i see that your relation in Person Model is called getId0, you can for readability change that to getAttribs(), and change to ->with('attribs') but that is just a digression :)

EDIT: as @soju commented, attributes is not possible to use as a relation name, and that is why gii has given it the name getId0. Attribs or something more informative can be helpful on readability.

If you want to show the results in a widget, like GridView or ListView, you can follow the guide here:

http://www.ramirezcobos.com/2014/04/16/displaying-sorting-and-filtering-model-relations-on-a-gridview-yii2/

EDIT2: as @soju commented, guide is possibly outdated. Read official documents aswell. http://www.yiiframework.com/doc-2.0/guide-output-data-widgets.html#working-with-model-relations

If you want to create your own view, you can access the values with $model->id0->haircolor or, if you rename the relation, $model->attribs->haircolor just like you would any other attribute.

Remember: using GridView / ListView requires the table name from the db when displaying, like 'attributes.eyecolor' , but the $model->id0 requires the relation name from the model, without the 'get' in front, and with lower case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM