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

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

kaoson
  1. 通常,很多人都是在控制器里直接調(diào)用view()方法渲染視圖文件,因為很多框架都是這么干的,于是大家都這么干了,但這種方式并不好,使得view與controller極度耦合。

  2. webman中的controller沒有傳遞request對象,使得代碼寫起來有些繁瑣,基本每個action要傳遞request,但如果在construct中傳遞request,就可以這么寫:

protected $request;

public function __construct(Request $request)
{
    $this->request = $request;
}
  1. 可以利用中間件解決很多問題,但中間件無法處理控制器內(nèi)部的業(yè)務(wù)邏輯,假設(shè)在調(diào)用action之前,我們希望業(yè)務(wù)邏輯通過是否有中斷標(biāo)識,決定是否真正調(diào)用action,用中間件搞感覺很麻煩,如果硬編碼在每個action里,又覺得很繁瑣,再有,我們想通過在調(diào)用action后統(tǒng)一處理action的返回結(jié)果,決定是否調(diào)用view渲染視圖還是返回json等等。

修改后的代碼:

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]);

                        if (true !== ($result = static::beforeCall($call[0], $call[1], $request))) {
                            return $result;
                        }

                        $reflector = static::getReflector($call);
                        $args = static::resolveMethodDependencies($plugin, $request, $args, $reflector);
                        // return $call(...$args);
                        return static::afterCall($call[0], $call[1], $call(...$args), $request);
                    };
                    $needInject = false;
                } else {
                    $call = function ($request, ...$args) use ($call, $plugin) {
                        $call[0] = static::container($plugin)->make($call[0], [$request]);

                        if (true !== ($result = static::beforeCall($call[0], $call[1], $request))) {
                            return $result;
                        }

                        // return $call($request, ...$args);
                        return static::afterCall($call[0], $call[1], $call($request, ...$args), $request);
                    };
                }
            } 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;
    }

    protected static function beforeCall($controller, $action, $request)
    {
        if (false !== ($result = static::detectHalted($controller))) {
            return $result;
        }

        static::doBeforeAction($controller, $action, $request);

        if (false !== ($result = static::detectHalted($controller))) {
            return $result;
        }

        return true;
    }

    protected static function afterCall($controller, $action, $response, $request)
    {
        $method = 'after' . ucfirst($action) . 'Action';
        if (method_exists($controller, $method)) {
            $response = $controller->{$method}($response, $request);
        }

        if (method_exists($controller, 'afterAction')) {
            $response = $controller->afterAction($response, $request);
        }

        return $response;
    }

    protected static function detectHalted($controller)
    {
        if (method_exists($controller, 'halted')  && $controller->halted()) {
            return $controller->getHaltedResult();
        }

        return false;
    }

    protected static function doBeforeAction($controller, $action, $request)
    {
        if (method_exists($controller, 'beforeAction')) {
            $controller->beforeAction($request);
        }

        $method = 'before' . ucfirst($action) . 'Action';
        if (method_exists($controller, $method)) {
            $controller->{$method}($request);
        }
    }

食用示例:

namespace app\controller;

use Webman\App;
use support\Model;
use support\Request;
use support\Response;

/**
 * 基礎(chǔ)控制器
 */
class Base
{
    protected $halted = false; //標(biāo)識是否中斷
    protected $haltedResult = null; //接收中斷返回的內(nèi)容
    protected $request = null;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public function halted($flag = null)
    {
        if (is_bool($flag)) {
            $this->halted = $flag;
            return;
        }

        return $this->halted;
    }

    public function getHaltedResult()
    {
        return $this->haltedResult;
    }

    // 統(tǒng)一處理action返回的結(jié)果
    public function afterAction($data)
    {
        $script = $this->request->script;
        if (!$data) {
            return view($script, $data);
        }

        return $data;
    }

}
2382 4 0
4個評論

walkor

我說下我看法,不一定對。

1、把view() json() xml() redirect()等函數(shù)獨立出來我覺得是比較解耦的做法,可以在控制器里使用,也可以在非控制器例如隊列里發(fā)送郵件時需要調(diào)用模版時使用。如果你的意思是要把這些函放在控制器基類里,那么當(dāng)你使用這些函數(shù)時就必須繼承基類并且初始化一個控制器才能使用。
當(dāng)然如果喜歡這么用直接自己創(chuàng)建一個基類就可以了。

2、關(guān)于使用$this->request還是傳遞$request,我覺得每次使用request都要打一遍$this->也很繁瑣。如果不喜歡使用參數(shù)$request可以使用函數(shù)request()也可以省略參數(shù)少打很多字。
還有如果控制器里存儲$request這種狀態(tài)數(shù)據(jù)就無法復(fù)用控制器實例,開啟控制器復(fù)用性能會有一定的提升,框架為了兼容兩種方式不能將$request強(qiáng)制存儲在控制器屬性里。
當(dāng)然如果喜歡這樣用就可以像類似你說的寫一個基類將$request存儲在控制屬性里。

3、中間件做的就是攔截請求和響應(yīng)的,所以你說的beforeAction和afterAction可以用中間件直接來做。
參考 http://m.wtbis.cn/plugin/30

你上面說的這些都可以很方便的在webman上改造,但是webman框架不能強(qiáng)制做這些。

  • kaoson 2023-05-30
    1. 在控制器里直接view() json() xml() redirect()都是耦合的,我一直用自己的框架(沒有發(fā)布,因為沒時間搞文檔),在框架建構(gòu)上,我有獨自看法,action返回array或一個賦值器(創(chuàng)建變量的arrayobject對象),交給一個中間件去處理,是否應(yīng)該返回view、json或者xml,根據(jù)客戶端傳遞的參數(shù)確定,比如returntype=json,那么就返回json,默認(rèn)返回view,這樣,就不用重復(fù)去寫代碼。

    基類對很多人來說都是有必要的,我相信大多數(shù)人都會寫基類,我提供的這個基類只是一小部分。另外,可能還會需要兩個以上基類。

    1. 在__construct()中傳遞request是為了代碼封裝,有時候把一部分業(yè)務(wù)邏輯放__construct()中處理比較方便,當(dāng)然,我也認(rèn)為$this->這樣反復(fù)寫也很累,只是建議多提供一種方式。

    2. 中間件能解決類似裝飾器模式的問題,但有時也很繁瑣,如果業(yè)務(wù)邏輯比較復(fù)雜,可能需要寫一堆中間件,其實如果能交給控制器本身處理,反而簡單明了。另外,中間件很難處理控制器里的業(yè)務(wù)邏輯,因為中間件只是簡單的before和after,但如果在控制器里,就可以方便的控制了。

  • walkor 2023-05-31

    1、webman也可以像你說的這樣干,但是webman不能強(qiáng)制這樣做
    2、寫個基類構(gòu)造函數(shù)就解決了,但是為了控制器復(fù)用,webman不能強(qiáng)制這樣做
    3、中間件可以重寫整個控制器處理邏輯,不僅僅簡單的before after

  • kaoson 2023-05-31

    客戶端提交數(shù)據(jù)時,后端如何驗證數(shù)據(jù)?是放中間件?那不是要寫很多中間件?在我自己的框架中,我通常是放beforeAction(全局)或beforeXxxAction(某個),驗證數(shù)據(jù)放控制器里簡單明了,中間件我只用于通用性比較強(qiáng)的業(yè)務(wù)邏輯。

  • walkor 2023-05-31

    之前寫過beforeAction afterAction的插件,beforeAction afterAction是定義在控制器中的,用中間件實現(xiàn)的。
    這個不好在內(nèi)核實現(xiàn),影響性能
    http://m.wtbis.cn/plugin/30

  • uspear 2023-06-09

    客戶端提交數(shù)據(jù)時,后端如何驗證數(shù)據(jù)?自建個validate文件夾在里面處理,walkor大佬可以整個像fastapi框架那要快速就好了。用習(xí)慣了java每次請求接口類型都要自己判斷很不爽……

PHP甩JAVA一條街

兩大佬好厲害, 看不懂說啥

  • wash2018 2023-06-08

    理念上的碰撞,每種方式都用擁護(hù)者,

kaoson

經(jīng)過再三考慮,僅非復(fù)用模式下對__construct()方法加上request參數(shù),before,after相關(guān)方法移入中間件實現(xiàn),但移植后發(fā)現(xiàn)問題,原來是框架強(qiáng)制返回了Response對象,這個還好處理,還有一個比較重要問題,那就是中間件的controller不是原來的controller,是重新new了一個,查了源碼,應(yīng)該還需要修改Container類,另起一片文章討論。

  • 暫無評論
1

cool!

  • 暫無評論
年代過于久遠(yuǎn),無法發(fā)表評論

kaoson

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