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

时间:2019-11-14 10:32:54

标签: php mysql laravel eloquent laravel-6

我有一个简单的MySQL数据库表,如下所示:

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,
            ]
        );
    } 
}

但是如果我更改数据库上的 DEFAULT ,我需要更改PHP代码,我不喜欢这样。

如果未传递该字段,是否可以使用 DEFAULT 数据库值?

谢谢。

2 个答案:

答案 0 :(得分:0)

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

您最好的选择是将firstOrCreate分为2个通话:

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

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

return $model;

答案 1 :(得分:0)

在@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语句中使用。