Tag: CI

CI配置smarty

10条评论

2011 年 07 月 12 日 at 上午 8:55分类:PHP

1、到相应站点下载Smarty的源码包;
2、将源码包里面的libs文件夹copy到CI的项目目录下面的libraries文件夹下,并重命名为Smarty;
3、在项目目录的libraries文件夹内新建文件Cismarty.php,里面的内容如下:

<?php
if(!defined('BASEPATH')) EXIT('No direct script asscess allowed');

require_once( APPPATH . 'libraries/Smarty/Smarty.class.php' );

class Cismarty extends Smarty {

	protected $ci;

	public function  __construct(){
				
		$this->ci = & get_instance();

		$this->ci->load->config('smarty');//加载smarty的配置文件
		
		//获取相关的配置项
		$this->template_dir   = $this->ci->config->item('template_dir');
		$this->complie_dir    = $this->ci->config->item('compile_dir');
		$this->cache_dir      = $this->ci->config->item('cache_dir');
		$this->config_dir     = $this->ci->config->item('config_dir');
		$this->template_ext   = $this->ci->config->item('template_ext');
		$this->caching        = $this->ci->config->item('caching');
		$this->cache_lifetime = $this->ci->config->item('lefttime');
	}
	
}

4、在项目目录的config文件夹内新建文件smarty.php文件,里面的内容如下:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$config['theme']        = 'default';
$config['template_dir'] = APPPATH . 'views';
$config['compile_dir']  = FCPATH . 'templates_c';
$config['cache_dir']    = FCPATH . 'cache';
$config['config_dir']   = FCPATH . 'configs';
$config['template_ext'] = '.html';
$config['caching']      = false;
$config['lefttime']     = 60;

5、在入口文件所在目录新建文件夹templates_c、cache、configs;

6、在项目目录下面的config目录中找到autoload.php文件
修改这项

:$autoload['libraries'] = array('Cismarty');//目的是:让系统运行时,自动加载,不用认为的在控制器中手动加载

7、在项目目录的core文件夹中新建文件MY_Controller.php 内容如下:

<?php if (!defined('BASEPATH')) exit('No direct access allowed.');

class Controller extends CI_Controller {	
    
	public function __construct() {
		
		parent::__construct();		
	    
    }

	public function assign($key,$val) {
		$this->cismarty->assign($key,$val);
	}


	public function display($html) {
		$this->cismarty->display($html);
	}
}

//================================================================
配置完毕
//================================================================
使用方法:
在控制器中如:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Welcome extends Controller {

	public function __construct(){
    	parent::__construct();	
    }

	public function index()
	{ 
		$data['title'] = '测试';
		$data['test'] = '123456789';
		$this->assign('test',$data);
		$this->assign('tmp','hello');
		$this->display('test.html');
	}
}

然后再视图中:试图文件夹位于项目目录的views之下:
新建文件test.html

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>{$test['title']}</title>

<style type="text/css">
</style>
</head>
<body>

{$test['test']|md5}
<br>
{$tmp}
123

</body>
</html>

CI路由剖析

没有评论

2011 年 07 月 10 日 at 下午 4:59分类:PHP | WEB开发

CI 的路由功能是在CodeIninter.PHP文件中开始执行的。
1:在核心文件CodeIninter.php中,加载完路由操作类Router之后,立刻就执行了$RTR->_set_routing();该方法主要的功能是:
a:在初始化路由类的时候加载了配置类Config,和URI操作类两个文件
b:首先判断是否开启了:enable_query_strings,如果是,那么执行以下:
(1):通过用$_GET['c']和$_GET['m']来获取当前的类和方法,并放到数组$segments中。
c:加载APPPATH/config/routes.php(路由配置文件),放到$this->routes中,然后释放routes.php中的$routes
d:获取默认的Controller($this->default_controller),转换成首字母大写
e:判断$segments数组是否为空(该变量的数据来源于可能的b步骤),如果执行了b步骤,显然不会为空,会调用方法$this->_validate_request($segments)来处理
f:方法_validate_request()的主要功能是:判断$segments中指定的控制器文件是否存在,存在,返回,不存在,判断是否存在子层目录,如果存在,进行相关处理。
g:调用URI中_fetch_uri_string方法:通过各种方法获取URI的内容(首先考虑的是 REQUEST_URI),将处理后的URI放到$this->uri_string中
h:判断$this->uri_string是否为空,若是:调用_set_default_controller();
1:设置默认的控制器,我们在路由配置文件中可以这么写:$route['default_controller'] = “Home/test”;,那么解析后,控制器为home,方法为test
2:然后调用方法_set_request():功能是先调用_validate_request(),判断控制器和方法是否存在,然后就是设置Router中class和method属性的值。
i:判断是否存在URL的后缀,如果有那么就调用URI中的_remove_url_suffix()方法来处理,
j:调用URI中的方法:_explode_segments()来将处理后的URI字符串转换成数组的形式存放到$this->segments[]数组中。
k:调用Router中的方法_parse_routes来解析用户自定义的路由。
1:该方法主要是判断用户是否自定义了路由,然后根据当前的URI信息来匹配用户自定义的路由,如果匹配上了的话,就调用_set_request()来设置当前操作类和方法,以实现路由的功能。代码:

                              //将URI参数数组用/重新组合
$uri = implode('/', $this->uri->segments);

// 判断当前的uri是否已被路由定义,
if (isset($this->routes[$uri]))
{
                      //直接设置路由中的类和方法还有参数
	return $this->_set_request(explode('/', $this->routes[$uri]));
}

// 遍历自定义的路由信息,以寻找和当前uri相匹配的数据
foreach ($this->routes as $key => $val)
{
	// 替换CI自定义的规则为正则
	$key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));

	// 执行当期uri和路由匹配
	if (preg_match('#^'.$key.'$#', $uri))
	{
		// $route['category/(:any)'] = 'home/category/$1';
		if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
		{
			$val = preg_replace('#^'.$key.'$#', $val, $uri);
		}
                              //直接设置路由中的类和方法还有参数
		return $this->_set_request(explode('/', $val));
	}
}
              //设置默认的路由信息
$this->_set_request($this->uri->segments);

l:最后调用函数$this->uri->_reindex_segments();来重置索引,确保数组$segments是从1开始的。
//=======================================================================================================
上面的操作都是在CI核心文件CodeIninter.php调用$RTR->_set_routing()方法所执行的操作
简单的概括就是:
通过URI类和Router类的操作来获取当前控制器和操作方法,如果不存在,那么就调用默认的控制器方法,然后结合用户自定义的路由信息。将当前要操作的控制器和方法存起来,然后我们通过方法$class = $RTR->fetch_class();$method = $RTR->fetch_method();就可以获取要操作的对象了另外,还将URI中其他的参数放到URI类的变量$this->segments[]中,我们只要从这个变量当中取就OK了
所以CI只要这样子call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));就可以驱动我们自己写代码和获取参数了。
那么整个项目也就跑起来了。
//================================================================================
PS:
CI提供了一个临时路由的方法:我们在CodeIninter.PHP文件中看到这么一行:

if (isset($routing))
{
	$RTR->_set_overrides($routing);
}

如果我们index.php文件中有设置这样子一个数组:

$routing['directory'] = '';//设置子控制器目录,一般为空
$routing['controller'] = 'Home';//控制器
$routing['function'] = ''; //方法

那么之前所有的路由解析将是作废的,系统会按照这个$routing数组定义的控制器和方法来运行你的程序。

CI执行过程剖析

没有评论

2011 年 07 月 09 日 at 下午 11:22分类:PHP

1、CI 中index.php文件的主要功能是:定义项目的相关路径常量,最后,加载CodeIninter.php文件,后面的事情交给他处理

2、在CodeIninter.php文件中,主要功能有:
a:加载CI核心的公共文件Common.php,内置的方法在系统全局中都会被用到,特别是:&load_class(),is_loaded(),&get_config(),config_item()函数,
b:加载文件读写属性的配置文件:constants.php
c:利用函数&load_class()加载获取某一段程序执行时间的类文件:Benchmark.php
d:利用函数&load_class()加载钩子类:Hooks.php
1:初始化时,加载了配置类Config,获取项目目录下config.php文件的配置项
2:判断在配置文件中是否开启了钩子,然后加载项目下面config/hooks.php钩子的配置文件
e:利用上一步实例化的钩子对象,来执行一个在系统执行之前执行的钩子”pre_system”,这个钩子的内容需要用户自己在hooks.php文件中配置,若不存在就不执行
f:用&load_class()加载配置类Config,做的工作是判断是否存在需要存入配置文件的变量,如果有,就存入,否则,不执行。
g:用&load_class()加载UTF8类,这个类主要是处理项目的编码的一些事情,比较简单。
h:用&load_class()加载URI类,主要是处理URI的,方便我们在项目中直接调用。
i:加载路由类Router,然后执行_set_routing()来设置路由。
j:加载输出类:Output
k:运行钩子:$EXT->_call_hook(‘cache_override’)
l:加载安全类:Security,主要是对数据进行消毒的。
m:加载输入类Input,设置获取get.post.cookie.server变量的函数,然后可以对他们进行消毒
n:加载语言类:Lang
o:加载核心控制器Controller类,通过引用方式(&)返回核心控制器的对象。
p:判断在项目的核心目录下面是否存在MY_Controller的拓展控制器,如果有,那就require_once();
q:根据路由类(Router)获取到的控制器($RTR->fetch_class()),来加载controlers下面的该控制器
///////////////////////////////////////////////////////////////////////////////////////////
到上面为止呢,系统当前执行的加载已经完毕了,既然刚刚加载我们项目的控制器,那么接下来就应该调用我们项目的控制器了
继续:
//////////////////////////////////////////////////////////////////////////////////////////
a:通过路由类来获取当前需要执行的控制器($RTR->fetch_class())和方法($RTR->fetch_method()),然后判断类和方法的合法性
b:运行钩子:$EXT->_call_hook(‘pre_controller’),在调用你的任何控制器之前调用
c:实例化项目当前路由捕获到的类,
d:运行钩子:$EXT->_call_hook(‘post_controller_constructor’);控制器实例化之后,任何方法调用之前调用.
e:判断当前的控制器中是否存在方法:_remap();,如果存在,那就直接调用该方法。否则,调用由路由捕获的方法;
f:运行钩子$EXT->_call_hook(‘post_controller’) 控制器完全运行之后调用.
g:运行钩子$EXT->_call_hook(‘post_system’);在最终着色页面发送到浏览器之后,浏览器接收完最终数据的系统执行末尾调用
h:判断是否打开数据库连接,关闭数据库连接。
//////////////////////////////////////////////////////////////////////////////
这样子,我们一个项目就运行完了。(PS:这个当然很多更加深入的就没有进行下去了,比如说路由是怎么实现的等。下次更新。。。)

架构分析查看:http://www.360doc.com/content/11/0320/21/6524307_102997671.shtml

CI中DB对象剖析

没有评论

2011 年 07 月 08 日 at 下午 5:01分类:MySQL

CI中使用DB类,只要你在你的控制器中使用了这句话:$this->load->database();那么你就可以在你的控制器中的任何地方或者是在模型的任何地方都可以使用$this->db->function()来操作数据库了。那么CI 是怎么样做到这一步的呢?下面一一道来:
首先,我做过测试,在$this->load->database()这句话之前你要是打印$this->db的话,是没有任何数据的,但是在这句话之后打印的话,那么会出现很多对象属性啊方法等信息。那么首先来看下Loader.php文件中的database方法:
该方法的主要功能有:1、通过get_instance()来获得一个CI对象,2、加载数据库初始化类文件database/DB.php,将初始化后的对象放置到$CI->db中,这样子,整个CI对象中就有了db对象了。在任何一个能获取CI对象的地方都可以使用db对象了。那么问题是:这个db对象到底是怎么了的呢?继续往下:
看下文件DB.php文件,里面就只有一个方法DB。这个方法的主要功能有:
1、加载config文件夹下面的数据库配置文件:config/database.php
2、判断当前选择的数据库,默认为$active_group = ‘default’
3、加载数据库驱动类文件/database/DB_driver.php
4、判断是否启动了Active Record 模式,如果是,那么就加载database/DB_active_rev.php文件,否则,不加载
5、判断类CI_DB是否存在,如果不存在,那么在AR模式下:class CI_DB extends CI_DB_active_record{};否则class CI_DB extends CI_DB_driver{}
6、加载指定数据库的驱动文件 如mysql的是:database/driver/mysql_driver.php
7、实例化database/driver/mysql_driver.php文件中类CI_DB_mysql_driver,这个实例化出来的对象就是我们平时用到的对象了。

类CI_DB_mysql_driver继承了CI_DB类,,然后CI_DB类 继承了CI_DB_active_record类,CI_DB_active_record类继承了CI_DB_driver类,
类CI_DB_driver是数据库的基类,
上面的继承都是在AR模式下面的
如果没有开启AR模式,那么继承方式是一样的;如下:
类CI_DB_mysql_driver继承了CI_DB类,,然后CI_DB类直接继承了CI_DB_driver类。
整个数据库的流程大致就是这样子。
//PS:
为什么我们在控制器和模型中都可以使用$this->db来操作数据库对象呢?
刚刚上面我们说了在控制器中的使用原理,那么在模型中为什么可以使用呢?
其实模型中的$this->db是完全靠控制器中的对象来实现的,主要是:
1、通过get_instance()来获取CI对象,
2、通过__get方法来获取db这个私有属性的值

function __get($key){
      return $CI->$key;
}

ci的HMVC

没有评论

2010 年 12 月 13 日 at 下午 10:51分类:PHP | WEB开发

HMVCHierarchical-Model-View-Controller),也可以叫做 Layered MVC。故名思意,就是按等级划分的 MVC 模式,简单的解释就是把MVC又细分成了多个子 MVC,每个模块就分成一个 MVC。

使用 HMVC 的好处就是可以降低各个功能模块之间的耦合性,提高代码复用性,使得每个功能都可以独立出来,每个模块都有自己的 MVC 结构,这就有点像 ActiveX 控件,每个控件都有自己的行为,控件之间互不影响。

CodeIgniter 结构示意

application
 	|- controllers
 		|- controllers1.php
 		|- controllers2.php
 		|- ...
 	|- models
 		|- models1.php
 		|- models2.php
 		|- ...
 	|- views
 		|- views1
 			|- index.php
 			|- footer.php
 			|- ...
 		|- views2
 			|- index.php
 			|- footer.php
 			|- ...
 		|- ...
上面的就是 CodeIgniter 原来的结构,如果是 HMVC 的话结构就是:
application
 	|- modules
 		|- modules1
 			|- controllers
 				|- controllers.phpCI
 			|- models
 				|- models.php
 			|- views
 				|- index.php
 				|- footer.php
 				|- ...
 		|- modules2
 			|- controllers
 				|- controllers.php
 			|- models
 				|- models.php
 			|- views
 				|- index.php
 				|- footer.php
 				|- ...
 		|- ....
 	|- controllers
 		|- ...
 	|- models
 		|- ...
 	|- views
 		|- ...
请注意,以上只是 CodeIgniter 框架的 HMVC 文件夹结构的一种表现形式,不代表 HMVC 必须以这个结构为准,需要根据不同语言或框架来设计其 HMVC 结构。

CI学习总结

没有评论

2010 年 12 月 10 日 at 下午 10:57分类:PHP | WEB开发

CI学习总结
1、什么是框架?
框架就是一个没写完的网站,提供了一些基础的功能,比如安全检查,表单难,数据库连接等。其它人可以在上面开发自己的东西。框架把一些烦琐重复而没有创造性的工作帮你做好,而让你从事具有创造性的工作。不过使用框架对执行速度有影响。
2、什么是CodeIgniter?
CodeIgniter是一个小巧的php框架,名称由两个单词组成,code代码Igniter点火器,连起来意思是代码点火器(什么意思?),简称CI
3、Application文件夹可以移动么?
可以移动或改名,修改后需要在index.php里把$application_folder = “application”;这句修改成相应的路径和名称。但是application下的controllers、models、views不能动。
4、什么是MVC?
复杂的不说了,人们都在讲这个,简单点儿几句话:m跟数据打交道,V跟界面打交道,C把M和V连起来,把从M取到的数据交给V显示。
5、CI中怎么连接数据库?
在application/config/database.php里面修改连接参数,然后在需要连接数据库的时候载入数据库就可以了。

$this->load->database();

6、如何取得post数据?
可以使用传统的php方法,

$_POST['name']
或者$this->input->post('name');

7、CI可以使用$_GET么?
不可以,如要实现类似功能,参考下面一问。
8、如何得到URL地址中的参数?
第一种办法:$this->uri->segment(n),n 为你想要得到的段数,具体可以查手册。
第二种办法:假设URL是这样:http://example.com/index.php/blog/list/3/myname
在blog的list方法可以这样写:

function list($id,$name)
{
//$id=3
//$name=myname
}

$id和$name得到链接中的参数,如果参数个数不一样会提示404错误。
9、VIEW怎么相互引用?
view也是php文件,可以直接include,也可以在view里使用load:

$this->load->view('View_name');

这个以实现VIew共用,分享网页头和尾。
10、View里怎么调用CSS和JS?
在VIEW头部这么写:

<link href='<?= base_url();?>css/tabs.css' rel='stylesheet' type='text/css' />
<script type='text/javascript' src='<?= base_url();?>js/jquery.js'></script>

base_url是网站根目录地址。
11、可以给一个view传递多个参数吗?
只能传递一个数组或对象参数,但是数组或对象可以想多复杂就多复杂。
12、controllers下可以建子目录吗?
可以,但只能建一级子目录
13、Controller是否可以互相调用?
不可以,可以用以下方法替代解决:
1.代码写到model里,调用model。
2.代码写到其他类里,比如库、插件、helper等。
3.扩展Controller,代码写到My_Controller里,继承。(sinopf in codeigniter.org.cn)
我的学习方法
第一天看手册
第二天逛CI论坛,搜索一些关键词,比如:VIEW 数据 安全 登录 验证等。
一方面回顾手册里的知识,另一方面,了解大家以前遇到过的问题及解决办法,避免以后走弯路。
比如我搜索到CI自带的SESSION不好用,我以后就不会在SESSION这个问题上折腾了,直接使用kndb session第三方类库。
第三天,看codeigniter.org.cn里的视频,照着做一个blog。
接下来,看源码,下载一个使用CI的开源系统看看,然后动手自己写。

CI入门 : 一些建议和最佳实践

没有评论

2010 年 12 月 04 日 at 下午 3:20分类:PHP | WEB开发

原文地址 http://codeigniter.com/forums/viewthread/125687/
1、 使用哪一个版本? 1.7.2 or 2.0
CodeIgniter 2.0 目前虽然还没有最终发布,但它已经非常稳定,并且 EllisLab 公司已经声明不会有很大的变动,只要是修正一些 BUG,许多人认为 2.0 比 1.7.2 更加稳定,Phil Sturgeon 在他的博客中写过一篇非常棒的关于怎样从旧版本升级到 2.0 版本的文章,你可以从 BitBucket.org 下载最新的 CI 2.0 的代码,以及最近的升级。
Moderator Jamie Rumbelow 曾写了一篇关于CI 2.0 的帖子。

2 、阅读手册 & 观看视频
了解 CI 的最好的方法是阅读它的手册,里面有很多值得参考的文章,特别是那些高亮的部分,你一定要阅读它们并引起注意。
也可以通过观看 nuttuts+ 上面的视频或 CI网站 上的视频来学习 CI ,后者采用了一个旧的版本,如果你注意了,它仍是一个很好的了解 CI 使用的地方。

3 、MVC 编程
如果你还不知道 MVC ,应该尽快的学习,你会很快的体会到在 Model 中数据访问,在 Controller 中进行业务逻辑,在 Views 中编写 HTML 代码的价值。如果你之前没有使用过这种模式写过程序,你也许会皱起额头,不过你应该给自己尝试这样做的机会。
一条实践准则是把更少的东西放进 Controller ,记住 DRY 准则:不要重复造轮子。当在超过一个地方编写相同的代码时,应该根据它的类型来尝试编写一个 library , helper,或 model 。
一旦领悟了 MVC 的精髓,这将会成为一种习惯,你会从 MVC 简洁的代码中受益良多。

4 、错误报告 和 调试
常常犯的一个错误是忘记关闭 PHP 错误和数据库错误报告,这样做是有风险的。在任何一个公开的站点,error_reporting 应该设置为0 ,最多只能设置为 E_ERROR,数据库设置 db_debug 应该设置为 false,基于其他安全考虑,设置不显示出错信息 ini_set(‘display_errors’, ‘Off’);
在你编码和调试时,应该把 error_reporting 设置为 E_ALL ,并且在把应用程序发布前解决每一个注意和警告。
一种简易的方法是在 application/config/database.php 文件设置 db_debug 的值为一个常量 MP_DB_DEBUG,当网站在运行中,如下设置:

ini_set('display_errors', 'Off');
error_reporting(0);
define('MP_DB_DEBUG', false);

在编码和调试中设置为:

ini_set('display_errors', 'On');
error_reporting(E_ALL);
define('MP_DB_DEBUG', true);

5、 Application 和 System 路径
最好是把 system 和 application 文件夹放在 webroot 以外的地方,如果 index.php 放在 FTP 服务器的 /public_html/ 路径下,应该尝试把 System 放在根目录下 /system ,这样的话,只能通过 index.php 访问你的PHP文件。
不要忘记在index.php文件中修改 $system_folder 和 $application_folder 的值,$system_folder 的值应该是相对于 index.php 文件,而 $application_folder 的值是相对于 system 目录。

6 、安全
关于SQL注入,XSS,以及 CSRF ,你应该先了解它们,再决定是否采用方法来防止它们。可以参考CI手册上的安全指南 以及 输入和安全类。也许最重要的原则是在把数据提交到数据库或文件系统之前检查所有用户的输入。
(1) SQL注入
使用 CI 自带的 Active Record 可以解决这个问题。
(2) XSS (跨站脚本)
通过设置 $config['global_xss_filtering'] = TRUE; 开启自动过滤POST和COOKIE中的跨站脚本攻击,但需要消耗一些资源。
也可以在每次处理POST和COOKIE的时候单独使用,把第二个参数设为TRUE,如 $this->input->post(‘some_data’, TRUE);
表单验证类也提供了 XSS 过滤选项,如 $this->form_validation->set_rules(‘username’, ‘Username’, ‘trim|required|xss_clean’);
(3) CSRF (跨站请求伪造)
CI 2.0 将内置 CSRF 检查,在 Google 上搜索 “CSRF tokens” 学习更多关于在保护表单提交和 URL 链接的知识,在 Ajax 应用方面可以搜索 “double cookie submission” 或 “双提交 cookie”。
(4) SPAM (垃圾留言和恶意注册)
通过保护你的邮件表单,评论表单,以及其他各种免费用户提交的数据来防止垃圾信息,一个简单的方法是只允许一个IP/User客户端在一分钟之内只能提交一次,
最好的方式是使用 Captcha ,比如 reCAPTCHA 来保护邮件表单和评论表单,可以在论坛上搜索怎样在CI中集成 reCAPTCHA 。CI2中内置了一个CAPTCHA的辅助函数。

7 、实践
编写简洁的代码,并且理解你的代码,不要只是复制粘贴别人的代码,并且不断提高编码能力。手册上的开发规范是一个能学习怎样更好编写代码的地方。
(1) DRY
不要总是重复造轮子,把能重用的代码放在它应该在的地方,比如libraries, helpers 或者是 models,而不是controllers,一个经验准则:当你复制代码的时候,也许你已经第二次把它放在了错误的地方。
(2) Caching (缓存)
缓存是一个提高性能的很好的方式,尤其是减少数据库的访问。可以参考网页缓存和数据库缓存,或者在论坛上搜索其他的可选方案,比如 MP_Cache 是作者自己的作品。
(3) HTTP headers (HTTP头部)
在客户端你能够通过单独发送HTTP头部使浏览器缓存页面来提高性能,当你使用 AJAX 的时候你也需要了解它来禁止浏览器缓存。
一个禁止缓存的例子:

$this->output->set_header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
$this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate");
$this->output->set_header("Cache-Control: post-check=0, pre-check=0", false);
$this->output->set_header("Pragma: no-cache");

一个长时间保持缓存的例子(比如 css, javascript)

$this->output->set_header('Cache-Control: private, pre-check=0, post-check=0, max-age=2592000');
$this->output->set_header('Expires: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() + 2592000));
$this->output->set_header('Last-Modified: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() - 20));

8 、访问数据库 和 ORM
CodeIgniter 有一个自带的库 Active Record 能够帮助你在不使用 SQL 语句的情况下写查询语句。这在你不太精通 SQL 语句或不知道怎样防止SQL注入的情况下是一个很好的方法。
当你需要更强大的工具时,你可以考虑使用 Object Relational Mapper ,就是鼎鼎大名的 ORM 了,遗憾的是,CodeIgniter 没有自带 ORM 库,不过也有一些其他很好的选择。
最流行的或许是 DataMapper OverZealous Edition (DMZ),还可以使用 Doctrine (这里有一个教程),另一个选择 RapidDataMapper 是作者自己的作品。

9 、使用用户验证 和 授权
CodeIgniter没有自带用户验证的库引起很大争论,因为很多用户认为应该包含,也有很多人持反对意见。我的意见是在论坛或 wiki 上搜索一个仍在维护的库,它应该有好的安全性并且能方便的应用到你的程序里。你也可以研究这些例子并且写一个自己的验证库。
这里推荐的一个验证库是 Ion Auth ,它的程序写得很好,也许会比你第一次尝试写的更出色,如果你打算自己写验证库的话,你可以阅读它的代码并获得一些灵感。

10 、其他
遇到问题,可以在CodeIgniter的 论坛 和 wiki 上搜索,如果没有解决的话,可以在论坛上提问。

CI内部问题(BUG)

没有评论

2010 年 12 月 03 日 at 下午 5:38分类:PHP | WEB开发

今天在弄CI 的表情符的时候发现两个问题:
问题一:当我们把所有的表情符弄好了,然后建立相应的控制器,并在控制器中添加相应的代码之后,运行之后,显示出了相应的表情图片。但是
当我们点击相应的表情符的时候,确出报一个JS变量未定义的错误信息,找了半天,在表情的辅助函数里面有个函数smiley_js(),这是函数里面有个部分有点问题;下面是该函数的部分代码:

$r .= <<<EOF
			
				var smiley_map = {$m};

				function insert_smiley(smiley, field_id) {
					var el = document.getElementById(field_id), newStart;
				
					if ( ! el && smiley_map[field_id]) {
						el = document.getElementById(smiley_map[field_id]);
					
						if ( ! el)
							return false;
					}
				
					el.focus();
					smiley = " " + smiley;

					if ('selectionStart' in el) {
						newStart = el.selectionStart + smiley.length;

						el.value = el.value.substr(0, el.selectionStart) +
										smiley +
										el.value.substr(el.selectionEnd, el.value.length);
						el.setSelectionRange(newStart, newStart);
					}
					else if (document.selection) {
						document.selection.createRange().text = smiley;     //这里原先是text,是不对的,改成smiley
					}
				}
EOF;

问题已经在注释里面说明了!这是问题之一
其次,在显示的所有表情图片中,有一个表情符号显示不出来,找了下问题所在,找到了相关的图片和在ocnfig/smileys.php文件中定义的代码,发现有点不一样,下面是没有显示图片对应的代码:

':P'			=>	array('raspberry.gif',		'19',	'19',	'raspberry'),

这里定义的图片名称是:raspberry.gif,而在表情包里面却没有这个图片只有一个rasberry.gif图片,由此看来这肯定是写的时候出错了!解决办法:
将表情里面的图片rasberry.gif名字改成raspberry.gif。这样子,图片就能全部显示出来了!

CI中验证码的使用

一条评论

2010 年 12 月 02 日 at 下午 3:57分类:PHP | WEB开发

    今天在做项目的时候要用到一个验证码程序!从CI的手册上看了下,找不到很好的资料,在CI 的论坛上找了几个 但是运行起来都是有点问题的!有些是不能显示的,有些是报错的!都是人家写的代码,不知道如何入手去修改那些错误的地方!还有些就是能够显示的,但是效果不是我想要的!在之前学习TP的时候 感觉TP的验证码做的不错!而且效果蛮不错的!最主要的是功能还是蛮强大的!支持中英文和各种样式的验证码生成!于是扔掉了从论坛上DOWN下来的所有验证码程序,自己把TP的整个验证码程序移植过来了!整合了一下,把所有的代码写在了一个类文件(Image.php)中,当然在移植的过程中修改了不少的东西,但是主要的效果和原理还是不变!主要是为了能够适应CI的环境!
    首先在Image.php文件中主要的有两个函数,其中的buildImageVerify()函数使用来生成英文 和数字的验证码的。还有一个函数buildGbVerify()是用来生成中文的验证码的!不用管这两个函数是怎么运行的!我们只要把这个文件(Image.php)放在我们项目或者是系统libraries文件夹中,然后在我们的控制器中调用就可以了!如:

               //验证码的实现1
		public function authCode () {  
			$this->load->plugin('captcha');
			$cap = create_captcha(array(        
				'img_width'	 => 80,
				'img_height' => 25,
				'word_length' => 5
			));  
		}
		//验证码实现2
		public function auth()
		{
			$type = isset($_GET['type'])?$_GET['type']:'gif';
			$this->load->library('image');
			Image::buildImageVerify(4,1,$type);    //输出英文,数字验证码
			Image::buildGbVerify(4,$type,'120','50','system\fonts\simhei.ttf');    //输出汉字验证码
			//echo $thid->session->userdata('check');       //输出验证码中的字符串
		}

首先第一个是采用的系统自带的验证码,不过样式不怎么好看,我个人感觉哈,所以就PASS了,
第二个是自己整理的出来的。首先得加载验证码的类文件,然后分别调用不同的方法 ,来显示不同样式的验证码!
其中要说名一点是,在调用汉字的验证码是,必须要指定字体的路径,相对index.php文件来说的。(我试了很多字体 好像只有这个字体可以正常显示啊!)
我们要想在视图中调用的话,直接这样子写:

<body>
<SCRIPT>
	function freshcheck () {		//重载验证码
		var timenow = new Date().getTime();
		document.getElementById("checkimg").src="<?php echo base_url().'index/auth/';?>"+timenow;
	}
</SCRIPT>
<img id="checkimg" src=<?php echo site_url('index/auth');?> align="middle" title="点击刷新" onclick="javascript:freshcheck();"/>
</body>

这样子以来在视图页面显示验证码和实现局部刷新验证码的功能就算OVER了!

stblog学习笔记1

没有评论

2010 年 12 月 01 日 at 下午 1:23分类:PHP | WEB开发

最近在学习CI 的开源产品StBlog,初次学习感觉这个产品写的很不错 对于我这样子的一个CI 新手来说是一个很不错的学习机会。在大致的理解了一下整个的博客系统的架构之后,感觉这个里面有好多东西都是我在之前一段时间里面学习CI没有接触到的东西,就比如说自定义模版的路径,这样子以来 使得整个网站有了一个新的功能 那就是可以选择主题和皮肤了!主要的实现过程就是自己在项目的类库文件夹中首先扩展Loader.php文件(class MY_Loader extends CI_Loader),然后在这个类里面定义两个方法(一个是项目的前台的重写路径,一个是后台的重写路径,后台的路径可以说不变还是原来的那个),该方法的功能是用来重写视图的路径的,详见代码:

 public function __construct() 
    {
        parent::CI_Loader();
    }

	 /**
	 * 打开皮肤功能
	 * 
	 * @access public
	 * @return void
	 */ 
    public function switch_theme_on()
    {
    	$this-&gt;_ci_view_path = FCPATH . ST_THEMES_DIR . DIRECTORY_SEPARATOR . $this-&gt;theme . DIRECTORY_SEPARATOR;
    }

	 /**
	 * 关闭皮肤功能
	 * 
	 * @access public
	 * @return void
	 */ 
    public function switch_theme_off()
    {
    	//just do nothing
    }

接着我们要扩展系统的控制器类(class QT_Controller extends Controller和class HT_Controller extends Controller),然后继承系统的控制器类,在这个类文件中实际上是有两个类的 一个是前台的(QT_Controller),只要是控制前台要操作的一些操作的,然后在之后的写前台的操作代码是只要继承这个类(QT_Controller)就可以了,别忘了在这个类中写上

/** 前台页面均使用主题皮肤功能 */
	    $this-&gt;load-&gt;switch_theme_on();

功能是开启主题皮肤功能我们很多的加载什么类啊 辅助函数啊等都可以在这个前台主控制器里面加载。再来说后台(HT_Controller)其实是跟前台一样的功能的,只不过不同的是使用了

 /** 后台管理页面,不使用皮肤 */
	    $this-&gt;load-&gt;switch_theme_off();

不开启主题皮肤功能,如果要开启的只要写成

/** 前台页面均使用主题皮肤功能 */
	    $this-&gt;load-&gt;switch_theme_on();

就OK了,这样子就描述完了实现前后台主题皮肤的功能!
接下来研究了主要的前台模型的类文件,感觉自己还是很有相当大的差距的,人家写的就是不一样。首先为了避免出现直接的数据库的数据表名,我们可以在模型文件类里面用const来定义表常量,就是把表名赋值给一个自定义的常量,之后在条用表名的时候用这个常量就可以了!其次也许是为了方便检查错误把,在初始化函数里面使用

log_message('debug', "STBLOG: Posts Model Class Initialized");

这样子通过查看日志文件就可以知道这个类已经被加载了。
看到stblog整个模型文件里面函数时,感到都有一个特征 而且我感到这样子蛮好的,就是先把所有各种各样带条件查询相关的函数写在一块,然后把所有的CURD的操作写在一块,这样子感觉整个模型文件蛮清晰的!要找一个函数能够快速找到!
再来说说单个函数的写法,其实要是我自己写的话,也无非就是整理查询条件等东西:首先,所有的查询方法中都有默认的参数项,在生成条件($this->db->where(XXXX))之前我们可以先判断这个参数值的一些情况如:是否为空 是否是数字类型的等等情况,然后在生成条件语句,再者我们可以用链式的写法如:

$this-&gt;db-&gt;select('uid')-&gt;from(self::TBL_USERS)-&gt;where($key, $value);

,在这之后我们还可以不断的写我们需要的各种条件语句 如order_By啊等,在这之后我们只要用

$this-&gt;db-&gt;select('uid')-&gt;from(self::TBL_USERS)-&gt;where($key, $value);

l来返回结果集或者:

$this-&gt;db-&gt;get(self::TBL_USERS)-&gt;row();

l来返回第一行数据,或者

$this-&gt;db-&gt;get(self::TBL_USERS)-&gt;num_rows();

l返回结果数据的数目等等
因为stblog在他的autoload.php文件中默认加载了一些类和辅助函数!因此在整个项目的书写时只要随时拿来用就可以了!
此外 要注意的是有个函数叫做setting_item()的,这个函数的作用是用来获取数据表setting的一些值的,一次获取一个指定name的值,这个函数定义在library的common.php文件中,虽然这个是个类,但是setting_item()函数是定义在类之外的,也就相当于我们一般的辅助函数之类的用法,这个函数用到了stblog自定义的缓存类stcache.php文件,这个文件里面的东西看起来很简单,这个文件中使用文件的辅助函数(file),只要利用文件辅助函数来将数据写入文件实现数据的定时缓存的!
stblog的url都是使用路由来实现的,一开始我也纳闷了半天,后天突然想到可能是设置了路由,打开routes.php一看 果不其然,里面设置了很多的路由规则!看的时候一定要注意哦!
一般情况下我们从网上下载下来CI系统,所有的东西都是放在system文件夹中的,而我们只要开发的目录是在application目录中,其实我个人也不是很喜欢这个样子的目录结果,我实现类似于TP那样子的,把我们要开发的项目目录文件夹APP放在框架同级目录 ,而不是在框架目录里面,其实在CI中要做到这点很简单的,只要把整个application文件剪切出来放在与system文件夹同级目录就行了,并不需要修改任何地方!这样子就实现了类似TP那样子的外围目录效果了!在CI中我们一般的如js啊css啊图片啊等都是在与system文件夹同级目录的目录上建立一个或者几个文件夹来存放相应的东西的!我们的上传文件的目录也是定义在这个地方,当然这个目录是自己定义的,可以放在自己想要的任意位置!我们甚至可以将我们的模版目录定义到入口文件的地方,定义的方法上面已经讲过了!不过要记住的一点就是所有的目录都是相对于index.php文件的,为什么呢?因为stblog是采用单一入口流程来运行的!