快速稳定的维护PHP
Just to recap, previously we'd have this sort of thing:
namespace me\adamcameron\testApp; use GuzzleHttp\Client; class GuzzleAdapter { private $client; private $endPoint; public function __construct($endPoint){ $this->endPoint = $endPoint; $this->client = new Client(); } public function get($id){ $response = $this->client->requestAsync( "get", $this->endPoint . $id ); return $response; } }
And say a logging decorator for that:
namespace me\adamcameron\testApp; class LoggedGuzzleAdapter { private $adapter; private $logger; public function __construct($adapter, $logger) { $this->adapter = $adapter; $this->logger = $logger; } public function get($id){ $this->logger->logMessage(sprintf("Requesting for %s", $id)); $response = $this->adapter->get($id); $body = $response->getBody(); $this->logger->logMessage(sprintf("Response for %s: %s", $id, $body)); return $response; } }
And we'd init our adapter thus:
$endPoint = "http://cf2016.local:8516/cfml/misc/guzzleTestEndpoints/getById.cfm?id="; $guzzleAdapter = new GuzzleAdapter($endPoint); $logger = new LoggingService(); $adapter = new LoggedGuzzleAdapter($guzzleAdapter, $logger);
So the underlying GuzzleAdapter handles the Guzzle stuff, the LoggedGuzzleAdapter handles just the logging stuff, but defers to its GuzzleAdapter to do its part of the job, and keeps all the moving parts and bits of functionality sensibly separated. And it's pretty simple. And as detailed in those earlier articles, we can keep layering decorators around an adapter to add caching or what-have-you in a similar way. Easy. Nice.
However this only works cos the call to Guzzle actually returns the result on the spot. And this is cos we were using it synchronously: we make a call to it, it blocks until it gets the answer back from the target and gives us the answer.
Now that we're using async calls, Guzzle doesn't give us the answer, it just gives us a Promise which will eventually resolve to be the answer. This is in theory good cos it means the calling code can make a bunch of HTTP calls, and not wait around for each of them to resolve in series: Guzzle will actually make them all in parallel. I have a look at this in article " PHP: async requests using Guzzle and request pools ".
If we go back to our decorator we can see the problem :
public function get($id){ $this->logger->logMessage(sprintf("Requesting for %s", $id)); $response $promisedResponse = $this->adapter->get($id); $body = $response $promisedResponse->getBody(); $this->logger->logMessage(sprintf("Response for %s: %s", $id, $body)); return $response $promisedResponse; }
At the point at which our decorator needs the body ... we don't have it yet. All we have is a promise that at some point we'll have a body (or we'll have response object via the resolved promise, anyhow; and the response object will have the body ).
To get the body we first need to wait for the promise to resolve... which is a blocking operation and kinda defeats the purpose of using the async approach in the first place. IE: we could do this sort of thing :
public function get($id){ $this->logger->logMessage(sprintf("Requesting for %s", $id)); $promisedResponse = $this->adapter->get($id); $response = $promisedResponse->wait(); $body = $response->getBody(); $this->logger->logMessage(sprintf("Response for %s: %s", $id, $body)); return $response; }
But doing the wait immediately defeats the purpose of making the call async in the first place. We want the wait call to... err... wait ... until the calling code says "right I need to actually use that data now".
Our initial attempt to sort this out was to analyse the issue as being one of "well we don't have the data we need until we call wait , so then we need to do the logging then... which means we need to intercept the wait call... which means we need to return our own decorated version of the response from the call to the adapter with its own wait and have a LoggedResponse, and return that from the code above..." But... and I hope my colleague doesn't mind me saying... when I saw this code in code review I kinda went "there must be a better, more semantic way of doing this". I won't repeat the code as I cannot use our actual work code in my blog, and I am not in the office right now and can't remember the detail of the implementation anyhow. But it's not ideal, so I don't want to share it anyhow.
I've been off sick for the last coupla days, which gives me a lot of time to deliberate and mess around with stuff and google a lot more than I allow myself time for when I'm in the office. With a wee bit of "standing back and having another think about it", the solution became clear. We don't need to explicitly override the wait method before we call it... the promise builds that capability in! At the time we're making the call, we get to tell the Promise what happens when it gets resolved. So I've knocked together this proof of concept:
public function get($id){ $this->logger->logMessage(sprintf("(%s) Requesting for %s", $this->thisFile, $id)); $response = $this->adapter->get($id); $response->then(function($response) use ($id){ $body = $response->getBody(); $this->logger->logMessage(sprintf("(%s) Response for %s: %s", $this->thisFile, $id, $body)); $body->rewind(); }); return $response; }
默认路由从url映射到文件的应用层级可通过配置项:route_app_hierarchy=>1,来修改。即应用n层*控制器n层来处理复杂的业务分层
控制器后缀支持自定义配置.默认还是Controller
mysql支持关闭数据缓存
CmlPHP 是基于php5.3+(v2.7+要求php5.4+)版本(已经测试过php7)开发的MVC/HMVC/MVSC/HMVSC框架,支持composer、分布式数据库、分布式缓存,支持文件、memcache、redis、apc等缓存,thg支持多种url模式、URL路由[RESTful],支持多项目集成、第三方扩展、支持插件。
快速稳定的维护PHP的更多相关文章
- 最新番茄花园win7系统快速稳定版
这是最新番茄花园win7系统64位快速稳定版 V2016年2月,该系统由系统妈整理和上传,系统具有更安全.更稳定.更人性化等特点.集成最常用的装机软件,集成最全面的硬件驱动,精心挑选的系统维护工具,加 ...
- Win7 SP1 32位 旗舰版 IE8 快速稳定 纯净优化 无人值守 自动激活 20170518
一.系统特色 1.采用微软原版旗舰版定制而成. 2.优化系统服务,关闭一些平时很少使用的服务. 3.精简掉一些无用的东西. 4.系统全程离线制作,不包含任何恶意插件,放心使用. 5.右下角时间加上星期 ...
- Win7 SP1 64位 旗舰版 IE8 快速稳定 纯净优化 无人值守 自动激活 20180604
一.系统特色 1.采用微软原版旗舰版定制而成. 2.优化系统服务,关闭一些平时很少使用的服务. 3.精简掉一些无用的东西. 4.系统全程离线制作,不包含任何恶意插件,放心使用. 5.右下角时间加上星期 ...
- ThinkPHP框架介绍
什么是框架 php框架是许多代码的集合,这些代码的程序结构的代码(并不是业务代码)代码中有许多的函数,类,功能类包 不使用框架开发的缺陷 代码编写不规范 牵一发而动全身 不能很好满足客户各方面的需求 ...
- ASP.NET MVC 多语言实现技巧 最简、最易维护和最快速开发
说说传统做法的缺点 1.做过多语言的都知道这玩意儿太花时间 2.多语言架构一般使用资源文件.XML或者存储数据库来实现.这样就在一定程序上降低了性能 3.页面的可读性变差,需要和资源文件进行来回切换 ...
- 转:ASP.NET MVC 多语言实现技巧 最简、最易维护和最快速开发
说说传统做法的缺点 1.做过多语言的都知道这玩意儿太花时间 2.多语言架构一般使用资源文件.XML或者存储数据库来实现.这样就在一定程序上降低了性能 3.页面的可读性变差,需要和资源文件进行来回切换 ...
- CODING 静态网站服务升级,快速、稳定、高拓展!
CODING 静态网站拥有强大的页面托管服务,目前已有数万开发者.设计师.产品经理.团队与企业使用 CODING 静态网站托管了他(她)们的个人网站.博客.企业与产品官网.在线文档等.CODING 静 ...
- IPFS - 可快速索引的版本化的点对点文件系统(草稿3)
摘要 星际文件系统是一种点对点的分布式文件系统, 旨在连接所有有相同的文件系统的计算机设备.在某些方面, IPFS类似于web, 但web 是中心化的,而IPFS是一个单一的Bittorrent 群集 ...
- github入门到上传本地项目【网上资源整合】
[在原文章的基础上,修改了描述的不够详细的地方,对内容进行了扩充,整合了网上的一些资料] [内容主要来自http://www.cnblogs.com/specter45/p/github.html#g ...
随机推荐
- 串口通信类,WPF
参考之前的资料,写了一个自己常用的串口类, 字符串发送类型用了两种方式,char[] 和byte[] : 数据接收也是采用两种 char[] 和byte[] 两种. 类代码贴出来: public cl ...
- Vue.2.0.5-事件处理器
监听事件 可以用 v-on 指令监听 DOM 事件来触发一些 JavaScript 代码. 示例: <div id="example-1"> <button v- ...
- PLSQL 的简单命令之三
-- 查找两个表中ID相等的 select a.id, a.name,b.math from stu a,scores b where a.id = b.id -- 右外连接 select b.id, ...
- 通常Struts框架会自动地从action mapping中创建action对象
开发者不必在Spring中去注册action,尽管可以这么去做,通常Struts框架会自动地从action mapping中创建action对象 struts2-spring-plugin-x-x-x ...
- Unable to instantiate Action...............
当时找了好久都没搞明白,出现这样的问题,可能不是代码错了.将新添加的action不要添加在末尾,这样可能导致这样的问题出现,所以新添加的action最好放置在struts配置文件中间.
- Java基础之创建窗口——使用边界布局管理器(TryBorderLayout)
控制台程序. 边界布局管理器最多能在容器中放置5个组件.在这种布局管理器中,可以把组件放在容器的任意一个边界上,也可以把组件放在容器的中心.每个位置只能放置一个组件.如果把组件放置在已被占用的边界上, ...
- notpad++安装python插件
1.安装python并添加到环境变量 2.在notpad++ 运行工具下点击运行,输入如下命令: cmd /k python "$(FULL_CURRENT_PATH)" & ...
- spring AutowireCapableBeanFactory 自动注入
文档:http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/Auto ...
- C++Primer 第十五章
//1.面向对象程序设计的核心思想是数据抽象,继承,动态绑定. // 通过使用数据抽象,我们可以将类的接口和实现分离 // 使用继承,可以定义相似的类型并对其相似关系建模 // 使用动态绑定,可以在一 ...
- SQL 数据库 子查询、主外键
子查询,又叫做嵌套查询. 将一个查询语句做为一个结果集供其他SQL语句使用,就像使用普通的表一样,被当作结果集的查询语句被称为子查询. 子查询有两种类型: 一种是只返回一个单值的子查询,这时它可以用在 ...