【问题标题】:Dynamic Routing in Laravel 5 ApplicationLaravel 5 应用程序中的动态路由
【发布时间】:2016-01-05 07:50:03
【问题描述】:

我希望有人可以帮助我为可以有多个段的 url 进行动态路由。我一直在网上进行一些搜索,但没有找到任何东西可以帮助我解决我的具体情况。

一点背景知识……几年前,我为基于 CodeIgniter 的自定义客户端网站开发了一个 CMS 包。这个 CMS 包有几个模块(页面、博客、日历、查询等)。对于 Pages 模块,我将路由缓存到“自定义路由”配置文件,该配置文件将页面的完整路由(包括父级、祖父级等)与页面的 ID 相关联。我这样做是为了不必进行数据库查找来查找要显示的页面。

我目前正在使用 Laravel (5.1) [在我学习 Laravel 时] 重建这个 CMS 包。我需要弄清楚路由情况,然后才能继续使用新版本包中的 Pages 模块。

我知道我可以做类似...

// routes.php
Route::get('{slug}', ['uses' => 'PageController@view']);

// PageController.php
class PageController extends Controller
{
    public function view($slug)
    {
        // do a query to get the page by the slug
        // display the view
    }
}

如果我不允许嵌套页面,这将起作用,但我允许。而且我只根据父项强制执行 slug 的唯一性。所以可能会有不止一个页面包含 fargo ...

  • 位置/法戈
  • 员工/法戈

与我使用 CodeIgniter 构建的包一样,我希望能够避免额外的数据库查找来找到要显示的正确页面。

我最初的想法是创建一个具有动态路由的配置文件,就像我对旧版本系统所做的那样。路由只会在特定时间发生变化(创建页面时,修改 slug 时,更改父级时),因此“缓存”它们会很好用。但我还是 Laravel 的新手,所以我不确定最好的方法是什么。

我确实设法弄清楚以下路线有效。但这是最好的设置方式吗?

Route::get('about/foobar', function(){
    return App::make('\App\Http\Controllers\PageController')->callAction('view', [123]);
});

Route::get('foobar', function(){
    return App::make('\App\Http\Controllers\PageController')->callAction('view', [345]);
});

基本上,我想在创建页面时(或更改 slug 或父级时)将特定路由绑定到特定页面 ID。

我只是把事情复杂化了吗?

我们将不胜感激任何有关这方面的帮助或指导。

谢谢!

【问题讨论】:

  • Am I just overcomplicating things?,IMO Yes。此外,这些路线看起来像静态的,如果您不允许 IDs 的任何占位符,则没有动态。每条路由只绑定到一个特定的id
  • 就我计划如何设置而言,我认为没有任何方法可以使用不需要我进行额外数据库查询来查找正确页面的动态路由。我会为其他模块使用动态路由,比如博客,但对于常规页面,我认为它不会起作用。

标签: php laravel laravel-5


【解决方案1】:

我处理这个问题的方法是使用两条路由,一条用于主页(通常包含更复杂的逻辑,如新闻、文章、横幅等),另一条用于任何其他页面。

路线

// Home page
Route::get('/', [
    'as'      => 'home',
    'uses'    => 'PageController@index'
]);

// Catch all page controller (place at the very bottom)
Route::get('{slug}', [
    'uses' => 'PageController@getPage' 
])->where('slug', '([A-Za-z0-9\-\/]+)');

上面要注意的重要部分是链接在路由末尾的->where() 方法。这允许您为路由参数声明正则表达式模式匹配。在这种情况下,我允许 {slug} 参数使用字母数字字符、连字符和正斜杠。

这将匹配像
test-page
test-page/sub-page
another-page/sub-page

这样的 slug

PageController 方法

public function index()
{
    $page = Page::where('route', '/')->where('active', 1)->first();

    return view($page->template)
        ->with('page', $page);
}

public function getPage($slug = null)
{
    $page = Page::where('route', $slug)->where('active', 1);

    $page = $page->firstOrFail();

    return view($page->template)->with('page', $page);
}

我将模板文件信息保存在数据库中,因为我允许用户在内容管理系统中创建模板。

然后将来自数据库查询的响应传递到视图,在视图中它可以输出到元数据、页面、面包屑等。

【讨论】:

  • 正如我在问题中提到的,如果两个不同的页面有不同的父级,则它们可能具有相同的 slug。所以我不能按照你的建议去做。而且我不想进行多次查找才能找到正确的父级。
  • @Becky 数据库中的 slug 列将包含 FULL slug。 IE。 locations/fargo。这样你就永远不必担心重复。您是否有理由只使用最后一段作为您的 slug?
  • 我只是想说谢谢你的回答。我花了几个小时试图找出一种在 Laravel 5.2 中动态处理子页面路由的好方法。您对允许在 slug 中使用正斜杠的 ->where() 方法的建议解决了它。虽然这是不言自明的,但我还可以补充一点,应该(必须?)在所有其他路线之后放置一条像这样的全部路线,以便例如 admin/pages 不会被当作这条路线的 slug .
  • 谢谢! ->where('slug', '([A-Za-z0-9\-\/]+)') 是我拼图中缺失的一块。
  • 天哪,你真是个天才,你节省了我的时间,谢谢! :)
【解决方案2】:

我也在寻找关于在 laravel 中创建动态路由的相同答案,我想出了这个: 在 routes.php 中

<?php


/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

$str=Request::url();
$del="/public/";
$pos=strpos($str, $del);
$important1=substr($str, $pos+strlen($del), strlen($str)-1);
$important=ucfirst($important1); 
$asif=explode("/", $important);
$asif1=explode("/", $important1);
//echo $important;
$post=$asif1[0];
$post1=$asif1[1];
if(isset($asif1[2]))
{
   $post2=$asif1[2];
}
if(!(isset($post2)))
{
   Route::match(array('GET','POST'),$important1, $asif[0].'Controller@'.$asif[1]);
}
if(isset($post2))
{      Route::match(array('GET','POST'),$post.'/'.$post1.'/{id}',$asif[0].'Controller@'.$asif[1]);
}
Route::get('/', function () {
    return view('welcome');
});

如果你在 laravel 中有带有方法 hello 的 PostController。您可以使用此网址http://localhost/shortproject/public/post/hello。其中 shortproject 是您的项目文件夹名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 1970-01-01
    • 2018-10-21
    相关资源
    最近更新 更多