【问题标题】:How can I declare a route and a controller method that explicitly expect two query parameters like this?如何声明明确期望这样的两个查询参数的路由和控制器方法?
【发布时间】:2017-07-22 15:46:05
【问题描述】:

我是 Laravel 的新手,遇到以下问题。

我必须声明一个处理这样的请求的路由:

http://laravel.dev/activate?email=myemail@gmail.com&token=eb0d89ba7a277621d7f1adf4c7803ebc

因此,此 URL 必须采用这种格式(activate 作为资源和 2 个查询参数,格式为 ?email&token。这是不是REST URI。我需要这样使用)。

我需要一个路由和一个控制器方法来处理这种请求。

我知道我可以这样做:

1) 在 routes/web.php 文件中,我声明这样的路由

Route::get('/activate','MyController@myMethod');

2) 进入 MyController 我声明这个方法:

public function myMethod(Request $request) {

    if(Input::has('email') && Input::has('token')) {
        $email = $request->input('email');
        $token= $request->input('token');

        // DO SOMETHING USING $email AND $token
    }
    else {
        // SHOW ERROR PAGE
    }
}

但只有我觉得这很可怕。我来自 Java,使用 Spring 框架,我可以在 URL 和控制器方法之间的映射中指定一个方法处理对资源的请求,并且必须传递一些要处理的特定查询参数。否则(如果这些参数不存在,则控制器方法不会处理 HTTP GET 请求)。

我知道在 Laravel 中我可以使用我的 URL 的 REST 形式做这样的事情,我认为是这样的:

对于路线映射:

Route::get('/activate/{email}/{token}', [ 'uses' => 'ActivationController@activate', 'as' => 'activate' ]);

然后控制器方法会是这样的:

public function activate($email, $token) {
    // $email would be 'myemail@gmail.com'
    // $token would be 'eb0d89ba7a277621d7f1adf4c7803ebc'
    // do stuff...
}

但在这种情况下我不能使用这种 URI(如指定的 URL 模式必须采用以下格式:

http://laravel.dev/activate?email=myemail@gmail.com&token=eb0d89ba7a277621d7f1adf4c7803ebc

所以我希望用这种 URI 做这样的事情。我不会将 Request $request 对象传递给我的控制器方法,然后从中提取参数,但我希望有一个这样的控制器方法签名:

public function activate($email, $token) {

如果没有传递所有预期的参数,则此控制器不会处理请求。

我更喜欢这样做,因为对我来说是一种更简洁的方法(读取控制器签名,其他开发人员立即知道该方法是预期的)。

而且还因为我希望方法不处理格式错误的参数(因此我可以避免处理错误情况,例如:用户未传递 2 个参数)。

我怎样才能在 Laravel 中做这样的事情? (如果可能的话……)

【问题讨论】:

  • 您可以创建进行检查(过度杀伤)的中间件,也可以创建进行验证的自定义 form request,这样如果没有有效参数,您的控制器方法就不会被命中。

标签: php laravel laravel-5 laravel-5.3 laravel-routing


【解决方案1】:

这当然是一个奇怪的请求,因为它违背了更传统的 Laravel 路由实践,但这应该适合你:

routes.php(Laravel web.php(Laravel 5.4+)中:

Route::get('/activate', [ 'as' => 'activate', function()
{
    return app()->make(App\Http\Controllers\ActivateController::class)->callAction('activate', $parameters = [ 'email' => request()->email, 'token' => request()->token ]);
}]);

因此,我们正在实例化 ActivateController 类并调用作为第一个参数的方法“activate”,然后以数组的形式提供该方法接收的参数列表。

public function activate($email, $token)
{
    echo "Email: $email"; // myemail@gmail.com
    echo "Token: $token"; // eb0d89ba7a277621d7f1adf4c7803ebc
    // do stuff
}

现在,如果您转到 http://laravel.dev/activate?email=myemail@gmail.com&token=eb0d89ba7a277621d7f1adf4c7803ebc $email$token 将是各自的关键查询参数。

现在,关于验证以确保数据存在。您必须在 activate() 方法中添加另一个参数,除非您想内联。

最佳实践方式:

运行php artisan make:request ActivateRequest

将在app\Http\Requests 中创建一个名为 ActivateRequest 的新文件。打开它并确保您的authorize() 方法返回true,如下所示:

public function authorize()
{
    return true;
}

接下来,在rules() 方法中有一个数组。添加以下内容:

return [
    'email' => 'required|email',
    'token' => 'required',
];

如果您想为这些规则提供自己的验证消息,请在rules() 下方添加一个名为messages() 的方法,如下所示:

public function messages()
{
     return [
        'email.required' => 'You must supply an email address.',
        'email.email' => 'That email is address is not valid.',
        'token.required' => 'Please supply a token.',
     ];
}

然后,回到ActivateController,在顶部use App\Http\Requests\ActivateRequest; 中拉入您的新FormRequest 类,并在方法中使用它,如下所示:

activate($email, $token, ActivateRequest $request) {
    ...

现在,您的请求将得到验证,您甚至不必使用 $request 变量。

内联(不是最佳实践方式)

如果您在方法中没有额外的参数而僵局,您可以像这样在控制器中验证数据:

首先,在顶部引入Validator 类。 use Validator;.

public function activate($email, $token)
{
    $validationMessages = [
        'email.required' => 'You must supply an email address.',
        'email.email' => 'That email is address is not valid.',
        'token.required' => 'Please supply a token.',
     ];

    $validation = Validator::make(request()->toArray(), [
        'email.required' => 'You must supply an email address.',
        'email.email' => 'That email is address is not valid.',
        'token.required' => 'Please supply a token.',
    ], $validationMessages);

    if ( $validation->fails() )
    {
       return 'Sorry, there was a problem with your request';
    }

    // do stuff
}

希望这会有所帮助。

【讨论】:

  • 对我来说很遗憾查询参数在 PHP 框架中被如此忽视。在搜索 Laravel does 是否验证查询参数一小时后,我找到了这个答案,因为文档没有太多要说的,而且大多数验证搜索结果都是针对 REST 路由的。感谢您的回复,它不仅指导如何解决问题,而且验证查询输入是否经过验证。 呼!
猜你喜欢
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 2013-10-14
  • 2011-07-09
  • 2019-03-17
  • 2013-08-22
  • 2018-01-21
相关资源
最近更新 更多