[Laravel 5.3 新功能] 3. Eloquent 方法 FirstOrCreate 增加新参数
8

说明

此文章是 [Laravel 5.3 新功能] 系列的第三篇文章,Eloquent 方法 FirstOrCreate 增加新参数。

[Laravel 5.3 新功能] 系列完整文章列表请见:https://laravel-china.org/topics/2638

FirstOrCreate 介绍

Eloquent 的 firstOrCreate() 可以接收一个数组类型的参数,根据传入的参数检查 Eloquent 对应的属性是否存在,并执行以下逻辑:

  1. 属性如存在,则返回该实例;
  2. 属性如不存在,则先创建它,再返回创建的实例。

5.3 之前,firstOrCreate() 的局限性

首先我们先创建如下代码:

$user = User::firstOrCreate(['name' => 'phphub-monkey']);

上面的代码将先判断 User 里是否有 name 为 phphub-monkey 的对象,如果没有则创建此对象。

在通常情况下,我们在创建用户时不会只生成 name 数据,同时还需生成邮箱 (email)、头像 (avatar)、性别 (gender) 等数据。在 5.3 之前,我们只能这样写:

$user = User::firstOrCreate([
    'name' => 'phphub-monkey', 
    'email' => 'jin114001251@gmail.com',
    'avatar' => 'http://....',
    'gender' => 'male',
]);

这样看起来没什么问题,运行后数据貌似也能正常生成,但实际上,上文代码运行的查询语句如下:

select * from `users` where `users`.`deleted_at` is null and 
(
    `name` = 'phphub-monkey' 
    and `email` = 'jin114001251@gmail.com' 
    and `avatar` = 'http://......' 
    and `gender` = 'male'
) limit 1

可以看出,这条查询语句是不符合我们要求的,它会认为只有同时满足四个条件,才能确认此用户存在。其实只要查出 name 为 phphub-monkey 的数据存在,就可认定此用户已经存在,无需再生成数据。

可能引起的不良后果

如果用户表已经存在 name 为 phphub-monkey,但是 email 为 phphub@phphub.com 的用户,程序依旧认为此用户不存在,会直接创建 phphub-monkey 用户,导致数据表里出现两个 phphub-monkey 用户,或者直接报错(如果 name 字段设置为 unique 的话)。

5.3 的解决方案

现在,在 5.3 中我们可以这么写:

$user = User::firstOrCreate(
    ['name' => 'phphub-monkey'],
    [
        'email' => 'jin114001251@gmail.com',
        'avatar' => 'http://....',
        'gender' => 'male',
    ]
]);

这样一来,程序只会查询 name 为 phphub-monkey 的数据是否存在,如果不存在,才将 name, email, avatar, gender 数据一并生成。

一句话总结

在 5.3 里,firstOrCreate() 有两个数组类型的参数:

  • 第一个参数用于确认 Eloquent 对象是否存在;
  • 第二个参数用于生成 Eloquent 对象时需要附加生成的属性。

全文完。

链接

本帖已被设为精华帖!
本帖由系统于 2年前 自动加精
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 6

如果要同时确认用户名和邮箱是不是在5.3里面这样写就对了:

$user = User::firstOrCreate(
    [
        'name' => 'phphub-monkey',
        'email' => 'jin114001251@gmail.com'
    ],
    [
        'email' => 'jin114001251@gmail.com',
        'avatar' => 'http://....',
        'gender' => 'male',
    ]
]);
2年前

对的,以前用5.2的时候,就很纠结,如果传入全部需要创建的数据进去的话,则就要全部满足,不符合需求,所以每次就又都重新判断了一遍

2年前

很棒棒哦

1年前

刚开始学laravel5.2就发现firstOrCreate()有问题

1年前

我试了下,laravel5.2也可以传两个参数

1年前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!