Laravel 6.x - 'create()' 使用数据库默认值的记录

Laravel 6.x - 'create()' record using DataBase DEFAULT values

我有一个简单的 MySQL 数据库 table 像这样:

mysql> show create table provenance;
| provenance | CREATE TABLE `provenance` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Unique incremental id',
  `name` char(255) NOT NULL DEFAULT 'AUTO-ADDED',
  `instance` char(255) NOT NULL,
  `username` char(255) DEFAULT NULL COMMENT 'User name',
  `priority` int(11) NOT NULL DEFAULT '0' COMMENT 'Provenance priority',
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `inserted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=2869 DEFAULT CHARSET=latin1 COMMENT='Provenance' |
mysql> 

如您所见,有 DEFAULT 值的字段:namepriority.

Laravel 模型 类似于:

class ProvenanceModel extends Model
{
    protected $table = 'provenance';
    protected $fillable = [
        'name',
        'instance',
        'username',
        'priority'
    ];
}

控制器

class ProvenanceController extends Controller
{
    public function myStore($array)
    {
        return ProvenanceModel::firstOrCreate(
            [
                'name'          => $array['name'],
                'instance'      => $array['instance'],
                'username'      => $array['username'],
                'priority'      => $array['priority'],
            ]
        );
    } 
}

问题是输入 $array[] 不能包含 namepriority(它们是从具有 DEFAULT 的数据库设置的)。

但是我如何更改我的代码以避免错误,例如,因为 $array['name'] 不存在?

一个想法可能是将 Controller 代码更改为:

class ProvenanceController extends Controller
{
    public function myStore($array)
    {
        return ProvenanceModel::firstOrCreate(
            [
                'name'          => $array['name'] ?? 'AUTO-ADDED',
                'instance'      => $array['instance'],
                'username'      => $array['username'],
                'priority'      => $array['priority'] ?? 0,
            ]
        );
    } 
}

但是如果我在 DB 上更改 DEFAULT,我需要更改 PHP 代码,我不喜欢这样。

有没有办法使用DEFAULT数据库值如果字段没有通过?

谢谢。

Laravel 无法知道数据库在构造查询时的默认设置。

您最好的选择是将 firstOrCreate 分成 2 个调用:

$model = ProvenanceModel::where($attributes)->first();

if (is_null($model)) {
    $model = ProvenanceModel::create([
        ...
        // non-default attributes
        ...
    ]);
}

return $model;

在@prgrm 评论之后,解决方案是插入到 ProvenanceModel::create() 方法中,只有在输入中收到的字段。

例如:

class ProvenanceController extends Controller
{
    public function myStore($array)
    {
        isset($array['name']) ? $secondArray['name'] = $array['name'] : null;
        isset($array['instance']) ? $secondArray['instance'] = $array['instance'] : null;
        isset($array['username']) ? $secondArray['username'] = $array['username'] : null;
        isset($array['priority']) ? $secondArray['priority'] = $array['priority'] : null;

        return ProvenanceModel::firstOrCreate($secondArray);
    } 
}

然后,如果 $array['name'] 未设置,$secondArray 将是:

$secondArray[
    'instance' => '<value>'
    'username' => '<value>'
    'priority' => '<value>'
]

name 字段将填充 DEFAULT MySQL 值,'AUTO-ADDED'.


在一行中完成而不构建 $secondArray():

class ProvenanceController extends Controller
{
    public function myStore($array)
    {
        return ProvenanceModel::firstOrCreate(
            [
                isset($array['name']) ? 'name' : 'xx' => $array['name'] ?? null,
                isset($array['instance']) ? 'instance' : 'xx' => $array['instance'] ?? null,
                isset($array['username']) ? 'username' : 'xx' => $array['username'] ?? null,
                isset($array['priority']) ? 'priority' : 'xx' => $array['priority'] ?? null,
            ]
        );
    } 
}

那么如果 $array['name'] 没有设置它将是:

        return ProvenanceModel::firstOrCreate(
            [
                'xx' => null,
                'instance' => <value>,
                'username' => <value>,
                'priority' => <value>,
            ]
        );

xx 字段不在 $fillable 数组中,不会在 INSERT 语句中使用。