上次讲到责任链模式的时候,我顺手实现了一个过滤器,分享给新人。SimpleMVC框架中,过滤器链是整个HTTP请求处理的核心组件。
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
Talk is cheap, show me the code.
上次讲到责任链模式的时候,我顺手实现了一个过滤器,分享给新人。SimpleMVC框架中,过滤器链是整个HTTP请求处理的核心组件。
责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
Talk is cheap, show me the code.
最近在为公司面试新人,经常会问到的一道题目就是PHP类型转换的值,例如:
var_dump((int)true); var_dump((string)true); var_dump((string)false); var_dump((bool)"1"); var_dump((bool)"0"); var_dump((bool)""); var_dump((bool)"false");
我印象中最早见到这道题目是在英极的PHP高级开发工程师岗位的笔试题里面,看似很基础,但是依然可以难住不少PHPer。先来看一下运行结果:
int(1) string(1) "1" string(0) "" bool(true) bool(false) bool(false) bool(true)
对于大多数人来说,第1、2、4行通常是没有问题的。但是为什么false转换为字符串是空字符串呢?在处理请求值时,通常会传一个字符串类型的false,但是“false”(字符串)并非false(布尔),这有点令人疑惑了。
为什么会这样呢? 继续阅读
在并行系统中并发问题永远不可忽视。尽管PHP语言原生没有提供多线程机制,那并不意味着所有的操作都是线程安全的。尤其是在操作诸如订单、支付等业务系统中,更需要注意操作数据库的并发问题。
接下来我通过一个案例分析一下PHP操作数据库时并发问题的处理问题。
首先,我们有这样一张数据表:
mysql> select * from counter; +----+-----+ | id | num | +----+-----+ | 1 | 0 | +----+-----+ 1 row in set (0.00 sec)
最近升级到了Mac OS X 10.10 Yosemite版本,系统的PHP环境也跟着升级了,从原来的5.4升级到了5.5.14。开发系统中的一些PHP扩展库全都木有了,需要重新安装。现在记录一下这个,以备查询。
安装PHP扩展要求你的Mac系统已经安装了Xcode环境和命令行开发工具,如果还没安装,请先使用Shell安装。
xcode-select --install
为了扩展管理方便,首先来安装pecl扩展管理器。
cd /usr/lib/php sudo php install-pear-nozlib.phar
现在软件规模越来越大,PHP项目的开发模式和许多年前已经有了很大变化。记得初学PHP那会儿,boblog是一个很好的例子,几乎可以代表PHP项目的开发模式。当时PHP 5.x以上的版本刚开始流行,仍然有大量的生产环境使用PHP4.x。由于历史遗留的问题,OOP思想在PHP项目中还不是那么广泛流行。随着PHP5.3的发布,PHP项目规模的扩大,在其他语言领域大展身手的OOP开发模式也在PHP中崭露头角。
大型项目不可能是从头开始的,使用社区已经提供的资源可以为项目带来很大的便利。然而各自为政的打包方式、依赖关系的处理,导致了很难将两个开源项目集成到一起。虽然有pear这种PHP官方支持的包管理工具,但是依然没有很好的统一的依赖关系管理的办法。直到Composer的出现。
Composer的依赖关系管理风格,看上去更像Java的Maven。项目编译和打包、依赖关系的解决都可以很轻松的实现。再也不用费神去寻找或者更新第三方库,或者将他们集成到一起。这一切全部都可以交给Composer来完成。
单元测试在软件开发过程中举足轻重,测试先行编程(Test-First Programming),极限编程(XP)和测试驱动开发(TDD)在实践中被广泛的使用,单元测试允许通过编程语言进行契约式设计。
在代码编写完成后,你可以使用PHPUnit来编写测试。然而在错误出现之前创建测试,测试才显得更有一样。所以与其在代码编写完成几个月之后再为它创建测试用例,不如尽早的赶在出现瑕疵的几天甚至几分钟内创建这些测试用例。尽管如此,人们自然而然的可以想到,为何不在瑕疵出现之前,就提前编写好这些测试呢?
测试先行编程是极限编程和测试驱动开发的一部分,基于这种思想我们来实现编程的“极限化”。在现在的电脑运行环境下,我们每天可以将数以千计的测试用例执行个几千次。利用测试的反馈,可以及时地改进每次开发引入的新特性,同时便于利用自动化测试检查可能新被引入的Bug。
最近想用一下PHPUnit来做单元测试。在网上找到了一些资料,还没来得及整理,先贴出来。
PHPUnit: http://phpunit.de/manual/current/en/test-doubles.html
Mock使用进阶: http://www.cnblogs.com/bourneli/archive/2012/09/08/2676981.html
httpd-2.4.4
./configure --enable-so --enable-deflate=shared --enable-ssl=shared --enable-dav=shared --enable-vhost-alias=shared --enable-rewrite=shared --with-mpm=worker
php-5.5.0
./configure --prefix=/usr/local/php-5.5.0 --with-apxs2=/usr/local/httpd-2.4.4/bin/apxs --with-openssl --with-pcre-regex --with-zlib --enable-bcmath --with-bz2 --enable-calendar --with-curl --enable-exif --enable-ftp --with-gd --with-gettext --with-mhash --enable-intl --enable-mbstring --with-mcrypt --with-mysql --with-mysqli --enable-opcache --enable-pcntl --with-pdo-mysql --enable-soap --enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm --with-pear
mysql-5.5.32
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-5.5.32 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci
上线的系统出了个Bug,数据库出现了脏数据,做了一半的事务居然提交了,觉得有点不可思议。但是不可思议的事情居然还大量发生了。
检查相关功能,Bug功能出现在一个自己实现的cron机制触发的定时任务中。由于PHP没有常驻系统的机制,因此计划任务或者定时任务这种东西只能依靠流量驱动,或者利用Linux系统的CRON服务。为了不增加运维人员的维护压力,就选择了前者,使用流量来驱动定时任务检查和触发。
结果,悲剧鸟。 继续阅读
话说PHP官方发布PHP5.4已经有一阵了,根据使用的情况来看,似乎还是很不错的。从初始发布到现在升级到的PHP5.4.4,修正不少的Bug。PHP5.4新的版本,除了提供了更多新的特性,还有大幅的效率提升。这个版本趋于稳定之后,我决定把我的服务器升级到PHP5.4.4。
服务器上的软件包,一直以来都是编译安装,因此对于这些东西自己也是比较可控的。从PHP官方网站下载最新的源代码包,解压缩并且安装,这没有什么特别的。以下是我使用的安装编译参数:
./configure --prefix=/usr/local/php-5.4.4/ --with-config-file-path=/usr/local/php-5.4.4/etc --with-mysql --with-mysqli --with-iconv --with-zlib --enable-xml --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mbstring --with-mcrypt --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --with-pdo-mysql
make ZEND_EXTRA_LIBS='-liconv'
make install