Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cake 3: How to add new entity to database with primaryKey set?

I want to populate my database with 'flat' data extracted from an excel sheet. All records are provided as arrays (similar to $request->data) but have their primaryKeys set which values must be kept. My code:

$imported = 0;  
foreach ($data as $record) {  
    $entity = $table->findOrCreate([$table->primaryKey() => $record[$table->primaryKey()]]);  
    $entity = $table->patchEntity($entity, $record);  
    if ($table->save($entity)) {  
        $imported++;  
    }  
}  

The code works, but I'm wondering if there is a better solution?

To clarify: What I want is adding something like

 [  
  ['id' => 25, 'title'=>'some title'],   
  ['id'=> 3, 'title' => 'some other title'],  
  ['id' => 4356,  'title' => 'another title']  
]  

to my empty database. findOrCreate() does the job. But I think it shouldn't be necessary to test every record that it not already exists in database before inserting.

like image 283
cewi Avatar asked Feb 06 '15 19:02

cewi


1 Answers

A common problem with records mysteriously losing some of the data being provided to a new Entity is that the Entity does not define the field(s) in question as _accessible.

Cake's BakeShell will skip the primary key fields when generating new Entity classes for you, for example:

<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

/**
 * Widget Entity.
 */
class Widget extends Entity {

    /**
     * Fields that can be mass assigned using newEntity() or patchEntity().
     *
     * @var array
     */
    protected $_accessible = [
        // `id` is NOT accessible by default!
        'title' => true,
    ];
}

There are a few ways to work around this.

You can modify your Entity class to make the id field permanently assignable:

    protected $_accessible = [
        'id' => true, // Now `id` can always be mass-assigned.
        'title' => true,
    ];

Or you can adjust your call to newEntity() to disable mass assignment protection:

$entities = $table->newEntity($data, [
    'accessibleFields' => ['id' => true],
]);

I've found the most important take-away when you're having issues with Cake 3 DB data is to double-check the Entity as soon as it's created or patched and compare it against your input data. You still need to have a sharp eye, but doing so would reveal that the Entities did not have their ->id property set at all even though $data defined them.

like image 98
beporter Avatar answered Sep 28 '22 08:09

beporter