Cake "ignores" inserting associated data

I found an issue in my application where when a user registers, it doesn’t insert the firstname and lastname into the associated table.
This was “intended” behaviour (more like: I forgot to implement this) back then so I started to fix it.

Fast forward two days and I can’t get it to work.
This is what I want:

  1. Create a new user entity (for the username, email, password and creation date) for the Users (named users in the db) table
  2. Add data to the associated UsersDetails (named users_details in the db) table
  3. Save it all
  4. Check whether it went right (to show success message or error message as needed)

This is the code I have currently written for that:

$user = $this->Users->newEntity([
  'username' => $this->request->getData('username'),
  'email' => $this->request->getData('email'),
  'password' => $this->request->getData('password'),
  'created' => date("Y-m-d H:i:s"),
  'users_details' => [
    'firstname' => '',
    'lastname' => ''
  ]
]);

if($this->Users->save($user)) {
...

The user is inserted into the Users table but Cake seems to “ignore” the fact that I added stuff to the UsersDetails table as well (so it doesn’t add a new entry to it).

This us my User entity file:

class User extends Entity {
    use UserTrait;

    protected $_accessible = [
        'username' => true,
        'email' => true,
        'password' => true,
        'created' => true,
        'articles' => true,
        'roles' => true,
        'users_details' => true
    ];

    protected $_hidden = [
        'password'
    ];
}

The UsersTable has an association to the UsersDetails table:

$this->hasOne('UsersDetails', [
    'foreignKey' => 'id',
    'joinType' => 'INNER'
]);

How can I make it work?

UPDATE: changed the belongsTo to hasOne

rename users_details to users_detail as its belongsTo

https://book.cakephp.org/3.0/en/orm/saving-data.html#saving-belongsto-associations

When saving belongsTo associations, the ORM expects a single nested entity named with the singular

when in doubt how your post structure should looks like you can always get record first and take a peek

$user = $this->Users->findById(1)->contain(['UsersDetails'])->first();
dd($user);

Doing this results in the error:

The UsersDetails association is not defined on Users.

Last time I encountered this issue I forgot to load the model (which I did this time).

sounds like wrong namespace / filename / letter casing

<?php
namespace Kikioboeru\Kikioboeru\Model\Table;

class UsersDetailsTable extends Table {
...

Loaded in the controller with:

$this->loadModel('Kikioboeru/Kikioboeru.UsersDetails');

you are loading UsersDetails and trying to use Users table?

I also have the Users Table loaded.
Like I said in the OP, I want to create a new user entity for the username, password and email and have associated data inserted into the UsersDetails table (the firstname and lastname of the user)

So I have some progress.
$this->Users has no associations at all (even though specified in the UsersTable).

dd($this->Users);

results in:

Table {#239 
  +"registryAlias": "Users"
  +"table": "users"
  +"alias": "Users"
  +"entityClass": "Cake\ORM\Entity"
  +"associations": []
  +"behaviors": []
  +"defaultConnection": "default"
  +"connectionName": "default"
}

however, TableRegistry::get('Kikioboeru/Kikioboeru.Users') does have associations:

$usersTable = TableRegistry::get('Kikioboeru/Kikioboeru.Users');
dd($usersTable);

results in:

UsersTable {#272 
  +"registryAlias": "Kikioboeru/Kikioboeru.Users"
  +"table": "users"
  +"alias": "Users"
  +"entityClass": "Kikioboeru\Kikioboeru\Model\Entity\User"
  +"associations": array:3 [
    0 => "articles"
    1 => "roles"
    2 => "usersdetails"
  ]
  +"behaviors": array:1 [
    0 => "Timestamp"
  ]
  +"defaultConnection": "default"
  +"connectionName": "default"
}

Is this a bug in CakePHP or?

For those wondering, this is my initialize method:

public function initialize() {
      parent::initialize();

      $this->loadModel('Kikioboeru/Kikioboeru.Users');
      $this->loadModel('Kikioboeru/Kikioboeru.UsersDetails');
      $this->loadModel('Kikioboeru/Kikioboeru.ResetTokens');
      $this->loadModel('Kikioboeru/Kikioboeru.AuthTokens');
}

Using the TableRegistry (instead of $this->Users) as shown above does make the issue go away.
Could somebody explain me why, even though I loaded the model it uses a completely different model instead?
It seems to have used some build-in model(?) instead of the one I specified in my controller.

whats in parent::initialize() ? maybe you already have loaded Users table before loading your plugin Users table version

Can you can use setProperty (or propertyName in array) to the relation to try force the association to be saved?

How about

$userData =[
    'username' => $this->request->getData('username'),
    'email' => $this->request->getData('email'),
    'password' => $this->request->getData('password'),
    'created' => date("Y-m-d H:i:s"),
    'users_details' => [
        'firstname' => '',
        'lastname' => ''
    ]
];

$user = $this->Users->newEntity($userData, [‘associated’ => ‘UserDetails’]);
pr($user);

There is one note of $this->loadModel('Users'); in the plugin’s AppController!
Unfortunately, I’ll have to try this out tomorrow when I have access to my workstation again.
Will report back!

Jepp, this seemed to be the issue…

I have updated the “rules” of the project to prevent these issues down the road.