2

I've got myself confused about the right (or best) way to make sure the associated models are being sent via POST when creating a new User. Both approaches listed bellow are working.

User hasOne UserDetails

Option 1

POST data:

{
    "username": "loremipsum",
    "password": "123456",
    "UserDetails": {
        "first_name": "Lorem",
        "last_name": "Ipsum"
    }
}

PatchEntity UserDetail and add it to User Entity like this:

public function add () {

    $user = $this->Users->newEntity();

    if ($this->request->is('post')) {
        $user = $this->Users->patchEntity($user, $this->request->data(), [
            'associated' => [], 
            'validate' => true
        ]);
        $userDetail = $this->Users->UserDetails->newEntity($this->request->data());
        $user->user_detail = $userDetail;

    if ($this->Users->save($user, ['associated' =>['UserDetails']]))
    { 
...

Edit 1: if the UserDetails is not present on the $this->request->data(), the UserDetails entity will get validation errors.

Option 2

POST data:

{
    "username": "loremipsum",
    "password": "123456",
    "user_detail": {
        "first_name": "Lorem",
        "last_name": "Ipsum"
    }
}

Add user_detail validation into UserTable.php:

Edit 2: if I don't add user_detail validation, the request can be sent without the associated model and it will be saved. Adding it makes sure there's a user_detail field on $this->request->data() and the Users entity is the one that will get the validation.

$validator
     ->requirePresence('user_detail', 'create')
     ->notEmpty('user_detail'); 

and patchEntity like this on UsersController.php:

public function add () {

    $user = $this->Users->newEntity();

    if ($this->request->is('post')) {
        $user = $this->Users->patchEntity($user, $this->request->data(), [
            'associated' => ['UserDetails'], 
            'validate' => true
        ]);

    if ($this->Users->save($user, ['associated' =>['UserDetails']]))
    { 
...

Are these approaches following Cake's conventions or there's a best/clean way to do it?

Bruno Serra
  • 43
  • 3
  • 8
  • Option 2 is a better option. And it will give you validation errors for both `Users` and the associated model `UserDetails`. – Indrasis Datta Feb 07 '17 at 03:55
  • @ObjectManipulator thanks for replying! Actually in both cases validation works because validation runs when creating the entity. The main difference here is the way code is written and data sent :) – Bruno Serra Feb 07 '17 at 15:14
  • option 1 is correct ..option 2 is not working it is validation only users model not userdetails..thanks man your really helpful – Soubhagya Kumar Barik Jul 04 '18 at 02:23

2 Answers2

0

The second option is the correct option for a few reasons IMO.

  1. Validation should be on the Model it pertains to.
  2. Validation should be expressive and explicit. If I'm the other guy reading this code, I could tell that validation is required for saving a user.
  3. It is clearer and less prone to errors.
  4. Matches with cake convention. I haven't seen in any of their examples where you would save one and then save the other. Saving Associations
styks
  • 3,193
  • 1
  • 23
  • 36
  • I've edit my question to make it clear. Both cases the data is saved at once; the first one just adds UserDetails entity separately. The thing is: to force UserDetails to be present on the request should I use the first or second option I gave? thanks! – Bruno Serra Feb 09 '17 at 15:57
0

if you want to validate multiple model then you need to create multiple newEntity as per table.here is the working example for hasOne association.

 public function add() {
        $user = $this->Users->newEntity();
        if ($this->request->is('post')) {
            $user = $this->Users->patchEntity($user, $this->request->getData());
            $userDetail = $this->UserDetails->newEntity($this->request->getData()['user_detail']);
            $user->user_detail = $userDetail;
            if ($this->Users->save($user)) {
                $this->Flash->success(__('The user has been saved.'));
                return $this->redirect($this->referer());
            } else {
                $this->Flash->error(__('The user could not be saved. Please, try again.'));
            }
        }
        $this->set(compact('user'));
    }
Soubhagya Kumar Barik
  • 1,979
  • 20
  • 26