蛋糕 3:如何向设置了主键的数据库添加新实体?
Cake 3: How to add new entity to database with primaryKey set?
我想用从 excel sheet 中提取的 'flat' 数据填充我的数据库。所有记录都以数组形式提供(类似于 $request->data),但它们的主键设置了必须保留的值。
我的代码:
$imported = 0;
foreach ($data as $record) {
$entity = $table->findOrCreate([$table->primaryKey() => $record[$table->primaryKey()]]);
$entity = $table->patchEntity($entity, $record);
if ($table->save($entity)) {
$imported++;
}
}
代码可以运行,但我想知道是否有更好的解决方案?
澄清一下:我想要的是添加类似
的内容
[
['id' => 25, 'title'=>'some title'],
['id'=> 3, 'title' => 'some other title'],
['id' => 4356, 'title' => 'another title']
]
到我的空数据库。 findOrCreate() 完成这项工作。但我认为没有必要在插入之前测试数据库中不存在的每条记录。
如果您真的只使用空表,那么您可以直接保存数据,无需查找和修补,只需禁用存在性检查即可保存。
另外,从您的代码来看,数据的格式似乎可以立即转换为实体,因此您可能希望一次创建它们。
$entities = $table->newEntities($data, [
// don't forget to restrict assignment one way or
// another when working with external input, for
// example by using the `fieldList` option
'fieldList' => [
'id',
'title'
]
]);
// you may want to check the validation results here before saving
foreach ($entities as $entity) {
if ($table->save($entity, ['checkExisting' => false])) {
// ...
}
// ...
}
另见
记录神秘地丢失了一些提供给新 Entity
的数据的一个常见问题是实体没有将相关字段定义为 _accessible
。
Cake 的 BakeShell 会在为您生成新实体 classes 时跳过主键字段,例如:
<?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,
];
}
有几种方法可以解决这个问题。
您可以修改您的实体 class 以使 id
字段永久 可分配:
protected $_accessible = [
'id' => true, // Now `id` can always be mass-assigned.
'title' => true,
];
或者您可以调整对 newEntity()
的调用以禁用批量分配保护:
$entities = $table->newEntity($data, [
'accessibleFields' => ['id' => true],
]);
我发现,当您遇到 Cake 3 DB 数据问题时,最重要的收获是在创建或修补实体后立即仔细检查实体,并将其与您的输入数据进行比较。你仍然需要有敏锐的眼光,但这样做会发现实体根本没有设置 ->id
属性,即使 $data
定义了它们。
我想用从 excel sheet 中提取的 'flat' 数据填充我的数据库。所有记录都以数组形式提供(类似于 $request->data),但它们的主键设置了必须保留的值。 我的代码:
$imported = 0;
foreach ($data as $record) {
$entity = $table->findOrCreate([$table->primaryKey() => $record[$table->primaryKey()]]);
$entity = $table->patchEntity($entity, $record);
if ($table->save($entity)) {
$imported++;
}
}
代码可以运行,但我想知道是否有更好的解决方案?
澄清一下:我想要的是添加类似
的内容 [
['id' => 25, 'title'=>'some title'],
['id'=> 3, 'title' => 'some other title'],
['id' => 4356, 'title' => 'another title']
]
到我的空数据库。 findOrCreate() 完成这项工作。但我认为没有必要在插入之前测试数据库中不存在的每条记录。
如果您真的只使用空表,那么您可以直接保存数据,无需查找和修补,只需禁用存在性检查即可保存。
另外,从您的代码来看,数据的格式似乎可以立即转换为实体,因此您可能希望一次创建它们。
$entities = $table->newEntities($data, [
// don't forget to restrict assignment one way or
// another when working with external input, for
// example by using the `fieldList` option
'fieldList' => [
'id',
'title'
]
]);
// you may want to check the validation results here before saving
foreach ($entities as $entity) {
if ($table->save($entity, ['checkExisting' => false])) {
// ...
}
// ...
}
另见
记录神秘地丢失了一些提供给新 Entity
的数据的一个常见问题是实体没有将相关字段定义为 _accessible
。
Cake 的 BakeShell 会在为您生成新实体 classes 时跳过主键字段,例如:
<?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,
];
}
有几种方法可以解决这个问题。
您可以修改您的实体 class 以使 id
字段永久 可分配:
protected $_accessible = [
'id' => true, // Now `id` can always be mass-assigned.
'title' => true,
];
或者您可以调整对 newEntity()
的调用以禁用批量分配保护:
$entities = $table->newEntity($data, [
'accessibleFields' => ['id' => true],
]);
我发现,当您遇到 Cake 3 DB 数据问题时,最重要的收获是在创建或修补实体后立即仔细检查实体,并将其与您的输入数据进行比较。你仍然需要有敏锐的眼光,但这样做会发现实体根本没有设置 ->id
属性,即使 $data
定义了它们。