這里面有很多內容,所以這里是重點。為了簡潔起見,代碼稍作了調整。
擴展類:
<?php
namespace AppHttp。
使用 IlluminateHttpRequest as LaravelRequest;
class Request extends LaravelRequest
{
中間件:
<?php
namespace AppHttpMiddleware。
使用 AppHttpRequest 作為 CustomizedRequest。
use Closure;
use IlluminateContractsFoundationApplication;
使用 IlluminateHttpRequest;
class CustomizeRequest
{
protected $app;
protected $customizedRequest;
public function __construct(Application $app, CustomizedRequest $customizedRequest){
$this->app = $app;
$this->customedRequest = $customizedRequest;
}
public function handle(Request$request, Closure $next){
$this->app-> instance(
'require'。
Request::createFrom($request, $this-> customizedRequest)。
);
return $next($this-> customRequest)。
}
路徑:
Route::get('/books1/{id}',[BookController::class, 'frontend1'])。)
Route::get('/books2/{id}',[BookController::class, 'frontend2'])。)
Controller:
<?php
namespace AppHttpControllers。
使用 AppModelsBook。
class BookController extends Controller
{
public function frontend1frontend1(IlluminateHttpRequest $request) {
dump($request)。
dump($request-> all())。
dump($request->route('id') )。)
return Book::all()。
}
title">frontend2(AppHttpRequest $request) {
dump($request)。
dump($request-> all())。
dump($request->route('id') )。)
return Book::all()。
}
}
這些都是非常原始的,因為我只是在玩Laravel來學習它,但這花了太多的時間,所以我可以使用一些幫助。
/books1/5?foo=bar和frontend1()的路徑是可行的。$request按照預期被填充。
/books2/5?foo=bar和frontend2()的路徑被破壞。$request有大量的缺失資料,就像它在實體化時什么都沒有。
顯然,如果我對我的子類進行型別提示,而不是對更通用的父類進行型別提示,它就會導致某種破碎的實體化。從OO的角度來看,我認為這應該是非常好的,我確實特別需要我的子類被提供,所以更喜歡這種型別提示。是不是Laravel內部有什么東西絆住了這個問題? 這是一些我以前沒有見過的晦澀的PHP行為嗎?
感謝您的到來
uj5u.com熱心網友回復:
這是個棘手的問題。
首先,你需要熟悉服務容器和依賴注入。以下是完整的檔案。https://laravel.com/docs/8.x/container
當你在控制器方法中輸入提示類時, Laravel會試著理解它應該怎么做.
如果在服務容器中沒有注冊任何東西, 它將嘗試創建一個新的實體。
IlluminateHttpRequest被系結為一個單子(https://laravel.com/docs/8.x/container#binding-a-singleton)。
雖然簡單的系結將在每次呼叫時回傳一個新的實體,但單子將始終回傳完全相同的實體。
AppModelsUser::class是一個沒有明確系結的類。
當你試圖使用服務容器來解決它時,它將找不到它,并將嘗試創建一個新的實體:
AppModelsUser::class是一個沒有明確系結的類。
$u1 = app(AppModelsUser::class);
//搜索AppModelsUser::class...
//無法找到AppModelsUser::class...。
//回傳new AppModelsUser();
$u2 = app(AppModelsUser::class)。
//同樣的程序再次發生。
$u3 = app(AppModelsUser::class)。
//再次
//你可以通過檢查它們的哈希值來檢查這些實體確實不同:
dd(
spl_object_hash($u1), // 000000004af5213500000000220f0bc0(52135)
spl_object_hash($u2), // 000000004af5213400000000220f0bc0 (52134)/span>
spl_object_hash($u3) // 000000004af5213700000000220f0bc0 (52137)/span>.
);
但是由于IlluminateHttpRequest::class是由Laravel系結的,它遵循不同的路徑:
$r1 = app(IlluminateHttpRequest::class) 。
//搜索 IlluminateHttpRequest::class...
//發現它了! 系結為一個單子。
///回傳新的IlluminateHttpRequest()并存盤
//實體,以防以后再需要它;
$r2 = app(IlluminateHttpRequest::class) 。
//搜索 IlluminateHttpRequest::class...
//發現它并且已經呼叫了! 回傳存盤的實體($r1)
$r3 = app(IlluminateHttpRequest::class)。
//搜索 IlluminateHttpRequest::class...
//發現它并且已經呼叫了! 回傳存盤的實體($r1)
//它們的哈希值是一樣的。
dd(
spl_object_hash($u1), // 0000000011f522cf0000000077704cd1
spl_object_hash($u2), // 0000000011f522cf0000000077704cd1
spl_object_hash($u3) // 0000000011f522cf0000000077704cd1
);
現在,發生了什么?
在引擎蓋下, 當一個新的請求被送到你的應用程式,并在擊中控制器方法之前, Laravel將做很多事情來準備IlluminateHttpRequest實體。
例如, 它將在IlluminateRoutingRouter中設定路由決議器:
/**.
* 回傳給定路由的回應。
*
* @param IlluminateHttpRequest $request
* @param IlluminateRoutingRoute $route
* @return SymfonyComponentHttpFoundationResponse
*/
protected function runRoute(Request $request, 路線 $route)
{
//here
$request-> setRouteResolver(function() use ($route) {
return $route;
});
//
$this->events->dispatch(new RouteMatched($route, $request) )。)
return $this-> prepareResponse($request,
$this->runRouteWithinStack($route, $request)
);
}
每次Laravel內部都會這樣呼叫一個方法:
protected function method(Request $request) /span>{
//對$request做一些處理。
}
$request總是同一個實體,因為它被系結為一個單子。
我們現在在你的控制器中。
public function frontend1(IlluminateHttpRequest $request) {
///搜索 IlluminateHttpRequest::class...{
//發現它并且已經呼叫了!
//回傳已經通過所有準備好的存盤實體。
// Laravel核心類
dump($request)。
dump($request->all()); //準備好了。
dump($request->route('id')); //well setup。
return Book::all()。
}
public function frontend2 title">frontend2(AppHttpRequest $request) {
///搜索AppHttpRequest::class...{
//無法找到AppHttpRequest::class...。
//回傳新的AppHttpRequest();
dump($request)。
dump($request->all()); //nothing.
dump($request->route('id')); //empty。
return Book::all();
}
如果你還在這里,如何解決這個問題?
最簡單的方法是使用一個FormRequest,最初是為了處理表單驗證,但是如果你回傳一個空的規則陣列,你應該能夠完成你的自定義AppHttpRequest實體的所有作業:
<?php
namespace AppHttp。
使用 IlluminateFoundationHttpFormRequest。
class Request extends FormRequest
{
public function rules()
{
return【】。
}
}
再試一次,一切都應該正常,因為這是一個專門用來替換初始IlluminateHttpRequest物件的功能。
完整的檔案在這里。https://laravel.com/docs/8.x/validation#creating-form-requests
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/329342.html
標籤:


