最近再给一个APP写API,同时还要写相应的后台管理网站。为了便于开发和代码组织与管理,我决定采用一个现有的框架。Codeigniter因为其轻量容易自定制的特色吸引了我,一路开发过来也有大半年时间了,写下一些本身在开发过程当中的一些体会来与你们共勉。php
开发工具备好多,每一个人的习惯也不一样。Eclipse一直是个人最爱,那么怎么让Eclipse支持codeigniter呢?git
首先这是个PHP项目,因此得让Eclipse支持PHP。假设你的计算机已经安装了PHP,那么最简单的作法就是在Eclipse的market space中搜索PDT并安装。具体操做:Help -> Eclipse Marketplace。在输入框中输入PDT,点击find,如图:github
点击右下方的install,等待几分钟便可。web
如今能够在Eclipse中写PHP了,不过对于codeigniter来讲,常常用到的语句相似以下:redis
$this->load->model ( 'user_model' ); $this->input->post ('phone');
每次都要手动输入这么长的相似的语句对于追求高效的人来讲显然是不可取的,因此得让Eclipse支持codeigniter特定的代码提示,包括Controller和Model。把以下代码添加到算法
system/core/ 目录下的Controller文件中CI_Controller类的构造函数以前,这其实就是进行apache
变量声明,Model文件也是一样操做。json
/** @var CI_Config */ var $config; /** @var CI_DB_active_record */ var $db; /** @var CI_Email */ var $email; /** @var CI_Form_validation */ var $form_validation; /** @var CI_Input */ var $input; /** @var CI_Loader */ var $load; /** @var CI_Router */ var $router; /** @var CI_Session */ var $session; /** @var CI_Table */ var $table; /** @var CI_Unit_test */ var $unit; /** @var CI_URI */ var $uri; /** @var CI_Pagination */ var $pagination;
如今效果以下:vim
只需输入$this 便可产生代码提示,效率提升很多。设计模式
通常一个项目中会有许多相同的逻辑,会使用到相同的代码。若是每次都去复制粘贴不只麻烦并且不利于后续修改,想到须要修改一个逻辑就要到每一个文件里修改代码就以为可怕(涉及到设计模式这一块了,值得咱们学学)。因此你要善于利用那些自定义辅助函数(helpers)和自定义的库(libraries)。把相同的逻辑封装成函数或者类,每次遇到相同的逻辑之时只需调用现成的helper或者library便可,修改也只须要在helper或者library中一处修改,不须要处处找代码。
举一个我项目中的例子。API须要给APP发送的请求返回json格式数据,那么在PHP中的一种实现方法就是:
echo json_encode ( $data);//$data 是array类型的数据
可是若是$data中包含中文字符的话,输出的json数据会把中文变成Unicode编码,为了不客户端须要再次处理数据,须要加入一个参数,即:
echo json_encode ( $data , JSON_UNESCAPED_UNICODE);//$data 是array类型的数据
这样就能输出原始的中文了。可是问题又来了,每次都要写这么长一段代码实在是麻烦,因此封装成一个辅助函数。在application/helpers 文件夹中新建一个文件render_helper.php。其中代码以下:
<?php defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' ); /** 打印不转义中文的json @param [array] $data */ function echo_json($data) { echo json_encode ( $data, JSON_UNESCAPED_UNICODE ); }
那么每次调用之时只需先在类中的构造函数载入该辅助函数,以下:
$this->load->helper ( 'render' ); // 载入打印json的自定义辅助函数
就能够在本类的全部成员函数中使用该方法:
echo_json ( $data);
这样省时省力(加上Eclipse的代码提示,你只须要输入echo,这个函数就能够出来了)。之后须要修改为编码后中文,或者转换成英文等等(奇怪的需求~)你均可以只修改一行代码,效率提升很多。
若是一个APP的活跃用户不是不少,那么传统的LAMP架构就能够应付了。可是随着用户的逐渐增多,要想提升并发量,最好仍是加一个缓存。在memcached和redis中,我选择了redis,主要由于它数据类型更丰富(不只支持key-value型的数据,同时还提供list,set,zset,hash等数据结构的存储),能帮你实现一部分逻辑(避免重复造轮子)。与Eclipse配置同理,首先得让计算机上的PHP可以和redis通信(假设你的计算机已经安装了redis),那么首选的是phpredis扩展,这里介绍一下我在Debain服务器上的配置过程,执行的命令以下:
wget https://github.com/nicolasff/phpredis/archive/master.tar.gz #下载扩展 tar xvf master.tar.gz #解压目录 cd phpredis-master/ #进入解压后的目录 phpize ./configure --enable-redis make && make install #安装 #可是报错-bash: phpize: command not found(在使用apt-get install php5安装php时,默认是没有安装phpize的,咱们安装phpredis时,须要用到phpize,所以,须要先安装#phpize。咱们经过安装php开发者工具来获取phpize。执行以下命令便可: apt-get install php5-dev) ls /usr/lib/php5/20100525/#根据安装提示的文件,结果:curl.so gd.so redis.so vim /etc/php5/apache2/php.ini #打开PHP配置文件 # Dynamic Extensions 后面添加extension=redis.so,由于上面命令结果显示有redis.so /etc/init.d/apache2 restart #重启Apache服务器
如今PHP就能和redis通信了,测试以下:
<?php $redis = new Redis(); $redis->connect('127.0.0.1',6379); $redis->auth('你的密码');//为了安全,要给redis设置密码 $redis->set('tom','hanks'); echo ' tom:'.$redis->get('tom'). '</br>';// tom:hanks echo 'will:'.$redis->get('will'); //will: ?>
好了,如今来到配置codeigniter使其可以使用redis的步骤了。Codeigniter3.0.0自己具备redis支持,可是它实现的功能过于单一,不可以知足个人业务需求,因此必需要修改。可是最好不要直接在/system/libraries/Cache/drivers/Cache_redis.php 中修改,由于之后codeigniter升级采用直接覆盖system文件夹的形式,会覆盖掉你的代码。因此最明智的作法仍是本身建立一个库,具体步骤以下:
一、在application/config/redis.php 中加入配置信息:
<?php defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' ); $config ['socket_type'] = 'tcp'; config ['host'] = '你的服务器域名或者IP'; $config ['password'] = '你的redis密码'; $config ['port'] = 6379; $config ['timeout'] = 0;
二、在application/libraries中创建以下图的文件结构
Rediscli.php 代码以下:
<?php defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' ); class Rediscli extends CI_Driver_Library { public $valid_drivers; public $CI; function __construct() { $this->CI = & get_instance (); $this->valid_drivers = array ( 'default' ); } }
Rediscli_default.php 代码从/system/libraries/Cache/drivers/Cache_redis.php 直接拷贝过来,惟一的不一样是把类名从CI_Cache_redis改成Rediscli_default,这样就能按照官方的使用方法使用咱们本身写的库。
三、如今能够在Rediscli_default.php中添加或者修改方法,具体操做取决于你本身的应用的需求。好比在个人应用中,须要保持一个必定长度的队列,因此在Rediscli_default类中添加以下两个方法:
/** 弹出链表头元素 @param unknown $key,链表名 */ public function lpop($key) { return $this->_redis->lPop ( $key ); } /** 插入元素到表尾 @param unknown $key,链表名 @param unknown $value,待插入值 */ public function rpush($key, $value) { return $this->_redis->rPush ( $key, $value ); }
某个类须要调用该库时只需在其构造函数中添加以下代码:
$this->load->driver ( 'rediscli' ); // 加载redis自定义库 $this->rediscli->default->is_supported ();//判断是否支持redis并打开链接
则该类的每一个函数就均可以使用Rediscli_default类中的任一方法,示例以下:
$this->rediscli->default->lpop('delnews');//弹出名为delnews的链表头元素 $this->rediscli->default->rpush('delnews',$nid);//该链表加入尾元素$nid
对于咱们的APP来讲,每一个请求都要判断用户是否已登录,对于登录的合法用户正常显示请求,对于未登陆的用户提示“请先登陆”。通常的web应用采用cookie-session机制,通常的session都是以文件形式保存在服务器上,考虑到文件访问慢于内存访问,咱们能够配置codeigniter的session保存于redis中。我这里模仿这种机制:用户正常login后返回一个特定的id和特定的token(你能够自定义产生算法),服务器以id为key、token为value直接保存在redis中。之后的每次访问APP都必须带上用appsecret(预约义)加密后的参数id和token,服务器端校验成功即正常返回数据,不然提示“请先登陆”。
那么是否每一个类都须要写一遍检查登录的代码呢?固然不能这么干,咱们能够自定义一个基类,在该基类的构造函数中检查登录状态(还能够在这里加载经常使用的辅助函数和库,好比上面的render_helper 和 rediscli)。而后其余的业务逻辑的类就继承该基类,并完成其自身逻辑便可。
具体操做就是在 application/core 中新建文件 MY_Controller.php,该文件对应MY_Controller类(继承CI_Controller类)。该类只须要一个构造函数完成上述功能便可。
而后其它逻辑类只需继承MY_Controller类就没必要再次校验登录状态,而只需完成自身逻辑。
Codeigniter是我最喜欢的一个PHP框架(相比于thinkPHP,Zend Framework等等),主要在于其易安装,轻量,易自定制的优势。把握好这些优势,咱们就能写出不逊于那些重量级框架写出来的应用,而且省时省力。
做为一个学生,在摸索学习的路上还有不少问题须要解决,本文的目的在于和你们分享,更重要的是你们有什么建议或者批评请必定不吝赐教哈