~~ webman中
$request->getRemoteIp()取的是真實tcp連接 ip
如有代理 nginx 就不友好,不管頭怎么設(shè)置真實ip都是nginx的真實ip
自己實現(xiàn)獲取用戶ip雖不難,但是,建議加入到 request 類里面
$request->header('X-Real-IP')~~
首先說明我為什么需要初始化函數(shù),在我們的業(yè)務(wù)中我想,在中間件鑒權(quán),鑒權(quán)后給控制器賦值當(dāng)前用戶的id及信息,當(dāng)然,這里也可以賦值給request 對象的屬性,但是我們習(xí)慣在 控制器里面$this->user_id,所以想在控制器每個請求進(jìn)來就初始化的時候賦值用戶id,但是初始化要在中間件后,下面是我修改的框架源代碼,大家?guī)兔纯矗袥]有什么bug。
protected static function getCallback($app, $call, $args = null, $with_global_middleware = true)
{
$args = $args === null ? null : \array_values($args);
$middleware = Middleware::getMiddleware($app, $with_global_middleware);
if ($middleware) {
$callback = array_reduce($middleware, function ($carry, $pipe) {
return function ($request) use ($carry, $pipe) {
return $pipe($request, $carry);
};
}, function ($request) use ($call, $args) {
self::_initialize($request); //在調(diào)用控制器回調(diào)前 調(diào)用初始化函數(shù)
if ($args === null) {
$response = $call($request);
} else {
$response = $call($request, ...$args);
}
if (\is_scalar($response) || null === $response) {
$response = new Response(200, [], $response);
}
return $response;
});
} else {
self::_initialize($request); //沒有中間件的時候
if ($args === null) {
$callback = $call;
} else {
$callback = function ($request) use ($call, $args) {
return $call($request, ...$args);
};
}
}
return $callback;
}
```
/**
* 控制器初始化
* @param string $request
*/
private static function _initialize($request)
{
if ($request->controller) {
$controller_obj = static::$_container->get($request->controller);
if (method_exists($controller_obj, '_initialize')) {
$_initialize = [$controller_obj, '_initialize'];
$_initialize($request);
}
}
}
```
代碼看著沒什么問題。
不過鑒權(quán)更適合用中間件,大部分框架都是用中間件來鑒權(quán)的,這樣可以控制業(yè)務(wù)流程流轉(zhuǎn),比如在鑒權(quán)失敗時統(tǒng)一跳轉(zhuǎn)到登錄頁面,如果在你說的那個控制器初始化函數(shù)里做就很難做到。
另外用 $request->user_id
比 $控制器->user_id
更合理一些。$request
類似用戶輸入的變量,包含請求數(shù)據(jù),用戶鑒權(quán)數(shù)據(jù)??刂破魇枪驳姆椒?,只根據(jù)輸入變量$request
來處理業(yè)務(wù),控制器自身不應(yīng)該存儲用戶狀態(tài)數(shù)據(jù)。控制器是單例的多請求共享的,也就是說上一個請求設(shè)置的$控制器->user_id
,下一個請求沒有將$控制器->user_id
重置直接使用將得到錯誤的用戶數(shù)據(jù)。
你說的我也明白,我的意思是,鑒權(quán)還是在中間件里面做,但是每個請求通過中間件后,在調(diào)用控制器方法前,調(diào)用一下控制器對象的特定方法(比如_initialize)。我們需要在這里做一些事情。比如清除一些數(shù)據(jù),比如修改當(dāng)前對象的一些值??赡苤皇俏覀冇羞@個需求,cv代碼的時候改動少。