我喜欢在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()
方法?
答案 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
模型实例注入我的控制器操作中。