Nodejs koA can be said to be very popular, especially its “onion model” should be used by people who are impressed, here is a try to use PHP to implement a.

Note: This article is the most original version of PHPec framework. PHPec is a simple and lightweight development framework written on this basis. In addition to providing middleware invocation mode, it also provides common automatic routing functions. The initial version has been released on Github. Welcome those who are interested to know about it and make suggestions. Also welcome star.
Github.com/tim1020/PHP…

Expect to use

So let’s see how do I use “this frame”?

require 'app.php';
$app = new App();

$app -> use(function($ctx){
    $ctx -> body.= '>m1';
    $ctx -> next();
    $ctx -> body .= '>m1 end';
});

$app -> use('Middleware2');

$app -> run();Copy the code

Basically like KOA, new an app object, use the use method to add middleware, support closures or external files.

$CTX supports various parameters required for injection, which is easy to be shared by middleware.

The complete code

//app.php class App{ private $m = array(); private $ctx = array(); function next(){ $f = $this -> c -> current(); if(! $f) return; $this -> c -> next(); $f($this); } function run(){ $this -> c = $this -> _gen(); $this -> next(); } private function _gen(){ foreach($this -> m as $v){ yield $v; } } private function _add($m){ if(! empty($this->m) && $this -> m[count($this->m) -1] === false) return; if(! $m){ $this -> m[] = false; }elseif(($m instanceof Closure)){ $this -> m[] = $m; }else{ $m = $this -> _load($m); if(! function_exists($m)){ throw new Exception('middleware error'); } else $this -> m[] = $m; }} private function _load($m){$f = './ /middleware/'.$m.".php"; if(! file_exists($f)) throw new Exception('middleware error'); require $f; return $m; } function __call($m,$v){ if('use' == $m){ $p = isset($v[0]) ? $v[0] : ''; $this -> _add($p); }else{ throw new Exception('method not exists'); } } function __set($k,$v){ print_r($k); print_r($v); $this -> ctx[$k] = $v; } function __get($k){ return isset($this -> ctx[$k]) ? $this -> ctx[$k] : NULL; }}Copy the code

Yes, that’s all the code is.

The code on

Method of use

Use can be added to closures or external files, and PHP5 does not support use as a method name. The override is implemented using __call, which calls the private _add method when use is called.

_add evaluates the parameters passed in. If it is a string, it indicates an external load, determines whether the file and handler function exist and are valid, and adds the handler function to the middleware queue.

If use() passes an empty argument, the middleware behind it is ignored.

Run method

$app -> run() = $app -> run()

  1. Call the private _gen to generate a generator that iterates back to the middleware handler function in the queue.
  2. Call the next method to execute the next middleware (in this case, the first entry)

    2.1 Call the generator’s current method to get the current handler

    2.2 Execute the function (passing $this as an argument, that is, $CTX) and call the generator’s next method to move on to the next handler

  3. Ends when the generator does not return.

The middleware calls $CTX -> next() to pass control to the next middleware, thus iterating through all middleware.

__get and __set methods

__get and __set methods are provided to facilitate the use of $CTX in middleware to set and access undefined values directly. Such as:

$ctx -> body = 'hello';
$ctx -> tplName = 'a.tpl';Copy the code

That is all