Php
Thu, Jan 19, 2017
这两天看一本PHP的进阶书,发现了一些之前没有注意的特性。比如PHP接口的设计方式和它对实现该接口的类的约束就和通常的语言(比如Java)不

Wed, Jan 18, 2017
这里记录一下如何在PHP5的扩展中创建变量,包括局部变量和全局变量。 必备知识 PHP内部有符号表的概念,其中局部变量存放在指针active_s


Tue, Apr 5, 2016
从开始写PHP就知道迭代器这个东西,当时师傅告诉我用的挺少的,需要的时候再看也不晚,于是就没有放在意上。但他还说这其实也是区分高手和菜鸟的一

Fri, Apr 1, 2016
今天花了点时间测试了开源项目seaslog和PHP内置的error_log的性能。本文不涉及该扩展的安装和使用,如果对其不了解,可移步官网。 项目的描述有语法问题”A effective …“,我提醒了原作者,然而并没有被理会。。。 测试环境 项目 属性 CPU Intel® Xeon® CPU E5520 @ 2.27GHz 8核 内存 48G PHP 7.0.1 Nginx 1.2.7 测试代码 <?php error_log("I am testing performance of error_log" . PHP_EOL, 3, __DIR__ . '/error_log.log'); SeasLog::debug("I am testing performance of seaslog"); 结果数据 每种方式测试5次,请求次数1000次,并发量分别是1, 10, 100, 1000。分别记录每次测试的QPS。 1. error_log 并发量 1 2 3 4 5 1 2430 2579 2685 2484 2622 10 7303 7844 5892 11739 9002 100 11763 6107 6921 9258 11999 1000 324 891 324 889 883 2.

Mon, Feb 1, 2016
终于把困扰我很久的问题搞定了,好开心。趁着记忆还热乎,一定要把它记下来。 前几天还和同事抱怨,用Yaf框架的人那么多,但我们身边竟然没有一个人对它的用法很清楚的。真是有些悲哀。几个同事都说鸟哥写的Yaf文档看不明白。 言归正传,就我自己的学习过程来看,如果你要自己搭建一个Yaf环境,遇到的问题可能主要有以下这些: 配置Nginx的rewrite规则 命名空间怎么用 目录结构设置 插件的使用 单Controller多Action配置 多模块配置 更多配置文件 下面就这些问题一一给出解答。 配置Nginx的rewrite规则 让我们直接忽略Apache和Lighttpd吧,默认大家都用Nginx。 Yaf路由规则 如果你看过官方文档,那4种路由规则我就不说了,只说最简单也是默认的Yaf_Route_Static。 读了Yaf源码的同学会发现,其实这个规则就是解析request_uri,用/把它分开,然后用每一部分去匹配Module/Controller/Action/Param。举个例子吧,假设PATH=/foo/bar/doge,更通俗一点,如果你的域名是http://yaf.dev,那么这个例子中的完整URL就是http://yaf.dev/foo/bar/doge。 路由规则做了以下动作: 解析URL,得到PATH部分 认为foo是Module,去application.modules配置中找Foo(不区分大小写) 如果找到了modules/Foo,则继续认为bar是Controller,查找modules/Foo/BarController;没找到则会认为foo是Controller,下面同4 如果找到了modules/Foo/BarController,则继续认为doge是Action,查找modules/Foo/BarController/dogeAction 这样是不是很清晰了? 不要这样配 老湿老湿,你不是要说Nginx的rewrite规则怎么配吗,怎么在这讲起了路由规则? 我是要告诉你不要听那些自作聪明的人(没错就是我)把rewrite规则配错!!! 也就是说 rewrite ^/(.*) /index.php/$1 last; 是绝对正确的,不要看谁谁谁说这不对而写成 rewrite ^/(.*) /index.php?$1 last; 这才是错误的。 我的配置: server { listen 80; root /var/www/yaf.ubuntu.com/public; index index.php index.html; server_name yaf.ubuntu.com; location = /favicon.ico { access_log off; error_log off; log_not_found off; } if (!-e $request_filename) { rewrite ^/(.

Sat, Jan 9, 2016
下载安装Composer 到composer官网按照指示下载。官方建议的是用curl -sS https://getcomposer.org/installer | php这条命令。可能有些同学会迷惑这是在干什么,这其实是为了保证你下载到的总是最新的composer。分析一下,首先看到了管道,把前面curl获取的结果交给php执行,执行的结果就是下载了一个最新的composer.phar到当前目录下。这时虽然也可以说已经能用了,但通常我还会把它链接到/usr/local/bin目录下,方便使用。 sudo ln -s /home/frost/packages/composer.phar /usr/local/bin/composer 这时在终端输入composer就应该能看到它的帮助信息了。 配置Packagist 原本这不是必需的,但由于众所周知的原因,我还是建议配置一下。具体见这里。 composer config -g repositories.packagist composer http://packagist.phpcomposer.com就可以了。 composer.json 简单起见,这里使用monolog/monolog为例。 要使用composer,首先需要一个composer.json文件,它描述了项目依赖关系及其他一些元信息。 require关键字 require可能是你第一个也是唯一需要制定的东西。它用来告诉Composer你的项目需要依赖哪些包。 { "require": { "monolog/monolog": "1.0.*" } } 如你所见,require接受一个包含包名(monolog/monolog)和版本限制(1.0.*)的映射的对象。 包名 包名由vendor名和项目名组成。两者经常会是相同的——vendor名的存在只是为了避免名称冲突。它可以允许两个人创建同一个名称的库json,这样两个包名就可能是igorw/json和seldaek/json了。 这里我们“需要”monolog/monolog,所以vendor名和项目名一样。建议对项目使用唯一的名字。稍后还允许同一个命名空间下的多个项目。如果你在维护一个库,这可以让你很容易的把它分成多个解耦的小部分。 包版本 上面的例子中我们“需要”版本1.0.*,这表示1.0版本的所有分支。 版本限制可以用多种不同的方式,这里给出了详细的解释。 稳定性 默认情况下只考虑稳定版本。如果你也希望用RC, beta, alpha或者开发版,可以用稳定性标识。为了不用为每个包单独设置稳定性标识,还可以用最小稳定性 安装依赖 要安装依赖,只需要执行composer install即可。 这会找到符合版本限制的最新版本的monolog/monolog,并且把它下载到vendor目录。把第三方的代码放在一个名为vendor的目录是一个规范。在本例中,会把它放在vendor/monolog/monolog。 如果你使用git,通常会把vendor目录放在.gitignore中。 你会注意到composer install命令还会在当前目录下生成一个composer.lock文件。 composer.lock锁文件 安装完依赖后,Composer会把它安装的精确版本号写入composer.lock文件中。它把项目锁定在某个特定的版本号。 把composer.lock文件和composer.json一起提交到版本控制中。这很重要,因为install命令会检查锁文件是否存在,如果存在,它就会下载指定的精确版本,否则就会按照composer.json的描述下载符合约束的最新版本。 这意味着每个下载了你的项目的人看到的都是完全相同的代码,不会因为依赖更新了就自动更新依赖。update命令会将依赖更新到符合要求的最新版本,然后更新锁文件。 update命令也可以指定单独的包名来更新指定的包。 Packagist Packagist是Composer的信息库。一个Composer信息库本质上是一个包的源——从这里你可以获取包。Packagist希望成为每个人用的中心信息库。这意味着你可以自动require任何这里存在的包。 自动加载 对于指定了自动加载信息的库,Composer会生成一个vendor/autoload.php文件。你可以放心的include这个文件而Composer会完成剩下的工作。 require __DIR__ . '/vendor/autoload.php'; 这让使用第三方代码很方便。比如,如果你的项目依赖Monolog,你可以马上开始使用它的类,它会被自动加载。 $log = new Monolog\Logger('name'); $log->pushHandler(new Monolog\Handler\StreamHandler('app.

Wed, Nov 25, 2015
本文只是给自己搞的一个小封装做个入口。 一次给同事写的一个接口做重构,上线以后发现性能恶化严重,导致了线上的严重问题,我马上想到用xhprof

Sat, Sep 26, 2015
上一篇中讲了PHP单元测试的一些简单概念,这里详细说一下会用到的各种assert*函数。官方文档按照字母顺序逐一讲述了这些方法,但我觉得那很不合适,至少应该大概按照类别来分类。 数组相关 assertArrayHasKey($expected_key, $actual_array) 如果$expected_key是$actual_array中元素的一个键值,则通过,否则不通过。也即 foreach ($actual_array as $k => $v) { if ($k === $expected_key) { // 测试通过 return true; } // 测试不通过 return false; } assertArraySubset($subset_array, $actual_array) 如果$subset_array是$actual_array的一个子数组,则通过,否则不通过。也即前者是后者的子集,这点很重要,其实由于在PHP中数组是作为HashTable存储的,所以是一般并不存在顺序的问题。因此这里只要求前者是后者的子集,而至于顺序则不要求。 assertCount($count, $array) 如果count($array) === $count)则通过。注意这里$count的类型必须是整数。 类属性相关 assertClassHasAttribute($attributeName, $className) 如果类名为$className的类拥有一个名为$attributeName的属性,则通过,否则不通过。值得注意的是,这个测试通过与否与属性的值是否设置没有关系,即使是只声明了名为$attributeName的属性,这个测试也是通过的,但实例化该类之后var_dump(new ClassAttr()->attr)的结果却是false。 assetClassHasStaticAttribute($staticAttributeName, $className) 这个自不必多说,和上面类似。只是用来判断静态属性。 对象关系 assertObjectHasAttribute($attributeName, $object) 如果对象$object拥有属性$attributeName,则通过。 包含关系 assertContains($needle, $haystack) 如果$haystack中包含$needle,则通过,否则不通过。这个包含可以是数组的包含,也可以是字符串的包含,注意,默认是区分大小写的,即assertContains('foo', 'FooBar')是不能通过测试的。但assertContains('foo', 'FooBar', '', true)则可以通过测试,也就是说第四个参数表示不区分大小写。至于第三个参数,其实是$message,也就是在测试不通过时报告 详细信息的,我个人理解和try/cache里面的Exception $e里面的getMessage()可能有点类似,没有深究。

Tue, Sep 22, 2015
我自认对这种比较系统的知识总是比较欠缺,所以还是花点时间补充上比较好。 这里说一下PHP的单元测试。 首先是搭建可以进行单元测试的环境,这里我首