目录
1. 递增和递减
2. 先执行 X 方法,X 方法执行不成功则执行 Y 方法
3. 模型的 boot() 方法
4. 带条件与排序的关联关系
5. 模型特性:时间、追加等
6. 通过 ID 查询多条记录
7. WhereX
8. 通过关系排序
9. Eloquent::when() -- 不再使用 if-else
10. 一对多返回默认模型对象
11. 通过赋值函数进行排序
12. 全局作用域下的默认排序
13. 原生查询方法
14. 复制:复制一行的副本
15. Chunk() 方法之大块数据
16. 创建模型时创建额外的东西
17. 调用 save 方法的时候指定 updated_at
18. update() 的结果是什么?
19. 把括号转换成 Eloquent 查询
20. 复数参数的 orWhere
首页 php框架 Laravel 常用的 Laravel Eloquent 必备的实用技巧

常用的 Laravel Eloquent 必备的实用技巧

Jun 13, 2020 pm 06:24 PM

常用的 Laravel Eloquent 必备的实用技巧

Eloquent ORM 看起来是一个简单的机制,但是在底层,有很多半隐藏的函数和鲜为人知的方式来实现更多功能。在这篇文章中,我将演示几个小技巧。

1. 递增和递减

要代替以下实现:

1

2

3

$article = Article::find($article_id);

$article->read_count++;

$article->save();

登录后复制

你可以这样做:

1

2

$article = Article::find($article_id);

$article->increment('read_count');

登录后复制

以下这些方法也可以实现:

1

2

3

Article::find($article_id)->increment('read_count');

Article::find($article_id)->increment('read_count', 10); // +10

Product::find($produce_id)->decrement('stock'); // -1

登录后复制

2. 先执行 X 方法,X 方法执行不成功则执行 Y 方法

Eloquent 有相当一部分函数可以把两个方法结合在一起使用, 例如 『 请先执行 X 方法,  X 方法执行不成功则执行 Y 方法 』。

实例 1 -- findOrFail():

要替代以下代码的实现:

1

2

$user = User::find($id);

if (!$user) { abort (404); }

登录后复制

你可以这样写:

1

$user = User::findOrFail($id);

登录后复制

实例 2 -- firstOrCreate():

要替代以下代码的实现:

1

2

3

4

5

6

$user = User::where('email'$email)->first();

if (!$user) {

  User::create([

    'email' => $email

  ]);

}

登录后复制

这样写就可以了:

1

$user = User::firstOrCreate(['email' => $email]);

登录后复制

3. 模型的 boot() 方法

在一个 Eloquent 模型中,有个神奇的地方,叫 boot(),在那里,你可以覆盖默认的行为:

1

2

3

4

5

6

7

8

9

10

11

12

class User extends Model

{

    public static function boot()

    {

        parent::boot();

        static::updating(function($model)

        {

            // 写点日志啥的

            // 覆盖一些属性,类似这样 $model->something = transform($something);

        });

    }

}

登录后复制

在创建模型对象时设置某些字段的值,大概是最受欢迎的例子之一了。 一起来看看在创建模型对象时,你想要生成 UUID 字段 该怎么做。

1

2

3

4

5

6

7

public static function boot()

{

  parent::boot();

  self::creating(function ($model) {

    $model->uuid = (string)Uuid::generate();

  });

}

登录后复制

4. 带条件与排序的关联关系

定义关联关系的一般方式:

1

2

3

public function users() {

    return $this->hasMany('App\User');

}

登录后复制

你知道吗?也可以在上面的基础上增加 where 或者 orderBy?\
举个例子,如果你想关联某些类型的用户,同时使用 email 字段排序,你可以这样做:

1

2

3

public function approvedUsers() {

    return $this->hasMany('App\User')->where('approved', 1)->orderBy('email');

}

登录后复制

5. 模型特性:时间、追加等

Eloquent模型有些参数,使用类的属性形式。最常用是:

1

2

3

4

5

6

class User extends Model {

    protected $table 'users';

    protected $fillable = ['email''password']; // 可以被批量赋值字段,如 User::create() 新增时,可使用字段

    protected $dates = ['created_at''deleted_at']; // 需要被Carbon维护的字段名

    protected $appends = ['field1''field2']; // json返回时,附加的字段

}

登录后复制

不只这些,还有:

1

2

3

4

5

6

protected $primaryKey 'uuid'// 更换主键

public $incrementing = false; // 设置 不自增长

protected $perPage = 25; // 定义分页每页显示数量(默认15)

const CREATED_AT = 'created_at';

const UPDATED_AT = 'updated_at'//重写 时间字段名

public $timestamps = false; // 设置不需要维护时间字段

登录后复制

还有更多,我只列出了一些有意思的特性,具体参考文档 abstract Model class 了解所有特性.

6. 通过 ID 查询多条记录

所有人都知道  find()  方法,对吧?

1

$user = User::find(1);

登录后复制

我十分意外竟然很少人知道这个方法可以接受多个 ID 的数组作为参数:

1

$users = User::find([1,2,3]);

登录后复制

7. WhereX

有一种优雅的方式能将这种代码:

1

$users = User::where('approved', 1)->get();

登录后复制

转换成这种:

1

$users = User::whereApproved(1)->get();

登录后复制

对,你没有看错,使用字段名作为后缀添加到 where 后面,它就能通过魔术方法运行了。

另外,在 Eloquent 里也有些和时间相关的预定义方法:

1

2

3

4

User::whereDate('created_at'date('Y-m-d'));

User::whereDay('created_at'date('d'));

User::whereMonth('created_at'date('m'));

User::whereYear('created_at'date('Y'));

登录后复制

8. 通过关系排序

一个复杂一点的「技巧」。你想对论坛话题按最新发布的帖子来排序?论坛中最新更新的主题在最前面是很常见的需求,对吧?

首先,为主题的最新帖子定义一个单独的关系:

1

2

3

4

public function latestPost()

{

    return $this->hasOne(\App\Post::class)->latest();

}

登录后复制

然后,在控制器中,我们可以实现这个「魔法」:

1

$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');

登录后复制

9. Eloquent::when() -- 不再使用 if-else

很多人都喜欢使用"if-else"来写查询条件,像这样:

1

2

3

4

5

6

if (request('filter_by') == 'likes') {

    $query->where('likes''>', request('likes_amount', 0));

}

if (request('filter_by') == 'date') {

    $query->orderBy('created_at', request('ordering_rule''desc'));

}

登录后复制

有一种更好的方法 -- 使用 when()

1

2

3

4

5

6

7

$query = Author::query();

$query->when(request('filter_by') == 'likes'function ($q) {

    return $q->where('likes''>', request('likes_amount', 0));

});

$query->when(request('filter_by') == 'date'function ($q) {

    return $q->orderBy('created_at', request('ordering_rule''desc'));

});

登录后复制

它可能看上去不是很优雅,但它强大的功能是传递参数:

1

2

3

4

5

$query = User::query();

$query->when(request('role', false), function ($q$role) {

    return $q->where('role_id'$role);

});

$authors $query->get();

登录后复制

10. 一对多返回默认模型对象

假设现在有种情况是要显示文章的作者,然后模板代码是:

1

{{ $post->author->name }}

登录后复制

但是如果作者的信息被删除或者因为某些原因没有被设置。代码会返回一个错误,诸如 "property of non-object"。

当然你可以这样处理:

1

{{ $post->author->name ?? '' }}

登录后复制

你可以通过 Eloquent 关系这样做:

1

2

3

4

public function author()

{

    return $this->belongsTo('App\Author')->withDefault();

}

登录后复制

在此示例中,如果文字没有作者的信息, author() 会返回一个空的 App\Author 模型对象。

再者,我们也可以给默认的模型对象里面的属性赋默认值。

1

2

3

4

5

6

public function author()

{

    return $this->belongsTo('App\Author')->withDefault([

        'name' => 'Guest Author'

    ]);

}

登录后复制

11. 通过赋值函数进行排序

想象一下你有这样的代码:

1

2

3

4

function getFullNameAttribute()

{

  return $this->attributes['first_name'] . ' ' $this->attributes['last_name'];

}

登录后复制

现在,你想要通过 "full_name" 进行排序? 发现是没有效果的:

1

$clients = Client::orderBy('full_name')->get(); //没有效果

登录后复制

解决办法很简单.我们需要在获取结果后对结果进行排序.

1

$clients = Client::get()->sortBy('full_name'); // 成功!

登录后复制

注意的是方法名称是不相同的 -- 它不是orderBy,而是sortBy

12. 全局作用域下的默认排序

如果你想要 User::all() 总是按照 name 字段来排序呢? 你可以给它分配一个全局作用域。让我们回到 boot() 这个我们在上文提到过的方法:

1

2

3

4

5

6

7

8

9

protected static function boot()

{

    parent::boot();

 

    // 按照 name 正序排序

    static::addGlobalScope('order'function (Builder $builder) {

        $builder->orderBy('name''asc');

    });

}

登录后复制

扩展阅读 查询作用域 。

13. 原生查询方法

有时候,我们需要在 Eloquent 语句中添加原生查询。 幸运的是,确实有这样的方法。

1

2

3

4

5

6

7

8

9

10

11

12

// whereRaw

$orders = DB::table('orders')

    ->whereRaw('price > IF(state = "TX", ?, 100)', [200])

    ->get();

 

// havingRaw

Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();

 

// orderByRaw

User::where('created_at''>''2016-01-01')

  ->orderByRaw('(updated_at - created_at) desc')

  ->get();

登录后复制

14. 复制:复制一行的副本

很简单。说明不是很深入,下面是复制数据库实体(一条数据)的最佳方法:

1

2

3

$task = Tasks::find(1);

$newTask $task->replicate();

$newTask->save();

登录后复制

15. Chunk() 方法之大块数据

与 Eloquent 不完全相关,它更多的关于 Collection (集合),但是对于处理大数据集合,仍然是很有用的。你可以使用 chunk() 将这些数据分割成小数据块

修改前:

1

2

3

$users = User::all();

foreach ($users as $user) {

    // ...

登录后复制

你可以这样做:

1

2

3

4

5

User::chunk(100, function ($users) {

    foreach ($users as $user) {

        // ...

    }

});

登录后复制

16. 创建模型时创建额外的东西

我们都知道Artisan命令:

1

php artisan make:model Company

登录后复制

但是,你知道有三个有用的标记可以为模型生成相关文件吗?

1

php artisan make:model Company -mcr

登录后复制
  • -m 将创建一个迁移文件

  • -c 将创建一个控制器

  • -r 表示控制器应该是一个资源控制器

17. 调用 save 方法的时候指定 updated_at

你知道  ->save() 方法可以接受参数吗? 我们可以通过传入参数阻止它的默认行为:更新  updated_at  的值为当前时间戳。

1

2

3

$product = Product::find($id);

$product->updated_at = '2019-01-01 10:00:00';

$product->save(['timestamps' => false]);

登录后复制

这样,我们成功在  save  时指定了  updated_at  的值。

18. update() 的结果是什么?

你是否想知道这段代码实际上返回什么?

1

$result $products->whereNull('category_id')->update(['category_id' => 2]);

登录后复制

我是说,更新操作是在数据库中执行的,但 $result 会包含什么?

答案是受影响的行。 因此如果你想检查多少行受影响, 你不需要额外调用其他任何内容 -- update() 方法会给你返回此数字。

19. 把括号转换成 Eloquent 查询

如果你有个 andor 混合的 SQL 查询,像这样子的:

1

... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)

登录后复制

怎么用 Eloquent 来翻译它呢? 下面是一种错误的方式:

1

2

3

4

$q->where('gender''Male');

$q->orWhere('age''>=', 18);

$q->where('gender''Female');

$q->orWhere('age''>=', 65);

登录后复制

顺序就没对。正确的打开方式稍微复杂点,使用闭包作为子查询:

1

2

3

4

5

6

7

$q->where(function ($query) {

    $query->where('gender''Male')

        ->where('age''>=', 18);

})->orWhere(function($query) {

    $query->where('gender''Female')

        ->where('age''>=', 65);

})

登录后复制

20. 复数参数的 orWhere

终于,你可以传递阵列参数给 orWhere()。平常的方式:

1

2

3

$q->where('a', 1);

$q->orWhere('b', 2);

$q->orWhere('c', 3);

登录后复制

你可以这样做:

1

2

$q->where('a', 1);

$q->orWhere(['b' => 2, 'c' => 3]);

登录后复制

我很确定还有更多隐藏的秘诀,但我希望至少上面的其中一些对你来说是新的。

推荐教程:《Laravel教程

以上是常用的 Laravel Eloquent 必备的实用技巧的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
<🎜>掩盖:探险33-如何获得完美的色度催化剂
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1676
14
CakePHP 教程
1429
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
laravel入门实例 laravel入门实例 Apr 18, 2025 pm 12:45 PM

Laravel 是一款 PHP 框架,用于轻松构建 Web 应用程序。它提供一系列强大的功能,包括:安装: 使用 Composer 全局安装 Laravel CLI,并在项目目录中创建应用程序。路由: 在 routes/web.php 中定义 URL 和处理函数之间的关系。视图: 在 resources/views 中创建视图以呈现应用程序的界面。数据库集成: 提供与 MySQL 等数据库的开箱即用集成,并使用迁移来创建和修改表。模型和控制器: 模型表示数据库实体,控制器处理 HTTP 请求。

Laravel如何学习 怎么免费学习Laravel Laravel如何学习 怎么免费学习Laravel Apr 18, 2025 pm 12:51 PM

想要学习 Laravel 框架,但苦于没有资源或经济压力?本文为你提供了免费学习 Laravel 的途径,教你如何利用网络平台、文档和社区论坛等资源,从入门到掌握,为你的 PHP 开发之旅奠定坚实基础。

laravel框架安装方法 laravel框架安装方法 Apr 18, 2025 pm 12:54 PM

文章摘要:本文提供了详细分步说明,指导读者如何轻松安装 Laravel 框架。Laravel 是一个功能强大的 PHP 框架,它 упростил 和加快了 web 应用程序的开发过程。本教程涵盖了从系统要求到配置数据库和设置路由等各个方面的安装过程。通过遵循这些步骤,读者可以快速高效地为他们的 Laravel 项目打下坚实的基础。

laravel有哪些版本 laravel新手版本选择方法 laravel有哪些版本 laravel新手版本选择方法 Apr 18, 2025 pm 01:03 PM

在面向初学者的 Laravel 框架版本选择指南中,本文深入探讨了 Laravel 的版本差异,旨在协助初学者在众多版本之间做出明智的选择。我们将重点介绍每个版本的关键特征、比较它们的优缺点,并提供有用的建议,帮助新手根据他们的技能水准和项目需求挑选最合适的 Laravel 版本。对于初学者来说,选择一个合适的 Laravel 版本至关重要,因为它可以显著影响他们的学习曲线和整体开发体验。

laravel用户登录功能 laravel用户登录功能 Apr 18, 2025 pm 12:48 PM

Laravel 提供了一个全面的 Auth 框架,用于实现用户登录功能,包括:定义用户模型(Eloquent 模型)创建登录表单(Blade 模板引擎)编写登录控制器(继承 Auth\LoginController)验证登录请求(Auth::attempt)登录成功后重定向(redirect)考虑安全因素:哈希密码、防 CSRF 保护、速率限制和安全标头。此外,Auth 框架还提供重置密码、注册和验证电子邮件等功能。详情请参阅 Laravel 文档:https://laravel.com/doc

laravel怎么查看版本号 laravel查看版本号方法 laravel怎么查看版本号 laravel查看版本号方法 Apr 18, 2025 pm 01:00 PM

Laravel框架内置了多种方法来方便地查看其版本号,满足开发者的不同需求。本文将探讨这些方法,包括使用Composer命令行工具、访问.env文件或通过PHP代码获取版本信息。这些方法对于维护和管理Laravel应用程序的版本控制至关重要。

laravel和thinkphp的区别 laravel和thinkphp的区别 Apr 18, 2025 pm 01:09 PM

Laravel 和 ThinkPHP 都是流行的 PHP 框架,在开发中各有优缺点。本文将深入比较这两者,重点介绍它们的架构、特性和性能差异,以帮助开发者根据其特定项目需求做出明智的选择。

laravel8 的优化点 laravel8 的优化点 Apr 18, 2025 pm 12:24 PM

Laravel 8 针对性能优化提供了以下选项:缓存配置:使用 Redis 缓存驱动、缓存门面、缓存视图和页面片段。数据库优化:建立索引、使用查询范围、使用 Eloquent 关系。JavaScript 和 CSS 优化:使用版本控制、合并和缩小资产、使用 CDN。代码优化:使用 Composer 安装包、使用 Laravel 助手函数、遵循 PSR 标准。监控和分析:使用 Laravel Scout、使用 Telescope、监控应用程序指标。

See all articles