Phalcon是一个C语言写的高性能PHP框架,相比PHP写的框架,它作为PHP的扩展在进程开启时便加载了,节省了每一次请求时的类库加载、MVC框架分派的开销。前面提到的使用Zephir来开发PHP扩展也是这个项目贡献的。
在CentOS 上安装Phalcon,因为之前安装过zephire了,所以直接下载cphalcon来编译安装就可以了,可以参照这里安装所需其他lib
git clone --depth=1 git://github.com/phalcon/cphalcon.git cd cphalcon/build/ sudo ./install sudo vim /etc/php.d/phalcon.ini
创建phalcon.ini增加以下内容
[phalcon] extension=phalcon.so
这里单独把phalcon.ini单独配置,是因为Phalcon扩展加载要在PDO扩展之后,而我的PDO也是单独配置的。如果不是的话会提示这个错误:
$ 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也提供开发工具用于快速生成项目骨架
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扩展的,否则会提示
$ 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
phalcon scaffold store
按照官方的Nginx说明配置
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错误日志
[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。当然把这个参数去掉也是可以的
;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
重启Nginx
sudo service nginx restart
与其他PHP框架一样,Phalcon 支持MVC应用开发,提供了诸多组件如,数据库,缓存,队列等。
Phalcon\DI 作为全局的服务管理,用于服务注册,比如数据库,缓存,文件等。将这些资源统一起来管理,以便其他地方可以调用,各个需要的地方不再需要是new 一个对象,解除耦合关系。
Phalcon\Events\Manager作为全局的事件管理,用于事件注册,触发,以便自定义消息通知,如数据库查询事件,初始化事件。
Phalcon还有一个比较有特色的地方支持注释解析: Phalcon\Annotations 。官方教程举例如何使用注释做输出缓存。首先在Dispatcher服务中注册一个监听dispactch事件的缓存插件
<?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; };
然后实现监听的缓存插件
<?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); } } }
现在就可以使用注释来进行缓存了
<?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(无侵入)并且非常简洁。数据模型里面也可以使用注释来对字段进行处理
<?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反射来实现
?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)