如何在Laravel中用Eloquent Where()细化数据库查询?

449 阅读4分钟

在本系列的前一部分中,你更新了演示程序,将链接组织到数据库中的列表中。现在,主应用程序视图显示了一个菜单,其中有当前在数据库中注册的所有列表,但该菜单还没有活动链接。

在本节中,你将在应用程序中创建一个新的路径,按列表显示链接。你还将学习如何使用Eloquent中的where() 方法来更好地过滤数据库查询的结果。

为了开始学习,在你的代码编辑器中打开routes/web.php 文件。

routes/web.php

该文件目前有以下内容。

routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Models\Link;
use App\Models\LinkList;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    $links = Link::all()->sortDesc();
    return view('index', [
        'links' => $links,
        'lists' => LinkList::all()
    ]);
});

Route::get 调用定义了应用程序入口页面的HTTP GET路由。当向应用程序发出/ 的请求时,这个回调函数将被触发以返回索引视图。

现在你将创建第二个路由,以显示基于列表slug的链接列表。slug是一个短字符串,通常用于建立用户友好的URL。新的路由必须查询数据库的link_lists 表,寻找一个以提供的URL参数作为其slug 字段的列表。如果找不到具有该lug的列表,应用程序应以HTTP 404或_未找到_错误通知用户。

下面的代码使用一个动态参数(由{slug} 定义)创建了一个 GET 路由,名为link-list 。这将。

  • 使用LinkList Eloquent模型,用where() 方法查询数据库,使用lug作为搜索条件。first() 方法将确保只返回一个对象。
  • 如果找不到指定slug的列表,就会用abort 方法抛出404错误。
  • 如果找到了一个有效的列表,索引视图就会被渲染,列表被作为模板参数提供。

提供$lists 参数是为了建立列表菜单,而提供$links 参数是为了与当前版本的索引视图兼容,因为它在一个具有该名称的变量中循环。

在你的routes/web.php 文件的底部包含以下代码。

routes/web.php

Route::get('/{slug}', function ($slug) {
    $list = LinkList::where('slug', $slug)->first();
    if (!$list) {
        abort(404);
    }

    return view('index', [
        'list' => $list,
        'links' => $list->links,
        'lists' => LinkList::all()
    ]);
})->name('link-list');

完成后保存该文件。

虽然有一些捷径可以实现引用Eloquent模型的路由,但在本教程中,我们主要是使用where() 方法来学习。

为了测试你的新路由是否如预期的那样工作,你可以到你的浏览器中访问默认列表页的链接。如果你到目前为止已经按照本系列的所有步骤进行了操作,而且你的数据库不是空的,那么默认列表页应该可以在以下本地地址找到。

http://localhost:8000/default

你会看到和以前一样的页面,但现在链接只限于默认列表中的链接。如果你有额外的列表,你可以通过将URL中高亮的default slug替换为你的列表的slug来访问他们的页面。

配置了新的路径后,你现在可以使用route Blade方法,从你的模板视图中为你的链接列表动态地生成URL。你还可以自定义页面标题,以显示有关列表的信息,如果有一个可用的话。

在你的代码编辑器中打开resources/views/index.blade.php 文件。

resources/views/index.blade.php

这个文件有2行需要更新。首先,找到包含你在本系列另一部分中创建的菜单的副标题段落。它现在看起来是这样的。

resources/views/index.blade.php

        <p class="subtitle">
            @foreach ($lists as $list)<a href="#" title="{{ $list->title }}" class="tag is-info is-light">{{ $list->title }}</a> @endforeach
        </p>

你将更新href 超链接,以包括列表页的当前 URL,使用route blade 方法。该方法希望将路由的名称作为第一个参数,并将 URL 参数作为方法调用的附加参数提供。用以下突出显示的内容替换# 字符。

resources/views/index.blade.php

        <p class="subtitle">
            @foreach ($lists as $list)<a href="{{ route('link-list', $list->slug) }}" title="{{ $list->title }}" class="tag is-info is-light">{{ $list->title }}</a> @endforeach
        </p>

接下来,找到链接部分和其中的foreach 循环。你需要包括对route() 方法的另一个调用,在该方法中,每个链接的列表名称被打印出来。这与前面的例子类似,但是,列表对象的访问方式不同,是通过$link 变量。

resources/views/index.blade.php

            <p>{{$link->url}}</p>
            <p class="mt-2"><a href="{{ route('link-list', $link->link_list->slug) }}" title="{{ $link->link_list->title }}" class="tag is-info">{{ $link->link_list->title }}</a></p>

接下来,你可能想包括有关列表的信息,当提供额外信息时。你可以检查$list 变量的存在,只有在该变量可用时才打印列表标题。

用下面突出显示的代码替换你的title 部分。

        <h1 class="title">
            @if (isset($list))
                {{ $list->title }}
            @else
                Check out my awesome links
            @endif
        </h1>

这就是你完成后的index.blade.php 文件的样子。为方便起见,这些改动被高亮显示。

resources/views/index.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Awesome Links</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">

    <style>
        html {
            background: url("https://i.imgur.com/BWIdYTM.jpeg") no-repeat center center fixed;
            -webkit-background-size: cover;
            -moz-background-size: cover;
            -o-background-size: cover;
            background-size: cover;
        }

        div.link h3 {
            font-size: large;
        }

        div.link p {
            font-size: small;
            color: #718096;
        }
    </style>
</head>
<body>
<section class="section">
    <div class="container">
        <h1 class="title">
            @if (isset($list))
                {{ $list->title }}
            @else
                Check out my awesome links
            @endif
        </h1>
        <p class="subtitle">
            @foreach ($lists as $list)<a href="{{ route('link-list', $list->slug) }}" title="{{ $list->title }}" class="tag is-info is-light">{{ $list->title }}</a> @endforeach
        </p>

        <section class="links">
            @foreach ($links as $link)
                <div class="box link">
                    <h3><a href="{{ $link->url }}" target="_blank" title="Visit Link: {{ $link->url }}">{{ $link->description }}</a></h3>
                    <p>{{$link->url}}</p>
                    <p class="mt-2"><a href="{{ route('link-list', $link->link_list->slug) }}" title="{{ $link->link_list->title }}" class="tag is-info">{{ $link->link_list->title }}</a></p>
                </div>
            @endforeach
        </section>
    </div>
</section>
</body>
</html>

当你完成更新其内容时,保存该文件。

现在你可以通过你的浏览器访问应用程序的主页。如果你使用包含的Docker Compose设置,该应用程序应该可以通过以下本地地址访问。

http://localhost:8000

你会得到一个类似于以下屏幕截图的页面。

The screenshot shows the updated Landing Laravel application with working links to individual list pages

在本系列的下一部分,你将学习如何在Laravel Eloquent中订购查询结果。

本教程是正在进行的关于Laravel Eloquent的每周系列的一部分。如果你想在新的教程发布时得到通知,你可以订阅Laravel标签