使用路由模型绑定清理 Laravel 控制器

简介

Http://lumen.laravel.com))作为构建网站的框架或构建API的容器([Lumen](Laravel已演变为开发人员的首选框架。Laravel带来了许多不断发展的功能--以Laravel的活动为例。Laravel中的事件过去是一个简单的发布-订阅库,但现在Laravel事件可以一路广播到客户端,并允许我们创建实时apps.

但这并不是重点,今天的名人是拉威尔的路线模型捆绑。

什么是路由模型绑定

Laravel中的路由模型绑定提供了一种将模型实例注入到您的路由中的机制。现在还不清楚它的意思,下面就是一个例子。假设我们想要从数据库中获取帖子,我们可以这样做:

 1...
 2// the route parameter is the id of the post
 3// for example http://example.com/posts/53
 4Route::get('posts/{id}', function ($id) {
 5
 6  // we have to find the post using the $id
 7  $post = Post::find($id);
 8
 9  // if there is no post, 404
10  if (!$post) return abort(404);
11
12  // return the view and the post
13  return view('post.show', compact('post'));
14});
15...

我们可以进一步将这种方法简化为

 1...
 2// the route parameter is the id of the post
 3// for example http://awesome.dev/posts/53
 4Route::get('posts/{id}', function ($id) {
 5
 6  // find the post or 404 if not found
 7  $post = Post::findOrFail($id);
 8
 9  // return the view and the post
10  return view('post.show', compact('post'));
11});
12...

但是,路由模型绑定通过将上述两个实例简化为

 1...
 2// by using $post, we can inject the Post object
 3Route::get('posts/{post}', function ($post) {
 4
 5  // we now have access to the $post object! no code necessary
 6
 7  // return the view and the post
 8  return view('post.show', compact('post'));
 9});
10...

这是通过告诉Laravel将Post模型注入到任何附加了{post}参数的路由控制器中来实现的。

Laravel目前支持两种类型的路由模型绑定。我们有:

  • 隐式模型绑定
  • 显式模型绑定

<$>[备注] 注意: 上面列出的路由模型绑定示例是显式的。 <$>

隐式模型绑定

虽然我们已经看到了显式模型绑定,但下面是隐式模型绑定的示例:

1Route::get('posts/{post}', function (App\Post $post) {
2  // be awesome. enjoy having the $post object
3});

Laravel非常聪明,他知道由于一个Post模型被注入到控制器闭包中,所以它应该从路径中获取id参数,并为用户获取详细信息。

访问帖子仍将使用http://awesome.example.com/posts/24.

更改机型的路由键

如果您希望隐式模型绑定在检索模型时使用id以外的数据库列,可以在您的eloquent模型上重写getRouteKeyName方法。

例如,如果我们想使用slug而不是id,我们可以这样做:

1class Post extends Model {
2  public function getRouteKeyName() {
3    return 'slug';
4  }
5}

然后我们可以使用http://awesome.example.com/posts/my-post-slug而不是http://awesome.example.com/posts/24.来访问我们的路线

显式模型绑定

顾名思义,您必须显式地告诉Laravel您希望它将一个url参数绑定到一个特定的模型。有两种方法可以做到这一点,我们可以使用提供的Route外观将参数绑定到模型上,或者在app/Providers/RouteServiceProvider.php中进行绑定(我更喜欢这种方法)。

使用Route外观

使用Route外观将参数绑定到模型,我们可以这样做:

1Route::bind('post', 'App\Post');

我们还可以给我们的约束赋予更多的含义,例如,如果我们只想要一个帖子,如果是草稿呢?为此,我们可以将route::bind的第二个参数更改为一个闭包,该闭包将路由参数作为其值。

1Route::bind('post', function ($value) {
2  return App\Post::find($value)->where('status', '=', 'published')->first();
3});

使用RouteServiceProvider

使用Route外观和RouteServiceProvider类的唯一区别是-在RouteServiceProvider类(位置是app/Providers目录)的boot方法中注册绑定,而bind方法是在该方法中注入的$router对象上调用的。快速示例

1public function boot(Router $router)
2{
3  parent::boot($router);
4
5  $router->bind('post', function ($value) {
6    return App\Post::find($value)->where('status', '=', 'published')->first();
7  });
8}

路由模型绑定自定义配置

我构建了很多API,所以对于像我这样的人来说,路由模型绑定的定制异常实际上更有用。拉威尔为我们提供了一种简单的方法来做到这一点。还是在RouteServiceProvider类的boot方法中,对$router对象调用Model方法。

Model方法有三个参数,这些参数与bind方法的参数类似,添加了一个新的第三个参数,这是一个抛出新异常的闭包。

1$router->model($routeParameter, $modelToBind, function () {
2  throw new NotFoundHTTPException;
3});

结论

您可以在documentation.中阅读有关路由模型绑定的更多信息

希望这个小但整洁的特性可以为您的项目节省几行代码,并使您的控制器更加简洁。

Published At
Categories with 技术
Tagged with
comments powered by Disqus