快速稳定的维护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 ...
随机推荐
- 用仿ActionScript的语法来编写html5——第七篇,自定义按钮
第七篇,自定义按钮这次弄个简单点的,自定义按钮.其实,有了前面所定义的LSprite,LBitmap等类,定义按钮就很方便了.下面是添加按钮的代码, function gameInit(event){ ...
- 浅谈C#抽象方法、虚方法、接口
每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...
- fifo manage
typedef struct { TEntry *header; TEntry *tailer; uint16 alloc; uint16 release;}TPoolCtrl;
- Azure 意外重启, 丢失sql server master表和 filezilla
突然发现今晚网站打不开了,提示连不上数据库. ftp也连不上了. 远程连上Azure 发现机器意外重启, 丢失sql server master表和 filezilla 要重新安装. 又耗费我几个小时 ...
- CareerCup: 17.14 minimize unrecognized characters
Oh, no! You have just completed a lengthy document when you have an unfortu- nate Find/Replace misha ...
- python自动化运维之路~DAY1
python自动化运维之路~DAY1 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.文件大小单位单位换算 我们一起看一下下面的图: 没错,都是数字,而且这些数字都是二进制的数字 ...
- 【IOS】2.基础
1.Identifers命名规则 Identifers is combined with letters, underline, dollars, numbers must begin with le ...
- linux for java programer
http://www.kancloud.cn/digest/javaxviii/126781 .查找文件 find / -name filename.txt根据名称查找/目录下的filename.tx ...
- Android 封装Dialog
package com.example.myandroid01; import android.support.v7.app.ActionBarActivity; import android.os. ...
- ORACLE 默认密码确认
select USER_NAME USER_WITH_DEFAULT_PASSWORD from ( select fnd_web_sec.validate_login('AME_INVALID_AP ...