brtriver/karen

简单的PSR-7微型框架,适用于PHP7

v0.2.1 2016-01-06 11:33 UTC

This package is not auto-updated.

Last update: 2024-09-14 18:20:39 UTC


README

Karen是一个简单的PSR-7微型框架,适用于PHP7。此框架提供了以下块名称和简单的控制器类:

  • 容器
  • 中间件
  • 路由
  • 响应
  • 运行

您只需用PSR-7对象以您自己的方式编写代码。

Karen默认使用以下组件

  • PSR-7请求、响应
    • zendframework/zend-diactoros
  • 中间件
    • relay/relay
  • 容器
    • pimple/pimple
  • aura/router
  • twig/twig

需求

  • PHP 7.0或更高版本。

安装

php -r "eval('?>'.file_get_contents('https://getcomposer.org.cn/installer'));"
php composer.phar create-project brtriver/karen ./your_app

演示

cd your_app
make server

然后在浏览器中打开 https://:8888/hello/karen_girls。如果尝试FastRoute版本,请打开 https://:8888/karen2/hello/karen_girls

用法

web/index.php

<?php
require __DIR__ . '/../vendor/autoload.php';

$app = new class extends Karen\Framework\Karen {
        public function action($map)
        {
            // hello name controller sample.
            $map->get('hello', '/hello/{name}', function($args, $controller) {
                $name = $args['name']?? 'karen';
                return $controller->render('[Karen] Hello, ' . $name);
            })->tokens(['name' => '.*']);

            // with twig
            $map->get('render_with_twig', '/template/{name}', function($args, $controller) {
                return $controller->renderWithT('demo.html', ['name' => $args['name']]);
            });

            return $map;
        }
    };

$app->run();
$app->sendResponse();

您必须使用匿名函数编写控制器的逻辑

$map->get('hello', '/hello/{name}', function($args, $controller) {
    $name = $args['name']?? 'karen';
    return $controller->render('Hello, ' . $name);
})->tokens(['name' => '.*']);

如果您编写自己的应用程序类并在其中编写逻辑,而不是匿名类,则它应该是简单的

<?php
$app = new YourFramework(); // YourFramework class extends Application class and implement your logic.
$app->run();
$app->sendResponse();

$args 是路由路径的参数,而 $controllerKaren\Controller 类的实例。

Karen\Controller 有一个 render 方法。这等于 $controller->response->getBody()->write($output)

扩展控制器

例如,您想要不使用模板引擎进行渲染

$c['controller'] = new Controller();

如果您想使用像Twig这样的模板引擎,您只需使用匿名类和特质来编写

$c['controller'] = function($c) {
    $controller = new class extends Controller{
            use Templatable;
        };
    $controller->setTemplate($c['template']);

    return $controller;
};

创建自己的框架

此微型框架应用程序是一个简单的模板方法模式。

    public function run()
    {
        $this->container();
        $this->middleware();
        $this->route();
        $this->response();
    }

这个抽象应用程序了解请求、响应、MiddlewareBuilder(Relay),因此您必须编写自己的应用程序逻辑在您的扩展应用程序类的容器、中间件、路由和响应方法中。这些方法由 run() 方法执行。

方法

容器

创建您的容器并在容器中设置必要对象

    public function container()
    {
        $this->c = new Container();
        $this->c['template'] = function($c) {
            $loader = new \Twig_Loader_Filesystem( __DIR__ . '/../../templates');
            return new \Twig_Environment($loader, array(
                'cache' => '/tmp/',
            ));
        };
    }

Karen使用pimple,但您可以更改它。

中间件(可选)

中间件方法是添加您的中间件,通过 $this->addQueue() 方法按需进行。Karen使用(Relay)[http://relayphp.com/],因此您必须传递具有以下签名的可调用对象

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\RequestInterface as Request;

function (
    Request $request,   // the request
    Response $response, // the response
    callable $next      // the next middleware
) {
    // ...
}

这是一个通过查询参数(状态)更改状态的示例

    public function middleware()
    {
        // if open https://:8888/hello/ssss?status=404, response status is set to 404
        $this->addQueue('changeStatus', function (Request $request, Response $response, callable $next) {
            $response = $next($request, $response);
            $status = $request->getQueryParams()['status']?? null;
            if ($status) {
                $response = $response->withStatus((int)$status);
            }

            return $response;
        });
    }

路由

路由方法用于定义您的应用程序路由和控制器逻辑

    public function route()
    {
        $map = $this->c['router']->getMap();
        // define routes at an action method in an extended class
        $map->get('hello', '/hello/{name}', function($args, $controller) {
            $name = $args['name']?? 'karen';
                return $controller->render('[Karen] Hello, ' . $name);
            })->tokens(['name' => '.*']);
        $this->route = $this->c['router']->getMatcher()->match($this->request);;
    }

或者,如果您使用匿名类,您可以将逻辑写入此类

  • 路由方法
    public function route()
    {
        $map = $this->c['router']->getMap();
        // define routes at an action method in an extended class
        $map = $this->action($map);
        $this->route = $this->c['router']->getMatcher()->match($this->request);;
    }
  • 匿名类
$app = new class extends Karen\Framework\Karen {
        public function action($map)
        {
            // hello name controller sample.
            $map->get('hello', '/hello/{name}', function($args, $controller) {
                $name = $args['name']?? 'karen';
                return $controller->render('[Karen] Hello, ' . $name);
            })->tokens(['name' => '.*']);

            return $map;
        }
    };

如果您将Aura.Route更改为其他版本,请阅读 src/Framework/Karen2.php

响应

在响应方法中,您必须将您的控制器可调用处理程序传递给 $this->addQueue('action', $handler, $args)。获取 $handler 的方法不同,因为它取决于您选择的路由库。

  • Aura.Router版本(Karen.php)
    public function response(){
        if (!$this->route) {
            $response =$this->response->withStatus(404);
            $response->getBody()->write('not found');
            return;
        }

        // parse args
        $args = [];
        foreach ((array)$this->route->attributes as $key => $val) {
            $args[$key] = $val;
        }
        // add route action to the queue of Midlleware
        $this->addQueue('action', $this->c['controller']->actionQueue($this->route->handler, $args));
    }
  • FastRoute版本(Karen2.php)
    public function response(){
        switch ($this->route[0]) {
            case \FastRoute\Dispatcher::NOT_FOUND:
                echo "Not Found\n";
                break;
            case \FastRoute\Dispatcher::FOUND:
                $handler = $this->route[1];
                $args = $this->route[2];
                $this->addQueue('action', $this->c['controller']->actionQueue($handler, $args));
                break;
            default:
                throw new \LogicException('Should not reach this point');
        }
    }

执行此响应方法后,中间件队列将自动执行。

如果您想使用JsonResponse

$map->get('json', '/json/{name}', function($args, $controller) {
    return new \Zend\Diactoros\Response\JsonResponse(['name' => $args['name']]);
});

您自己的框架

在此模式中,您只需在这些方法中实现您的框架逻辑。

$app = new YourApplication(); // extends Karen\Application
$app->run();
$app->sendResponse();

例如,Karen2是一个使用FastRoute而不是Aura.Router的示例微型框架,但您只需调用相同的方法。请参阅代码 web/karen2/index.phpsrc/Framework/Karen2.php

require __DIR__ . '/../../vendor/autoload.php';

$app = new class extends Karen\Framework\Karen2 {
        public function handlers()
        {
            return function(FastRoute\RouteCollector $r) {
                $r->addRoute('GET', '/karen2/hello/{name}', function($args, $controller){
                    return $controller->render('[Karen2] Hello ' . $args['name']);
                });
            };
        }
    };

$app->run();
$app->sendResponse();

请随意为PHP7创建自己的框架。

许可证

Karen遵循MIT许可证。