国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

webman框架源碼修改及性能優(yōu)化(四)

kaoson

在寫中間件時(shí),發(fā)現(xiàn)一個(gè)比較重要問(wèn)題,那就是中間件中獲取的controller對(duì)象,不是原來(lái)的controller對(duì)象,這樣不嚴(yán)謹(jǐn),也導(dǎo)致在__construct()中對(duì)controller修改的屬性不生效,所以需要修改幾個(gè)地方。

控制器中間件代碼通常是這樣:

if ($request->controller) {
            $controller = Container::get($request->controller); //這里獲取到的不是原來(lái)的controller對(duì)象
}

下面是分析和修改流程:

  1. 查找src/Container.php中的get()方法,調(diào)試發(fā)現(xiàn)是new了一個(gè)新的實(shí)例
    public function get(string $name)
    {
        if (!isset($this->instances[$name])) {
            if (isset($this->definitions[$name])) {
                $this->instances[$name] = call_user_func($this->definitions[$name], $this);
            } else {
                if (!class_exists($name)) {
                    throw new NotFoundException("Class '$name' not found");
                }
                $this->instances[$name] = new $name(); //返回了一個(gè)新的實(shí)例,instances和definitions都不起作用
            }
        }
        return $this->instances[$name];
    }

    剛開始準(zhǔn)備改這個(gè)get()方法,但這個(gè)方法對(duì)應(yīng)接口僅提供一個(gè)$name參數(shù),不想改動(dòng)太大,所以換個(gè)思路改make()方法,原make()方法:

    
    public function make(string $name, array $constructor = [])
    {
        if (!class_exists($name)) {
            throw new NotFoundException("Class '$name' not found");
        }
        return new $name(... array_values($constructor));
    }
需要在new的時(shí)候,同時(shí)加入到instances屬性中,修改后如下:
```php
public function make(string $name, array $constructor = [])
    {
        if (!class_exists($name)) {
            throw new NotFoundException("Class '$name' not found");
        }
        // return new $name(... array_values($constructor));
        $this->instances[$name] = new $name(... array_values($constructor));
        return $this->instances[$name];
    }
  1. 發(fā)現(xiàn)make()方法執(zhí)行是在中間件的Container::get()之后,分析src/App.php的流程,可以對(duì)getCallback()方法進(jìn)行修改,多傳遞一個(gè)request參數(shù),然后稍微調(diào)整,就可以讓make()方法先執(zhí)行,修改后代碼如下:

    protected static function getCallback(string $plugin, string $app, $call, array $args = null, bool $withGlobalMiddleware = true, RouteObject $route = null)
    {
        $args = $args === null ? null : array_values($args);
        $middlewares = [];
        if ($route) {
            $routeMiddlewares = array_reverse($route->getMiddleware());
            foreach ($routeMiddlewares as $className) {
                $middlewares[] = [$className, 'process'];
            }
        }
        $middlewares = array_merge($middlewares, Middleware::getMiddleware($plugin, $app, $withGlobalMiddleware));
    
        foreach ($middlewares as $key => $item) {
            $middleware = $item[0];
            if (is_string($middleware)) {
                $middleware = static::container($plugin)->get($middleware);
            } elseif ($middleware instanceof Closure) {
                $middleware = call_user_func($middleware, static::container($plugin));
            }
            if (!$middleware instanceof MiddlewareInterface) {
                throw new InvalidArgumentException('Not support middleware type');
            }
            $middlewares[$key][0] = $middleware;
        }
    
        $needInject = static::isNeedInject($call, $args);
        if (is_array($call) && is_string($call[0])) {
            $controllerReuse = static::config($plugin, 'app.controller_reuse', true);
            if (!$controllerReuse) {
                if ($needInject) {
                    $call = function ($request, ...$args) use ($call, $plugin) {
                        $call[0] = static::container($plugin)->make($call[0], [$request]);
                        $reflector = static::getReflector($call);
                        $args = static::resolveMethodDependencies($plugin, $request, $args, $reflector);
                        return $call(...$args);
                    };
                    $needInject = false;
                } else {
                    $call = function ($request, ...$args) use ($call, $plugin) {
                        $call[0] = static::container($plugin)->make($call[0], [$request]);
                        return $call($request, ...$args);
                    };
                }
            } else {
                $call[0] = static::container($plugin)->get($call[0]);
            }
        }
    
        if ($needInject) {
            $call = static::resolveInject($plugin, $call);
        }
    
        if ($middlewares) {
            $callback = array_reduce($middlewares, function ($carry, $pipe) {
                return function ($request) use ($carry, $pipe) {
                    try {
                        return $pipe($request, $carry);
                    } catch (Throwable $e) {
                        return static::exceptionResponse($e, $request);
                    }
                };
            }, function ($request) use ($call, $args) {
                try {
                    if ($args === null) {
                        $response = $call($request);
                    } else {
                        $response = $call($request, ...$args);
                    }
                } catch (Throwable $e) {
                    return static::exceptionResponse($e, $request);
                }
                if (!$response instanceof Response) {
                    if (!is_string($response)) {
                        $response = static::stringify($response);
                    }
                    $response = new Response(200, [], $response);
                }
                return $response;
            });
        } else {
            if ($args === null) {
                $callback = $call;
            } else {
                $callback = function ($request) use ($call, $args) {
                    return $call($request, ...$args);
                };
            }
        }
        return $callback;
    }

    改動(dòng)對(duì)比圖:
    截圖

截圖

  1. 對(duì)調(diào)用getCallback()的兩個(gè)地方,加上request參數(shù)
    165 行
    $callback = static::getCallback($plugin, $app, [$controller, $action]);

    改為:

    $callback = static::getCallback($plugin, $app, [$controller, $action], $args = null, $withGlobalMiddleware = true, $route = null, $request);

大概557行

$callback = static::getCallback($plugin, $app, $callback, $args, true, $route);

改為

$callback = static::getCallback($plugin, $app, $callback, $args, true, $route, $request);

好了,重新調(diào)試,OK!

1978 5 1
5個(gè)評(píng)論

PHP甩JAVA一條街

好厲害

  • wash2018 2023-06-08

    這次我站隊(duì)官方,我也覺(jué)得前半個(gè)洋蔥不該獲取到控制器實(shí)例

  • wash2018 2023-06-08

    kaoson是個(gè)大佬

walkor

這樣有兩個(gè)問(wèn)題
1、內(nèi)存始終會(huì)緩存一些控制器實(shí)例,這會(huì)導(dǎo)致這些控制器以及控制器引用的對(duì)象不釋放,比如__destruct(){}無(wú)法及時(shí)執(zhí)行
2、webman容器可配置,如果改成其它容器,那么你這個(gè)做法可能就失效了

  • kaoson 2023-06-07

    復(fù)用模式下本身就不用釋放的,非復(fù)用模式下,是不是可以在中間件執(zhí)行完畢后釋放?這樣稍改下代碼就行,當(dāng)然,還有沒(méi)有更好的方式?
    開發(fā)者要換自己的容器,那應(yīng)該得理解框架運(yùn)行流程,當(dāng)然相關(guān)地方要做好處理。

  • walkor 2023-06-07

    容器一般是標(biāo)準(zhǔn)的容器,比如 php-di,make方法時(shí)它們不會(huì)保存實(shí)例

  • kaoson 2023-06-07

    think、laravel貌似都是這么干的吧,think基本抄的laravel,如果你認(rèn)為這樣不行,那怎么解決我提的問(wèn)題?

  • walkor 2023-06-07

    如果要獲取同一個(gè)控制器實(shí)例,需要開啟控制器復(fù)用

  • kaoson 2023-06-07

    非復(fù)用下,每個(gè)中間件都要去new一下,不科學(xué)啊

  • walkor 2023-06-07

    根據(jù)中間件洋蔥模型,前置中間件就不應(yīng)該得到控制器實(shí)例,控制器實(shí)例應(yīng)該是在達(dá)到洋蔥芯才能實(shí)例化,提前實(shí)例化才是不科學(xué)的。

  • kaoson 2023-06-07

    你這么說(shuō)有道理,讓我又重新思索之前的做法,原來(lái)我就是認(rèn)為beforeAction, afterAction本來(lái)就屬于控制器內(nèi)部的東西,干嘛要交給中間件去調(diào)用?感覺(jué)比較矛盾。

  • walkor 2023-06-07

    如果你想改webman的http內(nèi)核,可以用自定義進(jìn)程去做
    http://m.wtbis.cn/doc/webman/process.html

  • kaoson 2023-06-07

    好的,回頭研究一下

  • wocall 2023-06-10

    實(shí)在是佩服,雖然看不懂

  • kangyu 2023-07-11

    大佬之間的交流

縫合

囧,看了半天代碼,配置上有這個(gè)控制器復(fù)用的參數(shù)。開啟復(fù)用的情況下,controller是不會(huì)重新new的。截圖
我還以為不支持

  • 暫無(wú)評(píng)論
W

大佬們??!請(qǐng)接收下我的膝蓋吧

  • 暫無(wú)評(píng)論
PHP甩JAVA一條街

你是fastadmin 作者嗎

年代過(guò)于久遠(yuǎn),無(wú)法發(fā)表評(píng)論

kaoson

520
積分
0
獲贊數(shù)
0
粉絲數(shù)
2023-05-30 加入
??