主页/PHP笔记/PHP问答/框架Laravel/理解Eloquent中的作用域(含示例)

理解Eloquent中的作用域(含示例)

Bug编译狮

Bug编译狮

Eloquent中的作用域

作用域是Eloquent ORM的一个强大特性,它允许你在查询模型时应用自定义条件。通过使用作用域,你可以简化复杂的查询逻辑,并且提高代码的可读性和维护性。

什么是作用域?

作用域是一组方法,这些方法可以在查询模型时被调用。通过这些方法,你可以添加各种过滤、排序和分页等条件。

如何创建作用域?

  1. 定义作用域:在模型类中定义作用域的方法。
  2. 使用作用域:在查询模型时调用这些作用域方法。

示例代码

以下是一个简单的示例,展示了如何在Eloquent模型中定义和使用作用域。

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class Product extends Model
{
    // 定义作用域
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    public function scopeLatest($query)
    {
        return $query->latest();
    }
}

在这个示例中:

  • scopeActive 方法用于筛选出状态为“active”的产品。
  • scopeLatest 方法用于获取最新的产品。

在控制器中使用作用域

现在,我们可以使用这些作用域来构建查询。

namespace AppHttpControllers;

use AppModelsProduct;
use IlluminateHttpRequest;

class ProductController extends Controller
{
    public function index()
    {
        // 使用作用域进行查询
        $products = Product::active()->latest()->get();

        return view('products.index', compact('products'));
    }
}

在这个例子中,我们在控制器的 index 方法中使用了 scopeActivescopeLatest 作用域来构建查询。

总结

作用域是Eloquent ORM中非常有用的功能,它可以简化复杂的查询逻辑,并提高代码的可读性和维护性。通过定义和使用作用域,你可以更灵活地控制数据库查询的行为。

黑板Bug讲师

黑板Bug讲师

介绍

Laravel的Eloquent ORM提供了使用ActiveRecord实现数据库操作的美丽且简单的功能。其中一个不那么被讨论,但非常强大的特性,就是查询逻辑封装到方法中的范围(scopes)。范围允许您将部分查询逻辑封装为一个方法,然后可以在整个应用程序中重用该方法。在这篇教程中,我们将深入探讨Eloquent的范围概念,提供清晰的例子以巩固您的理解。您将学习到局部范围、全局范围以及如何在您的Laravel项目中应用它们。

什么是瞄准镜?

在Eloquent中,范围方法是在您的Eloquent模型类上定义的方法,用于添加约束以限制查询的这些模型。

局部作用域

本地作用域允许您定义一组公共查询约束,这些约束可以在应用程序的多个地方轻松重用。例如:

class Post extends Model {
    /**
     * Scope a query to only include active posts.
     */
    public function scopeActive($query) {
        return $query->where('active', 1);
    }
}

现在,你可以通过Eloquent模型的实例来使用这个范围:

$activePosts = Post::active()->get();

全球视野

全局作用域允许您对给定模型的所有查询添加约束。Laravel内置的软删除功能就是一个例子。自定义全局作用域如下所示:

use IlluminateDatabaseEloquentScope;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentBuilder;
class ActiveScope implements Scope {
    public function apply(Builder $builder, Model $model) 
    {
        $builder->where('active', '=', 1);
    }
}

现在,我们将我们的自定义全局作用域应用到模型上:

class Post extends Model {
    protected static function booted() {
        static::addGlobalScope(new ActiveScope);
    }
}

在适用的范围内,任何关于的查询都将在我的能力范围内处理。Post模型将自动应用激活的约束。

在现实世界中的使用情况

让我们用一个例子来说明,我们希望过滤出活跃的博客帖子并从特定类别中提取它们。

class Post extends Model {
    /**
     * Scope to filter active posts.
     */
    public function scopeActive($query) {
        return $query->where('active', true);
    }

    /**
     * Scope to filter posts by a given category.
     */
    public function scopeOfCategory($query, $category) {
        return $query->where('category_id', $category->id);
    }
}

要从特定类别检索所有活跃帖子,你可以链接你的范围:

$category = Category::find(1);
$activePostsInCategory = Post::active()->ofCategory($category)->get();

动态范围

在某些情况下,你可能希望你的范围接受参数。让我们创建一个动态的范围,该范围可以从过去‘n’天内获取帖子:

class Post extends Model {
    /**
     * Scope to retrieve posts from the last 'n' days.
     */
    public function scopeFromLastDays($query, $days) {
        return $query->where('created_at', '>=', now()->subDays($days));
    }
}

要检索过去10天的帖子,请调用范围并传递天数:

$recentPosts = Post::fromLastDays(10)->get();

高级示例:组合多个范围

让我们考虑一个复杂的例子,其中我们通过组合多个范围来实现一个根据用户输入过滤和排序博客文章的功能:

class Post extends Model {
    ...
    public function scopeSearch($query, $searchTerm) {
        return $query->where('title', 'like', "%{$searchTerm}%");
    }

    public function scopeSort($query, $direction = 'asc') {
        return $query->orderBy('created_at', $direction);
    }
}

$posts = Post::active()->search('laravel')->sort('desc')->get();

这个链将会返回包含 ‘laravel’ 在标题中的活跃帖子,按创建日期降序排列。

结论

Eloquent的范围特性为查询数据库提供了一种强大的范式,使它们在复杂的应用中表现出色,从而简化了对数据库查询的管理。

长工码奴1523

长工码奴1523

Eloquent是Laravel框架的一部分,用于处理ORM(对象关系映射)。它提供了方便的语法来操作数据库查询和模型实例。

在Eloquent中,作用域是用于指定哪些数据属于哪个特定模型的方法。作用域可以基于以下几种方式:

  1. 属性:你可以为模型的任何字段定义作用域。
  2. 方法:你可以为模型的所有方法定义作用域。
  3. 路由:你可以通过设置路由来定义作用域。

示例

假设我们有一个名为User的模型,我们想要限制其所有用户的ID只显示在用户信息视图中。

use AppModelsUser;

class UserController extends Controller {
    public function show($id) {
        // 在这里使用$userId作为参数
        $user = User::find($id);

        return view('users.show', [
            'user' => $user,
        ]);
    }
}

在这个例子中,show()方法接受一个参数 $id,并尝试根据这个ID从数据库获取用户信息。然后,我们创建了一个视图文件users/show.blade.php,并在其中使用了$userId变量。

为了实现这个效果,我们需要在App/Http/Controllers/UserController.php中添加一个新的方法,该方法接受一个参数 $userId 并返回一个渲染好的视图。

UserController类的构造函数中,我们可以将$userId作为访问者传递到show()方法,并将其绑定到request()->input('userId')上:

public function __construct() {
    $this->middleware(['auth:api']);
}

protected function getShowAction(Request $request, $id) {
    // 假设我们有这样一个方法:
    $userId = $request->input('userId');

    return view('users.show', [
        'user' => User::where('id', $userId)->first(),
    ]);
}

这样,当用户调用show()方法时,它会首先检查请求是否包含了userId参数,如果没有则抛出404错误。如果有,则使用这个参数来获取用户信息。