目录
什么是查询范围?
局部查询范围
全局查询范围
#如何创建全局查询范围
#应用全局查询范围
#匿名全局查询范围
#忽略全局查询范围
#全局查询范围注意事项
测试局部查询范围
在控制器中测试范围
结论
首页 后端开发 php教程 学会在Laravel中掌握查询范围

学会在Laravel中掌握查询范围

Mar 06, 2025 am 02:28 AM

<p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174119929536701.jpg" class="lazy" alt="Learn to master Query Scopes in Laravel"></p> <p>在构建Laravel应用程序时,您可能需要编写具有约束条件的查询,这些约束条件在整个应用程序中的多个地方使用。也许您正在构建一个多租户应用程序,并且您必须不断向查询中添加<code>where</code>约束以按用户的团队进行筛选。或者,也许您正在构建一个博客,并且您必须不断向查询中添加<code>where</code>约束以筛选博客文章是否已发布。</p> <p>在Laravel中,我们可以使用查询范围来帮助我们将这些约束条件整洁地保存在一个地方并重复使用。</p> <p>在本文中,我们将研究局部查询范围和全局查询范围。我们将学习两者之间的区别,如何创建您自己的查询范围,以及如何编写它们的测试。</p> <p>在阅读完本文后,您应该能够自信地在Laravel应用程序中使用查询范围。</p> <h1 id="什么是查询范围">什么是查询范围?</h1> <hr> <p>查询范围允许您以可重用的方式在Eloquent查询中定义约束条件。它们通常定义为Laravel模型上的方法,或者作为实现<code>IlluminateDatabaseEloquentScope</code>接口的类。</p> <p>它们不仅非常适合在一个地方定义可重用的逻辑,而且还可以通过将复杂的查询约束隐藏在简单的函数调用之后来使您的代码更具可读性。</p> <p>查询范围分为两种类型:</p> <ul> <li>局部查询范围 - 您必须手动将这些范围应用于您的查询。</li> <li>全局查询范围 - 默认情况下,这些范围会应用于模型上的所有查询,前提是已注册该查询。</li> </ul> <p>如果您曾经使用过Laravel内置的“软删除”功能,您可能已经在不知不觉中使用了查询范围。Laravel使用局部查询范围为您提供模型上的<code>withTrashed</code>和<code>onlyTrashed</code>等方法。它还使用全局查询范围自动向模型上的所有查询添加<code>whereNull('deleted_at')</code>约束,以便默认情况下查询中不会返回软删除的记录。</p> <p>让我们来看看如何在Laravel应用程序中创建和使用局部查询范围和全局查询范围。</p> <h1 id="局部查询范围">局部查询范围</h1> <hr> <p>局部查询范围定义为Eloquent模型上的方法,允许您定义可以手动应用于模型查询的约束条件。</p> <p>假设我们正在构建一个具有管理面板的博客应用程序。在管理面板中,我们有两个页面:一个用于列出已发布的博客文章,另一个用于列出未发布的博客文章。</p> <p>我们假设博客文章是使用<code>AppModelsArticle</code>模型访问的,并且数据库表具有一个可为空的<code>published_at</code>列,用于存储博客文章的发布时间。如果<code>published_at</code>列在过去,则该博客文章被认为已发布。如果<code>published_at</code>列在未来或为<code>null</code>,则该博客文章被认为未发布。</p> <p>要获取已发布的博客文章,我们可以编写如下查询:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->where('published_at', '<', now()) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>要获取未发布的博客文章,我们可以编写如下查询:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; use Illuminate\Contracts\Database\Eloquent\Builder; $unpublishedPosts = Article::query() ->where(function (Builder $query): void { $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>上面的查询并不特别复杂。但是,假设我们在整个应用程序中的多个地方使用它们。随着出现次数的增加,我们犯错或忘记在一个地方更新查询的可能性越来越大。例如,开发人员可能会意外地使用<code>>=</code>而不是<code><</code>来查询已发布的博客文章。或者,确定博客文章是否已发布的逻辑可能会更改,我们需要更新所有查询。</p> <p>这就是查询范围非常有用的地方。因此,让我们通过在<code>AppModelsArticle</code>模型上创建局部查询范围来整理我们的查询。</p> <p>局部查询范围是通过创建一个以<code>scope</code>开头并以范围的预期名称结尾的方法来定义的。例如,名为<code>scopePublished</code>的方法将在模型上创建一个<code>published</code>范围。该方法应该接受一个<code>IlluminateContractsDatabaseEloquentBuilder</code>实例并返回一个<code>IlluminateContractsDatabaseEloquentBuilder</code>实例。</p> <p>我们将这两个范围都添加到<code>AppModelsArticle</code>模型中:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>declare(strict_types=1); namespace App\Models; use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; final class Article extends Model { public function scopePublished(Builder $query): Builder { return $query->where('published_at', '<', now()); } public function scopeNotPublished(Builder $query): Builder { return $query->where(function (Builder $query): Builder { return $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }); } // ... }</code> </p> <p>正如我们在上面的示例中看到的,我们将<code>where</code>约束从之前的查询移动到了两个单独的方法中:<code>scopePublished</code>和<code>scopeNotPublished</code>。我们现在可以在我们的查询中像这样使用这些范围:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->published() ->get(); $unpublishedPosts = Article::query() ->notPublished() ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>在我个人看来,我发现这些查询更容易阅读和理解。这也意味着如果我们将来需要使用相同约束条件编写任何查询,我们可以重复使用这些范围。</p> <h1 id="全局查询范围">全局查询范围</h1> <hr> <p>全局查询范围执行与局部查询范围类似的功能。但是,它不是在逐个查询的基础上手动应用,而是自动应用于模型上的所有查询。</p> <p>正如我们前面提到的,Laravel内置的“软删除”功能使用了<code>IlluminateDatabaseEloquentSoftDeletingScope</code>全局查询范围。此范围会自动向模型上的所有查询添加<code>whereNull('deleted_at')</code>约束。如果您有兴趣了解其底层工作原理,可以在这里查看GitHub上的源代码。</p> <p>例如,假设您正在构建一个具有管理面板的多租户博客应用程序。您可能只想允许用户查看属于其团队的文章。因此,您可能会编写如下查询:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->where('published_at', '<', now()) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>此查询很好,但很容易忘记添加<code>where</code>约束。如果您正在编写另一个查询并忘记添加约束,则最终会在您的应用程序中出现一个错误,该错误将允许用户与不属于其团队的文章进行交互。当然,我们不希望发生这种情况!</p> <p>为了防止这种情况,我们可以创建一个全局范围,我们可以将其自动应用于我们所有<code>AppModelArticle</code>模型查询。</p> <h3 id="如何创建全局查询范围">#如何创建全局查询范围</h3> <p>让我们创建一个全局查询范围,该范围按<code>team_id</code>列过滤所有查询。</p> <p>请注意,为了本文的目的,我们保持示例简单。在实际应用程序中,您可能希望使用更强大的方法来处理用户未经身份验证或用户属于多个团队等情况。但现在,让我们保持简单,以便我们可以专注于全局查询范围的概念。</p> <p>我们将首先在终端中运行以下Artisan命令:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; use Illuminate\Contracts\Database\Eloquent\Builder; $unpublishedPosts = Article::query() ->where(function (Builder $query): void { $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>这应该已经创建了一个新的<code>app/Models/Scopes/TeamScope.php</code>文件。我们将对此文件进行一些更新,然后查看完成的代码:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>declare(strict_types=1); namespace App\Models; use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; final class Article extends Model { public function scopePublished(Builder $query): Builder { return $query->where('published_at', '<', now()); } public function scopeNotPublished(Builder $query): Builder { return $query->where(function (Builder $query): Builder { return $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }); } // ... }</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>在上面的代码示例中,我们可以看到我们有一个新的类,它实现了<code>IlluminateDatabaseEloquentScope</code>接口并具有一个名为<code>apply</code>的单个方法。这就是我们定义要应用于模型查询的约束条件的方法。</p> <p>我们的全局范围现在可以使用了。我们可以将其添加到任何我们想要将查询范围缩小到用户团队的模型中。</p> <p>让我们将其应用于<code>AppModelsArticle</code>模型。</p> <h3 id="应用全局查询范围">#应用全局查询范围</h3> <p>有多种方法可以将全局范围应用于模型。第一种方法是在模型上使用<code>IlluminateDatabaseEloquentAttributesScopedBy</code>属性:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->published() ->get(); $unpublishedPosts = Article::query() ->notPublished() ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>另一种方法是在模型的<code>booted</code>方法中使用<code>addGlobalScope</code>方法:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $articles = Article::query() ->where('team_id', Auth::user()->team_id) ->get();</code></pre><div class="contentsignin">登录后复制</div></div> <p>这两种方法都将<code>where('team_id', Auth::user()->team_id)</code>约束应用于<code>AppModelsArticle</code>模型上的所有查询。</p> <p>这意味着您现在可以编写查询,而无需担心按<code>team_id</code>列进行过滤:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>php artisan make:scope TeamScope</code></pre><div class="contentsignin">登录后复制</div></div> <p>如果我们假设用户属于<code>team_id</code>为<code>1</code>的团队,则将为上面的查询生成以下SQL:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>declare(strict_types=1); namespace App\Models\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; use Illuminate\Support\Facades\Auth; final readonly class TeamScope implements Scope { /** * Apply the scope to a given Eloquent query builder. */ public function apply(Builder $builder, Model $model): void { $builder->where('team_id', Auth::user()->team_id); } }</code></pre><div class="contentsignin">登录后复制</div></div> <p>这很酷,对吧?!</p> <h3 id="匿名全局查询范围">#匿名全局查询范围</h3> <p>定义和应用全局查询范围的另一种方法是使用匿名全局范围。</p> <p>让我们更新我们的<code>AppModelsArticle</code>模型以使用匿名全局范围:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>declare(strict_types=1); namespace App\Models; use App\Models\Scopes\TeamScope; use Illuminate\Database\Eloquent\Attributes\ScopedBy; use Illuminate\Database\Eloquent\Model; #[ScopedBy(TeamScope::class)] final class Article extends Model { // ... }</code></pre><div class="contentsignin">登录后复制</div></div> <p>在上面的代码示例中,我们使用了<code>addGlobalScope</code>方法在模型的<code>booted</code>方法中定义匿名全局范围。<code>addGlobalScope</code>方法接受两个参数:</p> <ul> <li>范围的名称 - 如果您需要在查询中忽略它,则可以使用此名称来引用范围</li> <li>范围约束 - 定义要应用于查询的约束的闭包</li> </ul> <p>与其他方法一样,这会将<code>where('team_id', Auth::user()->team_id)</code>约束应用于<code>AppModelsArticle</code>模型上的所有查询。</p> <p>根据我的经验,匿名全局范围不如在单独的类中定义全局范围常见。但了解它们可用是很有好处的,以备不时之需。</p> <h3 id="忽略全局查询范围">#忽略全局查询范围</h3> <p>有时您可能希望编写一个不使用已应用于模型的全局查询范围的查询。例如,您可能正在构建一个需要包含所有记录的报表或分析查询,而不管全局查询范围如何。</p> <p>如果是这种情况,您可以使用两种方法之一来忽略全局范围。</p> <p>第一种方法是<code>withoutGlobalScopes</code>。如果未向其传递任何参数,此方法允许您忽略模型上的所有全局范围:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->where('published_at', '<', now()) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>或者,如果您只想忽略给定的一组全局范围,您可以将范围名称传递给<code>withoutGlobalScopes</code>方法:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; use Illuminate\Contracts\Database\Eloquent\Builder; $unpublishedPosts = Article::query() ->where(function (Builder $query): void { $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>在上面的示例中,我们忽略了<code>AppModelsScopesTeamScope</code>和另一个名为<code>another_scope</code>的虚构匿名全局范围。</p> <p>或者,如果您只想忽略单个全局范围,可以使用<code>withoutGlobalScope</code>方法:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>declare(strict_types=1); namespace App\Models; use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; final class Article extends Model { public function scopePublished(Builder $query): Builder { return $query->where('published_at', '<', now()); } public function scopeNotPublished(Builder $query): Builder { return $query->where(function (Builder $query): Builder { return $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }); } // ... }</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <h3 id="全局查询范围注意事项">#全局查询范围注意事项</h3> <p>务必记住,全局查询范围仅应用于通过模型进行的查询。如果您使用<code>IlluminateSupportFacadesDB</code>外观编写数据库查询,则不会应用全局查询范围。</p> <p>例如,假设您编写了此查询,您希望它只抓取属于登录用户的团队的文章:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->published() ->get(); $unpublishedPosts = Article::query() ->notPublished() ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>在上面的查询中,即使在<code>AppModelsArticle</code>模型上定义了<code>AppModelsScopesTeamScope</code>全局查询范围,也不会应用该范围。因此,您需要确保在数据库查询中手动应用约束条件。</p> <h1 id="测试局部查询范围">测试局部查询范围</h1> <hr> <p>既然我们已经学习了如何创建和使用查询范围,那么我们将研究如何为它们编写测试。</p> <p>有多种方法可以测试查询范围,您选择的方法可能取决于您的个人喜好或您正在编写的范围的内容。例如,您可能希望为范围编写更多单元样式的测试。或者,您可能希望编写更多集成样式的测试,这些测试会在诸如控制器之类的上下文中测试范围。</p> <p>就我个人而言,我喜欢混合使用两者,这样我就可以确信范围正在添加正确的约束,并且范围实际上正在查询中使用。</p> <p>让我们从前面的示例<code>published</code>和<code>notPublished</code>范围开始,并为它们编写一些测试。我们将需要编写两个不同的测试(每个范围一个):</p> <ul> <li>一个测试检查<code>published</code>范围只返回已发布的文章。</li> <li>一个测试检查<code>notPublished</code>范围只返回未发布的文章。</li> </ul> <p>让我们看看这些测试,然后讨论正在做的事情:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; $publishedPosts = Article::query() ->where('published_at', '<', now()) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>我们可以在上面的测试文件中看到,我们首先在<code>setUp</code>方法中创建一些数据。我们创建了两篇已发布的文章、一篇未安排的文章和一篇已安排的文章。</p> <p>然后是一个测试(<code>only_published_articles_are_returned</code>),它检查<code>published</code>范围只返回已发布的文章。还有一个测试(<code>only_not_published_articles_are_returned</code>),它检查<code>notPublished</code>范围只返回未发布的文章。</p> <p>通过这样做,我们现在可以确信我们的查询范围正在按预期应用约束条件。</p> <h1 id="在控制器中测试范围">在控制器中测试范围</h1> <hr> <p>正如我们提到的,测试查询范围的另一种方法是在控制器中使用的上下文中测试它们。虽然范围的隔离测试可以帮助断言范围正在向查询添加正确的约束,但它实际上并没有测试范围是否按预期在应用程序中使用。例如,您可能忘记向控制器方法中的查询添加<code>published</code>范围。</p> <p>通过编写断言在控制器方法中使用范围时返回正确数据的测试,可以捕获这些类型的错误。</p> <p>让我们以具有多租户博客应用程序的示例为例,并为列出文章的控制器方法编写一个测试。我们假设我们有一个非常简单的控制器方法,如下所示:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>use App\Models\Article; use Illuminate\Contracts\Database\Eloquent\Builder; $unpublishedPosts = Article::query() ->where(function (Builder $query): void { $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }) ->get();</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>我们假设<code>AppModelsArticle</code>模型已应用我们的<code>AppModelsScopesTeamScope</code>。</p> <p>我们将要断言只返回属于用户团队的文章。测试用例可能如下所示:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code>declare(strict_types=1); namespace App\Models; use Illuminate\Contracts\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; final class Article extends Model { public function scopePublished(Builder $query): Builder { return $query->where('published_at', '<', now()); } public function scopeNotPublished(Builder $query): Builder { return $query->where(function (Builder $query): Builder { return $query->whereNull('published_at') ->orWhere('published_at', '>', now()); }); } // ... }</code></pre><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div><div class="contentsignin">登录后复制</div></div> <p>在上面的测试中,我们正在创建两个团队。然后,我们创建一个属于团队一的用户。我们为团队一创建 3 篇文章,为团队二创建 2 篇文章。然后,我们充当用户并向列出文章的控制器方法发出请求。控制器方法应该只返回属于团队一的 3 篇文章,因此我们通过比较文章的 ID 来断言只返回这些文章。</p> <p>这意味着我们可以确信全局查询范围正在控制器方法中按预期使用。</p> <h1 id="结论">结论</h1> <hr> <p>在本文中,我们学习了局部查询范围和全局查询范围。我们学习了它们之间的区别,如何创建和使用它们,以及如何为它们编写测试。</p> <p>希望您现在应该能够自信地在Laravel应用程序中使用查询范围。</p>

以上是学会在Laravel中掌握查询范围的详细内容。更多信息请关注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 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
1 个月前 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教程
1677
14
CakePHP 教程
1430
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
说明PHP中的安全密码散列(例如,password_hash,password_verify)。为什么不使用MD5或SHA1? 说明PHP中的安全密码散列(例如,password_hash,password_verify)。为什么不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,应使用password_hash和password_verify函数实现安全的密码哈希处理,不应使用MD5或SHA1。1)password_hash生成包含盐值的哈希,增强安全性。2)password_verify验证密码,通过比较哈希值确保安全。3)MD5和SHA1易受攻击且缺乏盐值,不适合现代密码安全。

PHP类型提示如何起作用,包括标量类型,返回类型,联合类型和无效类型? PHP类型提示如何起作用,包括标量类型,返回类型,联合类型和无效类型? Apr 17, 2025 am 12:25 AM

PHP类型提示提升代码质量和可读性。1)标量类型提示:自PHP7.0起,允许在函数参数中指定基本数据类型,如int、float等。2)返回类型提示:确保函数返回值类型的一致性。3)联合类型提示:自PHP8.0起,允许在函数参数或返回值中指定多个类型。4)可空类型提示:允许包含null值,处理可能返回空值的函数。

PHP和Python:解释了不同的范例 PHP和Python:解释了不同的范例 Apr 18, 2025 am 12:26 AM

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

在PHP和Python之间进行选择:指南 在PHP和Python之间进行选择:指南 Apr 18, 2025 am 12:24 AM

PHP适合网页开发和快速原型开发,Python适用于数据科学和机器学习。1.PHP用于动态网页开发,语法简单,适合快速开发。2.Python语法简洁,适用于多领域,库生态系统强大。

PHP和Python:深入了解他们的历史 PHP和Python:深入了解他们的历史 Apr 18, 2025 am 12:25 AM

PHP起源于1994年,由RasmusLerdorf开发,最初用于跟踪网站访问者,逐渐演变为服务器端脚本语言,广泛应用于网页开发。Python由GuidovanRossum于1980年代末开发,1991年首次发布,强调代码可读性和简洁性,适用于科学计算、数据分析等领域。

PHP和框架:现代化语言 PHP和框架:现代化语言 Apr 18, 2025 am 12:14 AM

PHP在现代化进程中仍然重要,因为它支持大量网站和应用,并通过框架适应开发需求。1.PHP7提升了性能并引入了新功能。2.现代框架如Laravel、Symfony和CodeIgniter简化开发,提高代码质量。3.性能优化和最佳实践进一步提升应用效率。

为什么要使用PHP?解释的优点和好处 为什么要使用PHP?解释的优点和好处 Apr 16, 2025 am 12:16 AM

PHP的核心优势包括易于学习、强大的web开发支持、丰富的库和框架、高性能和可扩展性、跨平台兼容性以及成本效益高。1)易于学习和使用,适合初学者;2)与web服务器集成好,支持多种数据库;3)拥有如Laravel等强大框架;4)通过优化可实现高性能;5)支持多种操作系统;6)开源,降低开发成本。

PHP的影响:网络开发及以后 PHP的影响:网络开发及以后 Apr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

See all articles