[solved] Saving entity with "custom" id

#1

Hii there,

I’m trying to import users and data into my app.
The data for a user is build and saved like this:

$data = [
        'id' => $user['ID'],
        'username' => $user['user_nicename'],
        'email' => $user['user_email'],
        'password' => $user['user_pass'],
        'created' => $user['user_registered'],
        'users_detail' => [
          'firstname' => $user['user_nicename'],
          'lastname' => ''
        ],
        'roles' => [
          ['id' => $memberRole->id]
        ]
];
$usersEntity = $usersTable->newEntity($data);
$usersTable->save($usersEntity);

The user is inserted just fine except with one issue: the id is just plainly ignored and keeps following the autoincrement from the database.
Is there a way to insert the user with the proper ID?
Just rolling with it like this will complicate matters a lot as now the data from the other tables I need to migrate won’t align with the users at all (eg. the user with id=3 in the database actually is known with id=9, the one with id=4 in the database actually is known with id=29 etc.)

#2

adding $usersEntity->id = $user['ID']; before saving it does the trick

#3

The default code baked for you will exclude the primary key from being assigned in a patch call. Look at the _accessible property in your entity. There’s good security reasons to leave it like that most of the time; see Bypassing Field Guarding for a solution that might work well for your use case.

#4

This might be a cleaner way of doing it yes :slight_smile:
I’ll test it out when I’m back at the office tomorrow.

#5

Seems to work fine as well :slight_smile:

#6

A word of warning if you allow the ID column to be mass assigned… If you have an action: ‘add’ controller/view that has the ID as a text input, and you submit the form with the same ID as an existing record in your table - that record will be overwritten without warning.
The approach I use now is the same as your first answer…

$entity->id = $data[‘id’];

However, I run a select to check for an existing record with the same ID forst in my controller - which allows my to return a validation error.

Just for context, my use case was dealing with Products (like ecommerce), and the Product SKU is a natural key usually, so I wanted to SKU to be the entity ID.

#7

This is why you’d want to leave the _accessible property set as it is by default, and use the one-time bypass method from my link only in specific cases like the OP has, where the data is all built from a trusted source.

1 Like
#8

Yea, it’s only a “one-time” thing because I had to import data (like users, blogposts, comments etc.) from my live website into my CakePHP app :slight_smile: