在Laravel 5中扩展Request类

时间:2015-05-10 19:03:56

标签: php laravel laravel-5

我是Laravel的新手(只有经验丰富的Laravel 5,所以这里没有遗留问题)

我想知道如何扩展核心Request类。除了如何扩展它之外,我想知道这样做是否是一个明智的设计决定。

我已经详细阅读了文档(特别是关于注册服务提供者以及它提供Facade访问依赖容器中条目的方式) - 但我可以看到(并找到)无法替换{ {1}}我自己的实例

6 个答案:

答案 0 :(得分:26)

以下是正式文件:Request Lifecycle

app / Http / CustomRequest.php的内容

<?php namespace App\Http;

use Illuminate\Http\Request as BaseRequest;

class CustomRequest extends BaseRequest {
    // coding
}

将此行添加到public / index.php

$app->alias('request', 'App\Http\CustomRequest');

app = require_once __DIR__.'/../bootstrap/app.php';

更改public / index.php

中的代码
Illuminate\Http\Request::capture()

App\Http\CustomRequest::capture()

答案 1 :(得分:3)

我想你还必须延长RequestForm。我使用trait来避免代码重复。以下代码与 Laravel 5.3 相关。

app/Http/ExtendRequestTrait.php

<?php
namespace App\Http\ExtendRequestTrait;

trait ExtendRequestTrait {
  methodFoo(){}
  methodBar(){}
}

app/Http/Request.php

<?php
namespace App\Http;
use Illuminate\Http\Request as BaseRequest;

class Request extend BasicRequest {
  use ExtendRequestTrait;
}

app/Http/FormRequest.php

<?php
namespace App\Http;
use Illuminate\Foundation\Http\FormRequest as BaseFormRequest;

class FormRequest extend BasicFormRequest {
  use ExtendRequestTrait;
}

对于phpunit测试工作,您必须覆盖call方法,使其在Request使用Request::create类。

test/TestCase.php

<?php
use App\Http\Request;

abstract class TestCase extends Illuminate\Foundation\Testing\TestCase{

   // just copy Illuminate\Foundation\Testing\TestCase `call` method 
   // and set right Request class
   public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
    {
        $kernel = $this->app->make('Illuminate\Contracts\Http\Kernel');

        $this->currentUri = $this->prepareUrlForRequest($uri);

        $this->resetPageContext();

        $request = Request::create(
            $this->currentUri, $method, $parameters,
            $cookies, $files, 
            array_replace($this->serverVariables, $server), 
            $content
        );

        $response = $kernel->handle($request);

        $kernel->terminate($request, $response);

        return $this->response = $response;
    }

}

并且不要忘记在Illuminate\Http\Request::capture()文件中将App\Http\Request::capture()切换为public/index.php,并在$app->alias('request', 'App\Http\Request');之后或之内添加$app = require_once __DIR__.'/../bootstrap/app.php';

答案 2 :(得分:2)

我今天正在处理同样的问题,我认为值得一提的是你可能只是改变

Illuminate\Http\Request::capture()

App\Http\CustomRequest::capture()

不添加行

$app->alias('request', 'App\Http\CustomRequest');

因为在capture()方法中,laravel实际上将提供的类绑定到服务容器,并且请求&#39;作为关键

答案 3 :(得分:1)

Yerkes的回答启发了我编写一个自定义类,用于分页,但只能用于特定的请求

<?php

namespace App\Http\Requests;

use Illuminate\Http\Request;

class PaginatedRequest extends Request
{
    public function page(): int
    {
        return max(1, (int) ($this['page'] ?? 1));
    }

    public function perPage(): int
    {
        $perPage = (int) ($this['per_page'] ?? 100);
        return max(1, min($perPage, 500));
    }

    public function offset(): int
    {
        return ($this->page() - 1) * $this->perPage();
    }
}

然后,我还必须在/config/app.php中注册一个新的ServiceProvider,看起来像

<?php

namespace App\Providers;

use App\Http\Requests\PaginatedRequest;
use Illuminate\Support\ServiceProvider;

class PaginatedRequestServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->app->resolving(PaginatedRequest::class, function ($request, $app) {
            PaginatedRequest::createFrom($app['request'], $request);
        });
    }
}

现在,仅在需要时,我才可以将PaginatedRequest注入我的控制器方法中

<?php

namespace App\Http\Controllers;

use App\Http\Requests\PaginatedRequest;

class MyController
{
    public function __invoke(PaginatedRequest $request)
    {
        $request->page();
        // ...
    }
}

答案 4 :(得分:0)

我能够在Laravel 5.5中使用FormRequest添加自定义请求对象,如下所示。

首先,只需创建FormRequest

php artisan make:request MyRequest

然后让它看起来像这样:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class MyRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

然后,您可以在MyRequest作为参数的任何函数中使用Request作为替代品:

public function get(MyRequest $request)
{
}

我确实认识到FormRequest实际上是用于不同的目的,但无论如何都有效。

FormRequest上的文档:https://laravel.com/docs/5.0/validation#form-request-validation

答案 5 :(得分:0)

在Laravel 5.5.x中,我可以使用以下命令扩展特定请求的Request类:

ExtendedRequest类

<?php declare(strict_types = 1);

namespace App\Http\Request;

use Illuminate\Http\Request;

class ExtendedRequest extends Request {
    public function hello() {
        echo 'hello world!';
    }
}

ExtendedRequestServiceProvider

<?php declare(strict_types = 1);

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Http\Request\ExtendedRequest;

class ExtendedRequestServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(ExtendedRequest::class, function ($app) {
            return ExtendedRequest::capture();
        });
    }
}

然后在您的控制器中

<?php

namespace App\Controllers;

use App\Http\Request\ExtendedRequest;

class TestController extends Controller
{
    public function get(ExtendedRequest $request) {
        echo $request->hello();
    }
}

希望这对某人有帮助。