Phalcon是一个C语言写的高性能PHP框架,相比PHP写的框架,它作为PHP的扩展在进程开启时便加载了,节省了每一次请求时的类库加载、MVC框架分派的开销。前面提到的使用Zephir来开发PHP扩展也是这个项目贡献的。
在CentOS 上安装Phalcon,因为之前安装过zephire了,所以直接下载cphalcon来编译安装就可以了,可以参照这里安装所需其他lib
1 2 3 4 5 | git clone --depth=1 git: //github .com /phalcon/cphalcon .git cd cphalcon /build/ sudo . /install sudo vim /etc/php .d /phalcon .ini |
创建phalcon.ini增加以下内容
1 2 | [phalcon] extension=phalcon.so |
这里单独把phalcon.ini单独配置,是因为Phalcon扩展加载要在PDO扩展之后,而我的PDO也是单独配置的。如果不是的话会提示这个错误:
1 2 | $ php -m | grep phalcon PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/phalcon.so' - /usr/lib64/php/modules/phalcon .so: undefined symbol: php_pdo_get_dbh_ce in Unknown on line 0 |
与Zend Framwork类似,Phalcon也提供开发工具用于快速生成项目骨架
1 2 3 4 5 6 7 | git clone https: //github .com /phalcon/phalcon-devtools .git cd phalcon-devtools . /phalcon .sh sudo ln -s ~ /phalcon-devtools/phalcon .php /usr/bin/phalcon sudo chmod ugo+x /usr/bin/phalcon phalcon commands |
注意,这个开发工具也是需要依赖Phalcon扩展的,否则会提示
1 2 3 4 | $ phalcon command PHP Fatal error: Class 'Phalcon\Script' not found in /home/vagrant/phalcon-devtools/phalcon .php on line 40 PHP Stack trace: PHP 1. {main}() /home/vagrant/phalcon-devtools/phalcon .php:0 |
生成一个测试项目store
1 | phalcon scaffold store |
按照官方的Nginx说明配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | server { listen 8005; server_name store.localhost; index index.php index.html index.htm; set $root_path '/usr/share/nginx/html/tutorial/store/public'; root $root_path; try_files $uri $uri/ @rewrite; location @rewrite { rewrite ^/(.*)$ /index.php?_url=/$1; } location ~ \.php { fastcgi_pass unix:/tmp/php5-fpm.sock; fastcgi_index /index.php; include fastcgi.conf; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~* ^/(css|img|js|flv|swf|download)/(.+)$ { root $root_path; } location ~ /\.ht { deny all; } } |
访问一下192.168.33.14:8005,提示:Access denied。。。查看Nginx错误日志
1 2 | [root@vagrant nginx] # tail -n 20 error.log 2015 /07/28 03:41:42 [error] 7343 #0: *1 FastCGI sent in stderr: "Access to the script '/usr/share/nginx/html/tutorial/store/public' has been denied (see security.limit_extensions)" while reading response header from upstream, client: 192.168.33.1, server: store.localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/tmp/php5-fpm.sock:", host: "192.168.33.14:8005" |
一开始还以为是PHP-FPM配置security.limit_extensions引起的,后来发现这个这个参数默认就是注释掉的,没限制。 最后在这里找到答案:原来是之前安装Nginx时配置了:cgi.fix_pathinfo=0,将它改回1(默认值)就可以了。当这个参数为1时,会把 PATH_TRANSLATED 转换为 SCRIPT_FILENAME。当然把这个参数去掉也是可以的
1 | ;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
重启Nginx
1 | sudo service nginx restart |
与其他PHP框架一样,Phalcon 支持MVC应用开发,提供了诸多组件如,数据库,缓存,队列等。
Phalcon\DI 作为全局的服务管理,用于服务注册,比如数据库,缓存,文件等。将这些资源统一起来管理,以便其他地方可以调用,各个需要的地方不再需要是new 一个对象,解除耦合关系。
Phalcon\Events\Manager作为全局的事件管理,用于事件注册,触发,以便自定义消息通知,如数据库查询事件,初始化事件。
Phalcon还有一个比较有特色的地方支持注释解析: Phalcon\Annotations 。官方教程举例如何使用注释做输出缓存。首先在Dispatcher服务中注册一个监听dispactch事件的缓存插件
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php $di [ 'dispatcher' ] = function () { $eventsManager = new \Phalcon\Events\Manager(); // 添加插件到dispatch事件中 $eventsManager ->attach( 'dispatch' , new CacheEnablerPlugin()); $dispatcher = new \Phalcon\Mvc\Dispatcher(); $dispatcher ->setEventsManager( $eventsManager ); return $dispatcher ; }; |
然后实现监听的缓存插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <?php /** * 为视图启动缓存,如果被执行的action带有@Cache 注释单元。 * */ class CacheEnablerPlugin extends \Phalcon\Mvc\User\Plugin { /** * 这个事件在dispatcher中的每个路由被执行前执行 * */ public function beforeExecuteRoute( $event , $dispatcher ) { // 解析目前访问的控制的方法的注释 $annotations = $this ->annotations->getMethod( $dispatcher ->getActiveController(), $dispatcher ->getActiveMethod() ); // 检查是否方法中带有注释名称‘Cache’的注释单元 if ( $annotations ->has( 'Cache' )) { // 这个方法带有‘Cache’注释单元 $annotation = $annotations ->get( 'Cache' ); // 获取注释单元的‘lifetime’参数 $lifetime = $annotation ->getNamedParameter( 'lifetime' ); $options = array ( 'lifetime' => $lifetime ); // 检查注释单元中是否有用户定义的‘key’参数 if ( $annotation ->hasNamedParameter( 'key' )) { $options [ 'key' ] = $annotation ->getNamedParameter( 'key' ); } // 为当前dispatcher访问的方法开启cache $this ->view->cache( $options ); } } } |
现在就可以使用注释来进行缓存了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?php class NewsController extends \Phalcon\Mvc\Controller { public function indexAction() { } /** * This is a comment * * @Cache(lifetime=86400) */ public function showAllAction() { $this ->view->article = Articles::find(); } /** * This is a comment * * @Cache(key="my-key", lifetime=86400) */ public function showAction( $slug ) { $this ->view->article = Articles::findFirstByTitle( $slug ); } } |
为Action增加了缓存,但对Action的代码改动为0(无侵入)并且非常简洁。数据模型里面也可以使用注释来对字段进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <?php use Phalcon\Mvc\Model; class Robots extends Model { /** * @Primary * @Identity * @Column(type="integer", nullable=false) */ public $id ; /** * @Column(type="string", length=70, nullable=false) */ public $name ; /** * @Column(type="string", length=32, nullable=false) */ public $type ; /** * @Column(type="integer", nullable=false) */ public $year ; } |
路由解析也可以使用RouterAnnotations反射来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | ?php /** * @RoutePrefix("/api/products") */ class ProductsController { /** * @Get("/") */ public function indexAction() { } /** * @Get("/edit/{id:[0-9]+}", name="edit-robot") */ public function editAction( $id ) { } /** * @Route("/save", methods={"POST", "PUT"}, name="save-robot") */ public function saveAction() { } /** * @Route("/delete/{id:[0-9]+}", methods="DELETE", * conversors={id="MyConversors::checkId"}) */ public function deleteAction( $id ) { } public function infoAction( $id ) { } } |
是不是跟Java annotation有点像?之前介绍的PHPUnit,Zend Framework,还有Symfony 2 和 Doctrine 2已经在PHP层面上支持,使用ReflectionClass便可实现。
Phalcon也支持创建命令行应用,可以将PHP应用打包成Phar,直接运行,也可以结合命令行颜色进行输出。
参考链接:
Nginx 安装说明(Nginx Installation Notes)
Can’t upgrade to Phalcon 1.3.0
Nginx/PHP-FPM “Access denied.” error
Access denied (403) for PHP files with Nginx + PHP-FPM
Phalcon 开发工具(Phalcon Developer Tools)
IDE autocomplete for PhalconPHP
Annotations in PHP: They Exist
PHP Annotations Are a Horrible Idea
PHP CLI Colors – PHP Class Command Line Colors (bash)