【问题标题】:Is it possible to reorder or ignore parameters in controller routes?是否可以重新排序或忽略控制器路由中的参数?
【发布时间】:2014-09-07 12:00:51
【问题描述】:

问题标题是我能想到的最明确的,但为了清楚起见,这里有一个用例/示例:

假设我定义了以下路径来显示一篇文章:

Route::get('article/{slug}/{id}', 'ArticleController@show');

...

class ArticleController extends BaseController {

    public function show($id)
    {
        return View::make('article')->with('article', Article::find($id));
    }

}

这不起作用,因为show 会将$id 参数与$slug 参数混淆。有没有办法只将$id 参数传递给show 方法?

【问题讨论】:

  • 你能不能把你的路线改成'article/{id}'
  • 是的,但是我会失去用户输入的额外好处,例如,/article/some-title/12345,它比/article/12345 更容易记住(例如,查看 StackOverflow 的 URL) .
  • 那为什么不把你的 show 函数改成 public function show($slug, $id) 呢?如果没有传入,如何通过控制器中的 slug 获取您的文章?您的选择在这里非常有限,您要么想要 slug,要么不想要。
  • 请注意,我的问题是'是否有可能......'。我知道有一些解决方法。

标签: php laravel laravel-routing


【解决方案1】:

你当然可以在 Laravel 中“忽略”参数——即将它们设为可选——通过在参数名称后添加问号:

Route::get('article/{slug?}/{id?}', 'ArticleController@show');

请注意,您受到 PHP 处理可选函数参数的方式的限制:如果右边有必需的参数,则最左边的参数不能是可选的。

// Do
Route::get('article/{id}/{slug?}', 'ArticleController@show');
...
function show($id, $slug = null) {}

// Don't
Route::get('article/{slug?}/{id}', 'ArticleController@show');
...
function show($slug = null, $id) {}

我同意上面 cmets 的说法,这样做可能并不完全合乎逻辑。您将需要slugid 来在数据库中查找您的文章,但同时您希望它们中的一个就足以找到完全相同的文章。

如果你真的想有一个可选的 slug 以使你的 URL 更“可抓取”、SEO 友好、令人难忘或者你有什么,这里有一个建议,从上面的例子中构建:

Route::get('article/{id}/{slug?}', array(
    'as'   => 'article.show',
    'uses' => 'ArticleController@show'
));

...

function show($id, $slug = null)
{

    $article = Article::find($id);

    if (!$slug) {
        return Redirect::route('article.show', array($id, $article->slug));
    }

    ...
}

我认为没有人会尝试访问无 slug 的 URL,但这可能取决于您以及您尝试对您的应用执行的操作。这样,至少您可以让 slug 成为“可选”,同时确保每个人都以完整的 URL 出现在同一个位置。

【讨论】:

    【解决方案2】:

    可以手动调用控制器函数:

    Route::get('article/{slug}/{id}', function($slug, $id)
    {
        return App::make('ArticleController')->show($id);
    });
    

    【讨论】:

      【解决方案3】:

      我不知道你是否还在寻找解决方案,但由于我遇到了同样的问题并且我不喜欢这些解决方案,所以我这样做了:

      在你的 ArticleController 中你重载了 callAction($method, $parameters) 方法,这是 Laravel 控制器类中的一个方法,所以它看起来像这样:

      public function callAction($method, $parameters)
      {
              unset($parameters['id']);
              unset($parameters['slug']);
      
              return parent::callAction($method, $parameters);
      }
      

      在这之后你可以很容易地做到这一点:

      public function show($id)
      {
          return View::make('article')->with('article', Article::find($id));
      }
      

      【讨论】:

        猜你喜欢
        • 2017-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-04
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 1970-01-01
        相关资源
        最近更新 更多