Yii Framework Forum: Best way to create/update model and relation - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Best way to create/update model and relation Example: create new user and profile relation

#1 User is offline   Wade Shuler 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 33
  • Joined: 29-October 14
  • Location:Indiana

Posted 13 September 2017 - 01:46 PM

I am using the advanced app, with the default "user" migration. I then create a new table migration for "user_profile" which has a "user_id" column as a relation to back to "user->id".

- user
- - id
- - username

- user_profile
- - id
- - user_id <-- relation to user->id
- - firstname

A typical setup.

There are relation getters both ways. User can fetch it's profile via "$user->profile->firstname". The reverse works, if you pull up by the profile, you can get the user, "$profile->user->username".

I am trying to streamline the create and update actions to handle both "user" and "profile" the easiest, cleanest, most elegant way.

I think the easiest way to update them is like so:

UserController.php
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ( $model->load(Yii::$app->request->post()) && $model->profile->load(Yii::$app->request->post()) )
        {
            if ( $model->save() && $model->profile->save() ) {
                Yii::$app->session->setFlash('success', 'The user account has been updated!');
                return $this->redirect(['view', 'id' => $model->id]);
            }
        }

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


Note: We can call "load()" on the model (which is User) like normal AND on the relation "$model->profile->load()". Then call save on both ($model->save() and $model->profile->save()) It works great :) -- This streamlined the process, we don't have to do a separate "Profile::find()". This is the cleanest way. Anyone else working with this code would be able to see what is going on, and it isn't in an unnecessary Form model for such a simple step.

---

However, what is the best way to handle creating a new user and giving them some profile information? IE: create a new user and a profile all in one go.

So far, I know of 2 ways to do this.

1) Use a form to handle the inputs (both from user and profile), ie: username, email, firstname, lastname, phone

    public function actionCreate()
    {
        $model = new CreateUserForm;

        if ($model->load(Yii::$app->request->post()) && $model->createUser()) {
            return $this->redirect(['view', 'id' => $model->id]);
        }

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


Inside CreateUserForm:

    public function createUser()
    {
        if ($this->validate())
        {
            $user = new User();
            $user->username = $this->username;
            $user->email = $this->email;
            $user->status = $this->status;
            $user->setPassword($this->password);
            $user->generateAuthKey();

            if ($user->save())
            {
                $profile = new UserProfile;
                $profile->user_id = $user->id;
                $profile->firstname = $this->firstname;
                $profile->lastname = $this->lastname;

                return $profile->save() ? $user : null;
            }
        }

        return null;
    }


Note: In this, we manually create the user via "new User" and manually create the profile via "new UserProfile". Pretty typical stuff. However, I should be able to create a new user and define it's relation info, without manually calling "new UserProfile" and saving it separately. Yii already knows the relation and that it is related via the "id to user_id" relation...

2) The same way CreateUserForm works, only inside the create action itself and not neatly tucked inside a form..


---

So my question is, is there a way to create "user" and it's related "profile" in one go without adding "$profile = new UserProfile" and filling/saving it separately? Similarly how I was able to update both of them in one go..


---

PS: I just found the "link()" function Yii2 Doc -> Saving Relations. Basically, I want to do this, ONLY I also need to create the user too. Unfortunately, "link()" needs the user to already exist. In the meantime, I used transactions to create the user and the profile.
0

#2 User is offline   softark 

  • Keep It Simple
  • Yii
  • Group: Moderators
  • Posts: 3,361
  • Joined: 16-February 11
  • Location:Japan

Posted 13 September 2017 - 05:55 PM

Wow, it's a very enlightening article. It describes very well how to handle relational models in Yii ActiveRecord ORM.

Quote

So my question is, is there a way to create "user" and it's related "profile" in one go without adding "$profile = new UserProfile" and filling/saving it separately? Similarly how I was able to update both of them in one go..


I don't want that much. Your goal looks overly aggressive or sophisticated to me. :)
0

#3 User is offline   Sarke 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 83
  • Joined: 25-October 10

Posted 13 September 2017 - 05:56 PM

Look into http://www.yiiframew...ept-events.html

You can use EVENT_AFTER_INSERT and EVENT_AFTER_UPDATE events to save the relation data.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users