sebastiansulinski / laravel-routes
Laravel 的路由集合和路由模型绑定包装器
Requires
- php: >=5.4.0
- illuminate/routing: ^5.0
This package is auto-updated.
Last update: 2020-07-28 13:07:32 UTC
README
[已废弃] 此仓库不再维护
虽然此项目在旧版 Laravel 中仍然可用,但其依赖项已不再是最新的。您仍然可以探索、学习和使用此处提供的代码。
路由集合
创建一个新目录来存储您应用程序的所有路由集合 - 例如,可以在 app/Http
下的名为 Routes/Collections
的目录中。
app/Http/Routes/Collections
在目录内部创建一个新类,该类将与您的系统给定部分一起使用 - 例如,对于您应用程序的前端部分,我们使用 FrontCollection.php
并将其放入另一个目录中 - 为了区分不同的部分,因为这一个属于前端,所以我们称之为 Front
。
app/Http/Routes/Collections/Front/FrontCollection.php
新的 FrontCollection
类将扩展 SSD\LaravelRoutes\RouteCollectionFactory
,并需要有一个名为 getNameSpace
的方法,该方法返回当前命名空间,该命名空间将用于在 app/Http/Routes/Collections/Front
目录中创建每个类的完全限定名。
// app/Http/Routes/Collections/Front/FrontCollection.php
namespace App\Http\Routes\Collections\Front;
use SSD\LaravelRoutes\RouteCollectionFactory;
class FrontCollection extends RouteCollectionFactory
{
protected static function getNameSpace()
{
return __NAMESPACE__;
}
}
在相同的目录中为每个路由集合创建一个新文件 - 例如,对于前端部分的 Blog
模块,您可以使用
// app/Http/Routes/Collections/Front/Blog.php
namespace App\Http\Routes\Collections\Front;
use SSD\LaravelRoutes\RouteCollectionContract;
class Blog implements RouteCollectionContract
{
public function routes()
{
app('router')->group(['prefix' => 'blog'], function() {
app('router')->get('/', 'BlogController@index');
app('router')->get('latest', 'BlogController@latest');
app('router')->post('comment', 'BlogController@addComment');
app('router')->get('comment/{id}', 'BlogController@showComment');
});
}
}
并为表单提交方法的 Contact
控制器可能还需要另一个
// app/Http/Routes/Collections/Front/Contact.php
namespace App\Http\Routes\Collections\Front;
use SSD\LaravelRoutes\RouteCollectionContract;
class Contact implements RouteCollectionContract
{
public function routes()
{
app('router')->group(['prefix' => 'contact'], function() {
app('router')->get('/', 'ContactController@index');
app('router')->post('/', 'ContactController@submit');
});
}
}
现在您只需要在您的 app/Http/routes.php
文件中做的是
use App\Http\Routes\Collections\Front\FrontCollection;
FrontCollection::blog();
FrontCollection::contact();
FrontCollection
上的神奇静态方法名称是 camelCase
格式的集合类名称 - 例如,名称为 FoodRecepies
的集合将被称为 FrontCollection::foodRecepies()
,依此类推。
如果您想使您的 routes.php
文件更加整洁,您可以创建每个部分的集合主,然后将所有单独的路由集合包含在其中
// app/Http/Routes/Collections/Front/Master.php
namespace App\Http\Routes\Collections\Front;
use SSD\LaravelRoutes\RouteCollectionContract;
class Master implements RouteCollectionContract
{
public function routes()
{
FrontCollection::blog();
FrontCollection::contact();
}
}
并且对于 Admin
部分(请确保您首先创建了 AdminCollection
)
// app/Http/Routes/Collections/Admin/Master.php
namespace App\Http\Routes\Collections\Admin;
use SSD\LaravelRoutes\RouteCollectionContract;
class Master implements RouteCollectionContract
{
public function routes()
{
app('router')->group(
[
'prefix' => 'admin',
'namespace' => 'Admin'
],
function() {
AdminCollection::auth();
app('router')->group(
[
'middleware' => ['admin']
],
function() {
AdminCollection::blog();
AdminCollection::pages();
}
);
}
);
}
}
然后只需在 routes.php 中调用它
use App\Http\Routes\Collections\Front\FrontCollection;
use App\Http\Routes\Collections\Admin\AdminCollection;
FrontCollection::master();
AdminCollection::master();
自定义异常
抽象的 SSD\LaravelRoutes\RouteCollectionFactory
类可以抛出 SSD\LaravelRoutes\Exceptions\InvalidClassName
异常,当静态方法名称与现有类不匹配时,或者当您忘记在扩展 SSD\LaravelRoutes\RouteCollectionFactory
的类上声明 getNameSpace()
方法时,抛出 SSD\LaravelRoutes\Exceptions\MissingNamespace
异常。
路由模型绑定
路由模型绑定允许您分组模型绑定。
首先,在 app/Http/Routes
下创建一个名为 ModelBindings
的新目录
app/Http/Routes/ModelBindings
在此目录中创建一个与您要定义绑定的模型相对应的类 - 例如,如果您有一个名为 Blog
的模型,您想要定义两个绑定 - 一个用于 blog_id
,另一个用于 blog_slug
app('router')->get('blog/{blog_id}', 'BlogController@edit');
app('router')->get('blog/{blog_slug}', 'BlogController@show');
您的模型看起来可能是这样的
// app/Http/Routes/ModelBindings/BlogBinder.php
namespace App\Http\Routes\ModelBindings;
use Illuminate\Routing\Router;
use SSD\LaravelRoutes\RouteModelBinderContract;
use App\Blog;
class BlogBinder implements RouteModelBinderContract
{
public function bind(Router $router)
{
$router->model('blog_id', Blog::class);
// for version of PHP lower than 5.6 use:
// $router->model('blog_id', 'App\Blog');
$router->bind('blog_slug', function($slug) {
return $this->recordBySlug($slug);
});
}
protected function recordBySlug($slug)
{
return Blog::whereSlug($slug)->firstOrFail();
}
}
将scopeWhereSlug()
方法添加到您的Blog
模型中(或者,如果您在多个模型上使用slug,可以将其提取到Trait中)。
// app/Blog.php
namespace App;
class Blog extends Model
{
protected $table = 'blog';
public function scopeWhereSlug($query, $slug)
{
return $query->where('slug', '=', $slug);
}
}
现在,有了BlogBinder
,我们可以将其添加到`app/Providers/RouteServiceProvider.php`。
// app/Providers/RouteServiceProvider.php
namespace App\Providers;
use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use SSD\LaravelRoutes\RouteModelBinderFactory;
use App\Http\Routes\ModelBindings\BlogBinder;
class RouteServiceProvider extends ServiceProvider
{
protected $namespace = 'App\Http\Controllers';
public function boot(Router $router)
{
parent::boot($router);
RouteModelBinderFactory::bind(new BlogBinder, $router);
}
public function map(Router $router)
{
$router->group(['namespace' => $this->namespace], function ($router) {
require app_path('Http/routes.php');
});
}
}
模型绑定提示
您更有可能在前端应用中使用slug
- 所以为了稍微提高性能,让我们为slug
绑定缓存模型。为此 - 在App\Http\Routes\ModelBindings
下创建一个新的BaseBinder
类,并为了方便起见 - 让我们使用nespot/carbon
包。首先使用composer添加Carbon
依赖。
composer require nesbot/carbon
现在创建一个具有cache
方法的BaseBinder
类。我只为一天进行缓存,但您可以根据需要将其设置得更长。
// app/Http/Routes/ModelBindings/BaseBinder.php
namespace App\Http\Routes\ModelBindings;
use Carbon\Carbon;
abstract class BaseBinder {
protected function cache($key, callable $default)
{
$value = app('cache.store')->get($key);
if (is_null($value)) {
$arguments = func_get_args();
$value = call_user_func_array($default, array_splice($arguments, 2));
app('cache.store')->put($key, $value, Carbon::now()->addDay(1));
}
return $value;
}
}
最后修改BlogBinder
类
// app/Http/Routes/ModelBindings/BlogBinder.php
namespace App\Http\Routes\ModelBindings;
use Illuminate\Routing\Router;
use SSD\LaravelRoutes\RouteModelBinderContract;
use App\Blog;
class BlogBinder extends BaseBinder implements RouteModelBinderContract
{
public function bind(Router $router)
{
$router->model('blog_id', Blog::class);
$router->bind('blog_slug', function($slug) {
return $this->cache(
'blog.slug.'.$slug,
[
$this,
'recordBySlug'
],
$slug
);
});
}
protected function recordBySlug($slug)
{
return Blog::whereSlug($slug)->firstOrFail();
}
}
现在,您的模型绑定将首先从数据库中提供,然后,每次后续调用都将从缓存中读取,持续时间为一天。请确保在更新记录时,您也更新缓存的版本 - 或者简单地删除相应键的缓存。