前面我们写了怎么添加博客,这篇文章我们讲解博客首页怎么实现,我们主要用到的laravel功能如下
- 自定义中间件
- 视图共享数据
- 路由匹配规则
- 路由约束
首先我们定义一条新的路由
Route::get('/{id?}', 'BlogController@getBlogList')->where('id', '[0-9]+');
Route::get('/category/{id?}.html', 'BlogController@getBlogList')->where('id', '[0-9]+');
路由规则说明
- {id?} 表示这里的id可选
- where('id', '[0-9]+') 表示id的正则约束规则 所以这条规则对应的地址可以是:“/”,“/1”,"/2"
自定义中间件
我们执行如下命令,新增一条中间件
php artisan make:middleware Web
中间件的存储位置
app/Http/Middleware/Web.php
修改中间件的内容如下
<?php
namespace App\Http\Middleware;
use App\Models\Category;
use Closure;
class Web
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
view()->share('navCategoryList', Category::where('parent_id', 0)->get());
return $next($request);
}
}
注意下面这段代码,他表示,给视图赋值,从而让拥有这个中间件的所有视图都有这些数据,所以,要小心键的冲突
对应的SQL: select * from categories。get方法表示拿到所有数据。
view()->share('navCategoryList', Category::where('parent_id', 0)->get());
注册中间件
修改app/Http/Kernel.php文件
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'lee.web' => Web::class,
];
下面这句话,我们自己命名中间件的名字为lee.web
'lee.web' => Web::class,
使用中间件
还记得我们app/Providers/RouteServiceProvider.php这个文件么?我们当初统一修改web路由的命名空间。这里我们定义的中间件是通用的,为了给网站顶部分类使用,所以也需要应用的全部路由里面。修改我们的代码如下:
protected function mapWebRoutes()
{
//修改为我们自己定会的命名空间
Route::middleware(['web', 'lee.web'])
->namespace($this->namespaceWeb)
->group(base_path('routes/web.php'));
}
这样我们web下所有的路由都拥有了这个中间件,从而达到多个页面数据共享。
修改BlogController和BlogRepository
BlogController
public function getBlogList($categoryId = null)
{
$blogList = $this->blogRepository->getBlogList($categoryId);
$goodList = $this->blogRepository->getGoodList();
return view('web.blog.index', ['blogList' => $blogList, 'goodList' => $goodList]);
}
我们路由定义的id就会作为参数传递过来,如果的你参数是可选的,可以在controller里的方法中给默认值,我里给$categoryId的默认值为null
BlogRepository
public function getBlogList($categoryId = null)
{
return Blog::leftjoin('categories', 'blogs.category_id', '=', 'categories.id')
->orderby('blogs.id', 'desc')
->select('blogs.*')
->where(function ($q) use ($categoryId) {
if ($categoryId) {
$q->where('categories.parent_id', $categoryId);
}
})
->paginate();
}
这里我们用到了链表查询,leftjoin表示左连接,第一个参数表示例外一张表,第二和第四个参数表示表中的联结字段,第三个参数“=”固定写法。
这里我们用到了闭包,我们判断$categoryId是否存在,存在的话增加where条件。
模板继承
我们定义一下模板,作为公共模板
resources/views/web/layouts/app.blade.php
模板示例如下
这里用到了模板语法yield,他定义了一个可替换的位置
我们修改首页的模板
resources/views/web/blog/index.blade.php
@extends('web.layouts.app')
@section('title', '添加博客;')//替换我们@yield('title'),下面雷同
@section('keywords', '添加博客;')
@section('description', '添加博客;')
最总效果如下图
但是,当我们点击分类,怎么实现分类高亮呢?
<ul class="navbar-nav mr-auto">
@foreach($navCategoryList as $nav)
<li class="nav-item @if(request()->path()=='category/'.$nav->id.'.html') active @endif">
<a class="nav-link"
href="/category/{{$nav->id}}.html">{{$nav->category_name}}</a>
</li>
@endforeach
</ul>
这里我们用到了if语法,同时request()->path()可以获得我们的url片段,最终给我们的导航条加上高亮效果。
回顾一下我们用到的技术点
- 中间件
- 路由的正则约束
- 路由可选参数
- 视图数据共享
- 模板继承
- 模板中的逻辑判断
- leftjoin查询数据
- 如何使用闭包查询数据