到同一Laravel资源控制器操作的多个路由

时间:2014-06-17 13:15:22

标签: laravel routing

我喜欢在Laravel中使用资源控制器,因为它让我想到了数据建模。到目前为止,我已经过去了,但我现在正在开发一个拥有公共前端和受保护的后端(管理区域)的网站。

我创建了一个添加“admin”前缀的路由组,如下所示:

Route::group(array('before' => 'auth', 'prefix' => 'admin'), function()
{
    Route::resource('article', 'ArticleController');
    Route::resource('event', 'EventController');
    Route::resource('user', 'UserController');    
});

我可以使用默认网址结构访问这些方法,即 http://example.com/admin/article/1/edit

但是,我希望在前端使用不同的 URL结构,这不适合资源控制器所期望的。

例如,要访问文章,我想使用以下网址: http://example.com/news/2014/06/17/some-article-slug 。如果这篇文章的ID为1,它应该(在引擎盖下)转到 / article / 1 / show

我怎样才能在Laravel中实现这一目标?在那里我可以在路由上进行某种预处理以将日期和段塞与文章ID匹配,然后然后将其作为参数传递给我的资源控制器的show()方法?

3 个答案:

答案 0 :(得分:0)

一个简单的解决方案是为您的需求创建另一条路线,并在那里进行处理以将其链接到主路线。所以,例如:

//routes.php 
Route::get('/arical/{date}/indentifier/{slug}', array (
'uses' => 'ArticleController@findArticle'
  ));

//ArticleContoller

public function findArticle($date,$slug){
$article = Article::where('slug','=','something')->first(); //maybe some more processing;
$article_id = $article->id;
/*
Redirect to a new route or load the view accordingly
*/ 
}

希望这很有用。

答案 1 :(得分:0)

似乎Laravel 4在路由中支持(:all),您可以轻松完成,但遗憾的是(:all) is not supported in Laravel 4

但是,Laravel 4允许通过正则表达式检测路线,因此我们可以使用->where('slug', '.*')

routes.php:(文件底部)

Route::get('{slug}', 'ArticleController@showBySlug')->where('slug', '.*');

由于Laravel将首先尝试匹配routes.php中的最顶层路由,因此我们可以安全地将我们的通配符路由放在routes.php的底部,以便仅在已经评估了所有其他条件之后才检查它。

<强> ArticleController.php:

class ArticleController extends BaseController
{
    public function showBySlug($slug)
    {
        // Slug lookup. I'm assuming the slug is an attribute in the model.
        $article_id = Article::where('slug', '=', $slug)->pluck('id');

        // This is the last route, throw standard 404 if slug is not found.
        if (!$article_id) {
            App::abort(404);
        }

        // Call the controller's show() method with the found id.
        return $this->show($article_id);
    }

    public function show($id)
    {
        // Your resource controller's show() code goes here.
    }
}

上面的代码假定您将整个URI存储为slug。当然,您可以随时定制showBySlug()以支持更高级的段塞检查。

<强>附加

你也可以这样做:

Route::get('{category}/{year}/{slug}', 'ArticleController@showBySlug')->where('slug', '.*');

你的showBySlug()只会有其他参数:

public function showBySlug($category, $year, $slug)
{
    // code
}

显然,您可以延长到月,日或其他适应性。

答案 2 :(得分:0)

重新访问它,我通过使用路由模型绑定和模式来解决它:

$year = '[12][0-9]{3}';
$month = '0[1-9]|1[012]';
$day = '0[1-9]|[12][0-9]|3[01]';
$slug = '[a-z0-9\-]+';

// Pattern to match date and slug, including spaces
$date_slug = sprintf('(%04d)\/(%02d)\/(%02d)\/(%s)', $year, $month, $day, $slug);

Route::pattern('article_slug', $date_slug);

// Perform the route–model binding
Route::bind('article_slug', function ($slug) {
    return Article::findByDateAndSlug($date_slug);
});

// The actual route
Route::get('news/{article_slug}', 'ArticleController@show');

然后根据需要将Article模型实例注入我的控制器操作中。