你应该知道的 7 个 Laravel 最佳实践

Laravel

每个 web 开发人员在写代码时都有自己的风格。与此同时,如果我们使用 Laravel 框架,一切都准备就绪,但通常我们在这里误用了术语。 涉及不同的风格问题不大,但我们必须确保我们的代码遵循良好的风格。这意味着我们的代码必须可扩展,可维护和可测试。

是什么让我们的代码变得糟糕或者良好?因为PHP是一种面向对象的语言,我们应该遵循面向对象的原则,如 SOLID 设计原则,并考虑使用面向对象机制,如继承,抽象等。此外,Laravel有一个大社区,有时会有一些社区创造的约定。因此,其他遵循这些约定的 laravel 开发人员能够更好地、更快地理解我们的代码。在本文中,我将根据面向对象原则和一些 Laravel 社区约定,在 Laravel 上向你展示7个最佳实践。

1.胖模型,瘦控制器

如果我们有一个非常复杂的查询构造器或原始 SQL语句,我们应该将此查询移动到模型或仓库中。

坏的:

<?php
public function index()
{
    $partners = Partner::where('email_verified_at', '!=', null)
        ->with(['products' => function ($q) {
            $q->whereDate('created_at', now());
        }])
        ->get();

    return view('index', ['partners' => $partners]);
}

好的:

<?php
public function index()
{
    return view('index', ['partners' => $this->partner->newProducts()]);
}

class Partner extends Model
{
    public function newProducts()
    {
        return $this->where('email_verified_at', '!=', null)
            ->with(['products' => function ($q) {
                $q->whereDate('created_at', now());
            }])
            ->get();
    }
}

2.服务类中的业务逻辑

与上述第一点相关,我们应该有一个瘦控制器,然后我们应该将所有业务逻辑移动到单独的服务类中。 所以控制器应该只有一个职责,希望我们可以在其他控制器中重用这个服务。

坏的:

<?php
public function store(Request $request)
{
    $user = User::create();

    $user->update(['last_login' => now()]);

    dispatch(new UserCreated($user));

    // ...
}

好的:

<?php
public function store(Request $request)
{
    $this->userService->create($request);

    ....
}

class UserService
{
    public function create($request)
    {
       // ...
    }
}

3.Eloquent 查询优于原生 SQL 语句。

使用 Eloquent 进行查询更具可读性,避免 SQL 注入,并且易于维护。

坏的:

<?php
SELECT *
FROM `articles`
WHERE EXISTS (SELECT *
              FROM `users`
              WHERE `articles`.`user_id` = `users`.`id`
              AND EXISTS (SELECT *
                          FROM `profiles`
                          WHERE `profiles`.`user_id` = `users`.`id`) 
              AND `users`.`deleted_at` IS NULL)
AND `verified` = '1'
AND `active` = '1'
ORDER BY `created_at` DESC

好的:

<?php
Article::has('user.profile')->verified()->latest()->get();

4.DRY (Don’t Repeat Yourself)

我们应该考虑将可重用的逻辑/组件部分移动到单独的地方。
在 blade 模板中,我们可以使用组件来重用前端部分。在服务器中,我们可以将逻辑移动到一个单独的服务类、Eloquent scope作用域,甚至可以创建我们自己的包。

<!DOCTYPE html>
<html>
<head>
<title>DRY</title>
</head>
<body>

<h1>Custom Calendar</h1>

<x-custom-calendar>

</body>
</html>

5.不要在 Blade 模板中执行查询

尽管在 blade 模板中执行查询是可行的, 但最好不要这么做。

坏的。 将会造成 N+1 问题。

@foreach (User::all() as $user)
    {{ $user->email }}
@endforeach

好的:

$users = User::all(); // Server Query
@foreach ($users as $user)
    {{ $user->email }}
@endforeach

6.使用数据库事务

如果我们有一些复杂而冗长的逻辑/查询,那么我们应该考虑使用数据库事务。通过使用此功能,我们可以在需要时轻松回滚数据库,以确保我们的数据不会保存到数据库中,因此我们确信我们的数据是可靠的。

<?php
public function store(Request $request)
{
    DB::beginTransaction();
    $user = User::create();
    $response = app('service')->create($user);

    if (!$response) {
      DB::rollback();
      return;
    }
    // ...
    DB::commit();
 }

7.不要硬编码文本

我们不应该在代码/控制器中硬编码任何文本。这样以后很容易维护和扩展。如果我们想向用户显示消息,我们可以使用翻译,模型/类中的常量来设置任何值或配置文件来保存我们的配置。

trans('user.created'); // 'User Successfully Created'
$types = Product::TYPES; // Const in a Class/Model
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://cerwyn.medium.com/7-best-practic...

译文地址:https://learnku.com/laravel/t/67021

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 10

It’s the same if we’re working using the Laravel framework where everything is in place but usually we misused the terminology here.

这一句话不管是谷歌翻译还是自己翻都感觉翻的不通顺,希望各位英文大佬能帮忙翻一下。 以下是上下文:

Every web developer has its own style when it comes to writing codes. It’s the same if we’re working using the Laravel framework where everything is in place but usually we misused the terminology here.

2年前 评论
诺墨 2年前
Moonshadow2333 (作者) 2年前
诺墨 2年前

道理我都懂,一到用的时候就废了

2年前 评论
啵啵 1年前
啵啵 1年前
她来听我的演唱会 1年前
<?php
public function store(Request $request)
{
    $this->userService->create($request);

    ....
}

class UserService
{
    public function create($request)
    {
       // ...
    }
}

这个依然有问题,UserService 中不应该和具体的业务耦合,也就是说把 $request 作为请求参数传递,会导致该 Service 只能处理请求相关的业务逻辑,如果该业务逻辑在异步队列或者调度任务中也能用到呢?那么哪里拿到请求实例?

$users = User::all(); // Server Query
@foreach ($users as $user)
    {{ $user->email }}
@endforeach

这么写依然存在 N+1 的问题,治标不治本

1年前 评论
lqalbert 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!