摘要:的话,是一个遵循规范微型的框架,作者这样说大致意思的核心工作分发了请求,然后调用回调函数,返回一个对象。执行的方法时,我们从中取出的依赖,这时候,注册的回调函数被调用,返回实例。
Slim
Slim的话,是一个遵循PSR (PSR-7)规范微型的框架,作者这样说:
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs. At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it.
大致意思:slim的核心工作:分发了Http请求,然后调用回调函数,返回一个Http response对象。
Slim其实就帮我们做了两件事
路由的分发
依赖的注入
框架很小,所以别的部分(如db操作、模板引擎)可能需要自己实现,但slim通过依赖注入,让你可以很轻松的组装其他功能到slim中。
快速入门:[ "addContentLengthHeader" => false, ]]; $app = new SlimApp($config); // Define app routes $app->get("/hello/{name}", function ($request, $response, $args) { return $response->write("Hello " . $args["name"]); }); // Run app $app->run();
request代表了当前请求对象,response代表了当前响应对象,$args是占位符的键值对数组。
访问/hello/salamander就会输出Hello salamander
DB是我自己封装的一个PDO的操作类。
$config = ["settings" => [ "addContentLengthHeader" => false, ]]; $app = new SlimApp($config); $container = $app->getContainer(); $container["db"] = function($c) { $dbHost = "localhost"; $dbName = "test"; $dbConf = [ "dsn" => "mysql:dbname={$dbName};host={$dbHost}", "username" => "root", "password" => "******", "charset" => "utf8" ]; $db = new AppLibraryDB(); $db->__setup($dbConf); return $db; }; // Define app routes $app->get("/user/{uid}", "AppControllerIndexController:index");IndexController类
namespace AppController; class IndexController { protected $container; public function __construct(ContainerInterface $container) { $this->container = $container; } public function index($request, $response, $args) { $info = $this->container["db"]->fetch("SELECT name FROM user WHERE uid = :uid", [ "uid" => $args["uid"] ]); echo "user name is " . $info["name"]; } }
IndexController类的是通过composer自动载入的(代码中没写):
"autoload": { "psr-4": { "App": "app/" } },
代码中可以发现,依赖容器的注入是在类实例化的时候发生的。执行IndexController的index方法时,我们从$container中取出的db依赖,这时候,注册的回调函数被调用,返回实例。因为是用到时才实例化,这个叫做延迟实例化。
结合SwooleSwoole让PHP可以常驻内存,而且它提供了Http Server的功能,所以Slim和Swoole没什么冲突。
思考Slim是通过当前路由(譬如/user/2,不带查询字符串)和http方法来找到正确的回调函数的。这些量Slim是从哪里取的呢?肯定是$_SERVER。查看slim源码:
run()方法:
public function run($silent = false) { $response = $this->container->get("response"); try { ob_start(); $response = $this->process($this->container->get("request"), $response); } catch (InvalidMethodException $e) { $response = $this->processInvalidMethod($e->getRequest(), $response); } finally { $output = ob_get_clean(); } if (!empty($output) && $response->getBody()->isWritable()) { $outputBuffering = $this->container->get("settings")["outputBuffering"]; if ($outputBuffering === "prepend") { // prepend output buffer content $body = new HttpBody(fopen("php://temp", "r+")); $body->write($output . $response->getBody()); $response = $response->withBody($body); } elseif ($outputBuffering === "append") { // append output buffer content $response->getBody()->write($output); } } $response = $this->finalize($response); if (!$silent) { $this->respond($response); } return $response; }
发现$request对象是从容器取出来的,那$request是怎么注册的呢??,那就看App类的构造函数了,最后发现Container类的构造函数中有registerDefaultServices()方法:
private function registerDefaultServices($userSettings) { $defaultSettings = $this->defaultSettings; /** * This service MUST return an array or an * instance of ArrayAccess. * * @return array|ArrayAccess */ $this["settings"] = function () use ($userSettings, $defaultSettings) { return new Collection(array_merge($defaultSettings, $userSettings)); }; $defaultProvider = new DefaultServicesProvider(); $defaultProvider->register($this); }
查看$defaultProvider->register()方法:
public function register($container) { if (!isset($container["environment"])) { /** * This service MUST return a shared instance * of SlimInterfacesHttpEnvironmentInterface. * * @return EnvironmentInterface */ $container["environment"] = function () { return new Environment($_SERVER); }; } if (!isset($container["request"])) { /** * PSR-7 Request object * * @param Container $container * * @return ServerRequestInterface */ $container["request"] = function ($container) { return Request::createFromEnvironment($container->get("environment")); }; } //...
可以看到$request对象是通过Request::createFromEnvironment方法构造的,它需要从容器中取出environment依赖,而environment依赖是通过构造一个Environment对象得来的,它正好放入了$_SERVER
查看Environment类源码,可以发现它继承了Collection类,Collection的构造函数如下:
public function __construct(array $items = []) { $this->replace($items); }
从上面我们可以得出,我们主要注册一个自定义的environment依赖就行,原来$_SERVER的信息可以从swoole的$request->server中取。
简单实现server.php
on("start", function ($server) { echo "Swoole http server is started at http://0.0.0.0:8888 "; }); $http->on("request", function ($request, $response) { // Instantiate the app $config = [ "settings" => [ "addContentLengthHeader" => false, ] ]; $config["environment"] = function () use($request) { $server = []; foreach ($request->server as $key => $value) { $server[strtoupper($key)] = $value; } return new Environment($server); }; $app = new SlimApp($config); // Register routes require APP . "/routes.php"; // Run app $slimResponse = $app->run(true); $headers = $slimResponse->getHeaders(); foreach ($headers as $name => $values) { $response->header($name, implode(", ", $values)); } $response->header("X-Powered-By", "Salamander"); $response->end($slimResponse->getBody()); }); $http->start();
注意$request->server中key都是小写的,所以这里转化了一下。
routes.php(在App目录中)
get("/", function (Request $request, Response $response) { $response->getBody()->write("Hello Salamander"); return $response; }); $app->get("/user/{uid}", function (Request $request, Response $response, $args) { $response->getBody()->write("Hello User:" . $args["uid"]); return $response; });测试
访问/
访问/user/45
打包下载测试百度云盘
tip:环境基于docker的,运行docker-compose up即可
Issue
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/28198.html
摘要:使开发人员可以编写高性能的异步并发,服务。使用作为网络通信框架,可以使企业研发团队的效率大大提升,更加专注于开发创新产品。总之,这个库让可以常驻内存,并提供了,等功能。 swoole 使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(...
摘要:使开发人员可以编写高性能的异步并发,服务。使用作为网络通信框架,可以使企业研发团队的效率大大提升,更加专注于开发创新产品。总之,这个库让可以常驻内存,并提供了,等功能。 swoole 使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(...
摘要:总之,是用来管理多个容器的,用都会写一个开启所有服务关闭所有服务上面说了,关键是编排好,以下就是的目录结构访问在目录下运行命令,在浏览器访问可以看到讲解和都是用了官方的镜像,而是从本地构建的。 Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,...
摘要:总之,是用来管理多个容器的,用都会写一个开启所有服务关闭所有服务上面说了,关键是编排好,以下就是的目录结构访问在目录下运行命令,在浏览器访问可以看到讲解和都是用了官方的镜像,而是从本地构建的。 Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,...
阅读 2380·2021-11-15 11:38
阅读 2803·2021-11-02 14:44
阅读 3715·2021-09-26 10:13
阅读 3025·2021-08-13 15:02
阅读 736·2019-08-30 15:56
阅读 1358·2019-08-30 15:53
阅读 2338·2019-08-30 13:01
阅读 3165·2019-08-29 12:57