CI 学习笔记、记录

【ci框架】ci框架目录结构分析

分类: CodeIgniter深入研究】2013-05-09 00:24 7420人阅读 评论(5) 收藏 举报

[php] view plaincopy

  1. myshop  
  2. |-----system                框架程序目录  
  3. |-----core          框架的核心程序  
  4. |-----CodeIgniter.php   引导性文件  
  5. |-----Common.php    加载基类库的公共函数  
  6. |-----Controller.php    基控制器类文件:CI_Controller  
  7. |-----Model.php     基模型类文件:CI_Model  
  8. |-----Config.php    配置类文件:CI_Config  
  9. |-----Input.php     输入类文件:CI_Input  
  10. |-----Output.php    输出类文件:CI_Output  
  11. |-----URL.php       URL类文件:CI_URl  
  12. |-----Router.php    路由类文件:CI_Router  
  13. |-----Loader.php    加载类文件:CI_Loader  
  14. |-----helpers           辅助函数  
  15. |-----url_helper.php    url相关的辅助函数,如:创建url的辅助函数  
  16. |-----captcha_helper.php创建图形验证码的辅助函数  
  17. |-----libraries         通用类库  
  18. |-----Pagination.php    通用分页类库  
  19. |-----Upload.php    通用文件上传类库  
  20. |-----Image_lib.php 通用图像处理类库  
  21. |-----Session.php   通用session类库  
  22. |-----language          语言包  
  23. |-----database          数据库操作相关的程序  
  24. |-----DB_active_rec.php 快捷操作类文件(ActiveRecord)  
  25. |-----fonts         字库  
  26. |-----application           项目目录  
  27. |-----core          项目的核心程序  
  28. |-----helpers           项目的辅助函数  
  29. |-----libraries         通用类库  
  30. |-----language          语言包  
  31. |-----config            项目相关的配置  
  32. |-----config.php    项目相关的配置文件     
  33. |-----database.php  数据库相关的配置文件  
  34. |-----autoload.php  设置自动加载类库的配置文件  
  35. |-----constants.php 常量配置文件  
  36. |-----routes.php    路由配置文件  
  37. |-----controllers       控制器目录  
  38. |-----welcome.php   控制器文件,继承CI_Controller  
  39. |-----models            模型目录  
  40. |-----welcome_model.php 模型文件,继承CI_Model  
  41. |-----views         视图目录  
  42. |-----welcome.php   视图模板文件,默认后缀名为.php  
  43. |-----cache         存放数据或模板的缓存文件  
  44. |-----errors            错误提示模板  
  45. |-----hooks         钩子,在不修改系统核心文件的基础上扩展系统功能  
  46. |-----third_party       第三方库  
  47. |-----logs          日志  
  48. |-----index.php             入口文件  

 

 

 

 

base_url();根目录地址
site_url();网址

表单验证类 使用

public function index()
{
$this->load->helper(array('form', 'url'));

$this->load->library('form_validation');//1.载入表单验证类

$this->form_validation->set_rules('username', 'Username', 'required');//设置验证规则
$this->form_validation->set_rules('password', 'Password', 'required',
array('required' => 'You must provide a %s.')
);
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
$this->form_validation->set_rules('email', 'Email', 'required');

if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
}

 


举例来说,如果你的 URI 是这样的:

example.com/index.php/products/shoes/sandals/123

URI 的第3和第4部分会被传递给你的方法(“sandals” 和 “123”):

<?php
class Products extends CI_Controller {

public function shoes($sandals, $id)
{
echo $sandals;
echo $id;
}
}
?>

上面的方法调用时必须给两个相应的参数,要不然会出错。当然你也可以像下面这样写,就不用在调用的时候给参数了!

<?php
class Products extends CI_Controller {

public function shoes($sandals='Test', $id=1)
{
echo $sandals;
echo $id;
}
}

 


定义默认控制器
当你的网站没有设置 URI 或者直接从根目录访问的时候,CodeIgniter 会加载默认控制器。打开 application/config/routes.php 文件来设置默认控制器:

$route['default_controller'] = 'Blog'

?>

 

处理输出
CodeIgniter 拥有一个输出类用来确保你修改的数据会自动被传递给浏览器。关于这个的更多信息可以在视图和输出类里找到。有些时候,你可能想要自己发布修改一些最终的数据或是自己把它传递给浏览器。CodeIgniter 允许你给你的控制器增加一个名为 _output() 的方法来接收最终的数据。

注意: 如果你的控制器包含一个 _output() 方法,那么它将总是被调用,而不是直接输出最终的数据。这个方法类似于OO里的析构函数,不管你调用任何方法这个方法总是会被执行。

例如:

public function _output($output)
{
echo $output;
}

请注意,你的 _output() 将接收最终的数据。 Benchmark和内存的使用率数据将被渲染,缓存文件会被写入(如果已启用缓存),并且 HTTP 头也将被发送(如果您使用该功能),然后交给 _output() 函数。

为了让你的控制器输出缓存正确, 它的 _output() 函数可以这样来写:

if ($this->output->cache_expiration > 0)
{
$this->output->_write_cache($output);
}
如果您正在使用页面执行时间和内存使用统计的功能,这可能不完全准确,因为他们不会考虑到你所做的任何进一步的动作。请在输出类参用可用的方法,来控制输出以使其在任何最终进程完成之前执行。

 

私有方法
在某些情况下,你可能想要隐藏一些方法使之无法对外查阅。将方法私有化很简单,只要在方法名字前面加一个下划线(“_”)做前缀就无法通过 URL 访问到了。例如,如果你有一个像这样的方法:

private function _utility()
{
// some code
}

那么,通过下面这样的 URL 进行访问是无法访问到的:

example.com/index.php/blog/_utility/

 


如何将控制器放入子文件夹中
如果你在建立一个大型的应用程序,你会发现 CodeIgniter 可以很方便的将控制器放到一些子文件夹中。

只要在 application/controllers 目录下创建文件夹并放入你的控制器就可以了。

注意: 如果你要使用某个子文件夹下的功能,就要保证 URI 的第一个片段是用于描述这个文件夹的。例如说你有一个控制器在这里:

application/controllers/products/shoes.php

调用这个控制器的时候你的 URI 要这么写:

example.com/index.php/products/shoes/show/123

你的每个子文件夹中需要包含一个默认的控制器,这样如果 URI 中只有子文件夹而没有具体功能的时候它将被调用。只要将你作为默认的控制器名称在 application/config/routes.php 文件中指定就可以了。

CodeIgniter 也允许你使用 URI 路由 功能来重新定向 URI。

 


构造函数
如果要在你的任意控制器中使用构造函数的话,那么必须在里面加入下面这行代码:

parent::__construct();

这行代码的必要性在于,你此处的构造函数会覆盖掉这个父控制器类中的构造函数,所以我们要手动调用它。

<?php
class Blog extends CI_Controller {

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

如果你需要设定某些默认的值或是在实例化类的时候运行一个默认的程序,那么构造函数在这方面就非常有用了。
构造函数并不能返回值,但是可以用来设置一些默认的功能。

 

 


视图
简而言之,一个视图就是一个网页,或是网页的部分,如头部,底部,侧边栏等等。事实上,如果你需要这种层次类型,视图可以很灵活的嵌入到其他视图中。

视图从不直接调用,必须被一个控制器来调用。记住,在一个 MVC 框架中,控制器扮演着交通警察的角色,那么,他有责任去取回某一特定的视图。如果你还没有阅读过控制器页面的话,你应该事先阅读控制器页面。


载入视图 $this->load->view('name');
子文件夹里面的视图
$this->load->view('folder_name/file_name');

zai载入多个视图
如果有多个调用,那么他们将会被合并到一起。例如,你可能希望有一个标题视图、一个菜单视图、一个内容视图、和一个页脚视图。他们看起来应该是这样:

$data['page_title'] = 'Your title';
$this->load->view('header',$data);
$this->load->view('menu');
$this->load->view('content');
$this->load->view('footer');
我们一次性载入多个视图的时候,你只需在第一个视图传入数据就可以了(header视图显示title,content视图显示message),比如:


创建循环
$todo_list 是传过来的数据
<ul>
<?php foreach ($todo_list as $item):?>

<li><?php echo $item;?></li>

<?php endforeach;?>
</ul>

 

 


获取视图内容
view函数第三个可选参数可以改变函数的行为,让数据作为字符串返回而不是发送到浏览器。如果想用其它方式对数据进一步处理,这样做很有用。如果将view第三个参数设置为true(布尔)则函数返回数据。view函数缺省行为是 false, 将数据发送到浏览器。如果想返回数据,记得将它赋到一个变量中:

$string = $this->load->view('myfile', '', true);

view方法中的第三个参数表示不输出视图,而只是将结果返回给一个变量。


active record

 

模型
文件名应该是模型类名的小写版。比如,如果你的类是:

class User_model extends CI_Model {

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

类的文件名应该是:

application/models/user_model.php

 

载入模型
模型可以在 控制器 中被引用。就像这样:

$this->load->model('Model_name');

如果模型文件在子文件夹下,引用的时候要带上相对路径名。例如:如果你有一个模型 application/models/blog/queries.php。下面的代码可以引用它:

$this->load->model('blog/queries');

模型一旦被载入,你就能通过下面的方法使用它:

$this->load->model('Model_name');

$this->Model_name->function();

在默认的情况下模型名称就直接被引入作为对象名,就如上面所示。当然,如果你愿意,可以起个更好记的对象名!那么,可以在加载模型函数中指定第二个参数来设定,例如:

$this->load->model('Model_name', 'fubar');

$this->fubar->function();

 

 

自动载入模型实现的方法是打开 application/config/autoload.php 文件,然后在自动装载数组中添加上这个模型。


链接数据库
您可以把 第三个参数 设置为TRUE来使模型装载函数自动连接数据库,连接配置可以在您的数据库配置文件中可以定义:
$this->load->model('Model_name', '', TRUE);

您可以手动设定第三个参数来载入您的自定义数据库配置:
$config['hostname'] = "localhost";
$config['username'] = "myusername";
$config['password'] = "mypassword";
$config['database'] = "mydatabase";
$config['dbdriver'] = "mysql";
$config['dbprefix'] = "";
$config['pconnect'] = FALSE;
$config['db_debug'] = TRUE;

$this->load->model('Model_name', '', $config);

 

辅助函数
URL Helpers 可以帮助我们创建链接,Form Helpers 可以帮助我们创建表单,Text Helpers 提供一系列的格式化输出方式,Cookie Helpers 能帮助我们设置和读取COOKIE, File Helpers 能帮助我们处理文件,等等。

CodeIgniter 默认是没有载入辅助函数文件的,所以如果你想用辅助函数,就必须先载入它。一旦被载入,辅助函数将全局可用(globally available),你可以在 controller 和 views 中使用它们。

就近原则
辅助函数文件一般保存在 system/helpers 或 application/helpers 文件夹中。CodeIgniter 将会先在 application/helpers 寻找对应的辅助函数文件,如果目录不存在或者目录下没有对应的辅助函数文件,CI 才会载入 system/helpers 下的辅助函数文件。

载入辅助函数是非常简单的:

单个载入
$this->load->helper('name');
多个载入

$this->load->helper( array('helper1', 'helper2', 'helper3') );

自动载入
通过打开 application/config/autoload.php ,并往自动载入数组(autoload array)中增加辅助函数来实现。


name 是辅助函数文件的名字(不带.php后缀 和"helper" 部分)。辅助函数载入函数并不返回值,所以不要尝试将它付给一个变量

使用::
使用辅助函数
一旦你载入了想要用到辅助函数文件,你就可以用标准的函数调用方法来使用里面的函数。

例如,要使用anchor() 函数来建立一个链接,在视图(View)文件里面你可以这样做:

<?php echo anchor('blog/comments', 'Click Here');?>

 

扩展辅助函数
"扩展" Helpers
你如果想 "扩展"一个原有的 Helpers,,可以在你的 application/helpers/ 目录下创建一个新的helper,新的helper的名字是在被“扩展”的Helper的名字开头多加一个 MY_ (这是可以配置的. 见下.).

如果你想做的只是在原有的helper中添加一些新的功能,比如,添加一两个新的方法,或者是修改一个方法;就不值得重写自己的helper。在这种情况下,最好是“扩展”已有的helper。“扩展”一词用在这里不是很恰当,因为Helper的方法是程序化(procedural) 和离散(discrete)的,在传统的语言环境中无法被“扩展”,不过在CodeIgniter中,你可以添加或修改helper的方法。

例如,扩展一个本地已有的 Array Helper 你应该建立一个文件: application/helpers/MY_array_helper.php, 并添加或重写(override)其中的一些方法:

// any_in_array() is not in the Array Helper, so it defines a new function
function any_in_array($needle, $haystack)
{
$needle = (is_array($needle)) ? $needle : array($needle);

foreach ($needle as $item)
{
if (in_array($item, $haystack))
{
return TRUE;
}
}

return FALSE;
}

// random_element() is included in Array Helper, so it overrides the native function
function random_element($array)
{
shuffle($array);
return array_pop($array);
}

设定你自己的前缀(Prefix)
用于"扩展" helper 而加上前缀的文件同样也是对库和核心类的扩展.为了设置你自定义的前缀,请打开 application/config/config.php 文件,然后找到如下的条目:

$config['subclass_prefix'] = 'MY_';

请注意:由于所有CodeIgniter自带的库都被冠以 CI_ 这样的前缀命名,所以请不要使用CI_来自定义前缀.

 

 

 

 

使用 CodeIgniter 类库
所有的类库文件存放在system/libraries 文件夹。大多数情况下你需要预先在controller中初始化后才能使用它们:

$this->load->library('class name');


多个类库可以通过传递包含类库的数组一次加载。

$this->load->library(array('email', 'table'));

例如$this->load->library('form_validation');


建立你的类库文件
你的类库文件必须保存在 application/libraries 文件夹,CodeIgniter将在这个文件夹中寻找并初始化它们.

命名约定
文件名首字母大写. 例如: Myclass.php
类声明首字母大写. 例如: class Myclass
类的名字和文件名应符合.
类文件
所有的类应有基础原型(注意,这里我们以 Someclass 这个名字为例):

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

class Someclass {

public function some_function()
{
}
}

/* End of file Someclass.php */

使用你自己的类
在所有的Controller 函数中,你可以用以下的标准方式初始化你的类:

$this->load->library('someclass');

当 someclass 是文件名时,不用加上".php"扩展名.这里名字不分大小写.

一旦你自定义的类加载完毕,你可以通过以下方式调用类,注意使用 小写 的名字:

$this->someclass->some_function(); // 对象的实例名永远都是小写的

 


在初始化自定义类时传递参数
当初始化类库时,你可以通过第二个参数动态的传递数组到类的构造函数中去:

$params = array('type' => 'large', 'color' => 'red');

$this->load->library('Someclass', $params);

当你使用这个特性时,你必须为类的构造函数加上参数:

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

class Someclass {

public function __construct($params)
{
// Do something with $params
}
}

?>

 


在你自定义的类库中初始化CodeIgniter资源,必须使用 get_instance() 函数.

 

一般来说在你的控制器函数中你可以通过 $this 调用任何可用的CodeIgniter函数:

$this->load->helper('url');
$this->load->library('session');
$this->config->item('base_url');
//etc.
$this, 只直接作用在你自己的控制器,模型和视图中.当你在自定义类中想使用CodeIgniter原始类时,你可以这样做:

首先,定义CodeIgniter对象赋给一个变量:

$CI =& get_instance();

一旦定义某个对象为一个变量,你就可以使用那个变量名 取代 $this:

$CI =& get_instance();

$CI->load->helper('url');
$CI->load->library('session');
$CI->config->item('base_url');
//etc.
注意: 你将注意到get_instance()这个函数通过被引用的方式被传递:

$CI =& get_instance();

这十分重要. 通过引用的方式赋给变量将使用原始的 CodeIgniter 对象,而不是创建一个副本。

 

 

扩展的类必须申明由母类扩展而来.
新扩展的类所在的文件必须以 MY_ 为前缀(这个选项是可配置的,下面有说明).
例如,要扩展原始类 Email 类你要建立文件 application/libraries/MY_Email.php, 并按如下方式在文件中声明:

class MY_Email extends CI_Email {

}

注意:如果你需要在类中使用构造函数,你必须在构造函数中显式继承母类构造函数:

class MY_Email extends CI_Email {

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

载入你的子类
要载入扩展子类,你应该使用标准字符名. 请不要使用前缀. 例如,要载入上文说过的email扩展子类,你应该这样写:

$this->load->library('email');
\
扩展子类一旦被载入,就能像一般的类一样使用它们. Email类中的所有函数就能被调用:

$this->email->some_function();

 

 

 

 

 

 

 

 

使用 CodeIgniter 适配器
适配器的源文件存放在system/libraries 目录下, 在自己的文件夹一样有和父类名字相同的类库可以使用 同时在这个文件夹中,有一个子文件夹叫做 drivers在其中包含了所有的子类

要使用一个适配器,你需要在一个控制器里用如下的初始化函数初始它:

$this->load->driver('class name');
这里的class name 是你想加载的适配器的名字。 比如说你想加载一个叫做"Some Parent"的适配器,你可以这样:

$this->load->driver('some_parent');

控制器类中的方法可以用如下的方式来调用:

$this->some_parent->some_method();

这些作为子类的适配器能直接通过父类调用,而不用初始化。

$this->some_parent->child_one->some_method();
$this->some_parent->child_two->another_method();


创建适配器
适配器目录和文件结构
适配器目录和文件结构布局的例子:

/application/libraries/Driver_name
Driver_name.php
drivers
Driver_name_subclass_1.php
Driver_name_subclass_2.php
Driver_name_subclass_3.php
这个 Driver_name 目录必须使用 ucfirst() 函数处理。

 

 


);

 

 

 

 

 

 

 

 


钩子 - 扩展框架的核心
CodeIgniter 的钩子功能使得您可以在不修改系统核心文件的基础上来改变或增加系统的核心运行功能。 当 CodeIgniter 运行后,它会产生出一个特殊的进程,这个进程在 项目流程 页面中有说明。 当然,您可以自定义一些动作来替代程序运行过程中的某些阶段。例如,您可以在控制器刚刚载入前或刚刚载入后来运行特定的脚本,或者在其他时刻来触发您的脚本。

启用钩子
钩子功能可以在全局范围内打开或关闭,您可以在 application/config/config.php 文件中设定:

$config['enable_hooks'] = TRUE;

定义钩子
钩子是在 application/config/hooks.php 文件中定义的。 每个钩子可以用以下格式的数组来定义:

$hook['pre_controller'] = array(
'class' => 'MyClass',
'function' => 'Myfunction',
'filename' => 'Myclass.php',
'filepath' => 'hooks',
'params' => array('beer', 'wine', 'snacks')
);

说明:
数组的索引与你使用的指定挂钩点名字相关.上面的例子中挂钩点是pre_controller. 挂钩点参数列表如下所示. 以下各项将定义在你的相关钩子数组里:

class 你希望调用的类名.如果你更喜欢使用过程函数代替类的话,此项保留为空.
function 你希望调用的函数名.
filename 包含有你的类/函数的文件名.
filepath 包含你的脚本的目录名. 注意: 你的脚本放在 application 文件夹下的目录里, 这样 filepath就以那个文件夹(application)为基准. 例如, 如果你的脚本放在application/hooks下, 你可以把hooks 作为你的filepath. 如果你的脚本放在application/hooks/utilities下你可以把 hooks/utilities作为filepath. 注意后面没有"/".如果不放在根目录下可以根据相对路径的配置,来完成调用。这样就可以完成,多个应用共享一个钩子。
params 你希望传递给脚本的任何参数. 此项是可选的.
同一挂钩点的多次引用
如果你想在同一个挂钩点引用多个脚本,最简单的方式就是把你的数组定义成二维的,像这样:

$hook['pre_controller'][] = array(
'class' => 'MyClass',
'function' => 'Myfunction',
'filename' => 'Myclass.php',
'filepath' => 'hooks',
'params' => array('beer', 'wine', 'snacks')
);

$hook['pre_controller'][] = array(
'class' => 'MyOtherClass',
'function' => 'MyOtherfunction',
'filename' => 'Myotherclass.php',
'filepath' => 'hooks',
'params' => array('red', 'yellow', 'blue')
);

注意在每个数组索引后面的中括号:

$hook['pre_controller'][]

这允许你的多个脚本拥有相同的挂钩点。你定义数组的顺序将是程序执行的顺序.

 

 

 

 

 


挂勾点
以下是一组可用的挂钩点.

pre_system
系统执行的早期调用.仅仅在benchmark 和 hooks 类 加载完毕的时候. 没有执行路由或者其它的过程.
pre_controller
在调用你的任何控制器之前调用.此时所用的基础类,路由选择和安全性检查都已完成.
post_controller_constructor
在你的控制器实例化之后,任何方法调用之前调用.
post_controller
在你的控制器完全运行之后调用.
display_override
覆盖_display()函数, 用来在系统执行末尾向web浏览器发送最终页面.这允许你用自己的方法来显示.注意,你需要通过 $this->CI =& get_instance() 引用 CI 超级对象,然后这样的最终数据可以通过调用 $this->CI->output->get_output() 来获得。
cache_override
可以让你调用自己的函数来取代output类中的_display_cache() 函数.这可以让你使用自己的缓存显示方法
post_system
在最终着色页面发送到浏览器之后,浏览器接收完最终数据的系统执行末尾调用

 


自动装载资源
“libraries”文件夹中的核心类
“helper”文件夹中的辅助函数
“config”文件夹中自定义配置文件
“system/language”文件夹中的语言包
“models”文件夹中的模型
要自动装载资源,打开 application/config/autoload.php 文件,然后将你想要自动装载的项目添加到 autoload 数组中,你会发现该文件中对应于上面每个项目类型指示。

 

 

 

 

公共函数
注:本条为本人添加。公共函数位于 system/core/Common.php 文件中,大家可以在这里定义自己的公共函数。--IT不倒翁

CodeIgniter 使用了一些全局定义的函数来完成操作,在任何情况下你都能够使用这些函数。使用他们不需要载入任何类库或辅助函数。

eg:
show_error('message'), show_404('page'), log_message('level', 'message')

set_status_header(code, 'text');
允许你手动设置服务器状态头(header)。例如:

set_status_header(401);

// 将header设置为: Unauthorized

 


html_escape($mixed)
利用此功能可以方便的使用htmlspecialchars()函数。它接受字符串和数组。有助于防止跨站脚本攻击(XSS)。

 

 

 

 

 

 

 

 


URI 路由
example.com/class/function/id/

 

设定你自己的路由规则
路由规则定义在application/config/routes.php 文件中. 在此文件中,你可以看到一个名为 $route的数组,它可以让你定义你自己的路由规则。 定义可以用两种方式: 通配符(wildcards) 或者 正则表达式(Regular Expressions)

 

通配符
一个典型的通配符路由看起来是这样的:

$route['product/(:num)'] = "catalog/product_lookup";

在一个路由中,数组的键包含着被匹配的URI,而数组的值包含着路由将被重定向的目的地.在上面的例子中,如果单词“product”出现在URL的第一个部分中,而且数字(:num)出现在URI的第二个部分中,"catalog"类和"product_lookup"方法将被替代使用(即将被重定向).

你可以匹配文字的值或者使用以下两种通配符类型:

:num 将匹配一个只包含有数字的segment(段).
:any 将匹配一个包含任何字符的segment.

注意: 路由将会按照定义的顺序来运行.高层的路由总是优先于低层的路由.
$route['journals'] = "blogs";

如果URL的第一个分段(类名)是关键字"journals",那么将会重定向到"blogs"类中处理.

$route['blog/joe'] = "blogs/users/34";

如果URL的前两个分段是"blog"和"joe",那么将会重定向到"blogs"类的"users"方法中处理.并且将ID"34"设为参数.

$route['product/(:any)'] = "catalog/product_lookup";

当"product"作为URL中第一个分段时, 无论第二分段是什么都将被重定向到"catalog"类的"product_lookup"方法.

$route['product/(:num)'] = "catalog/product_lookup_by_id/$1";

当“product”作为 URL 中第一个分段时,如果第二分段是数字,则将被重定向到“catalog”类,并传递所匹配的内容到“product_lookup_by_id”方法中。


一个典型的正则表达式看起来像下面的样子:

$route['products/([a-z]+)/(\d+)'] = "$1/id_$2";

上例中, 类似于 products/shirts/123 的URI 将换成调用 shirts 控制器类的 id_123 方法.

 


系统保留的路由
系统会保留两个路由:

第一个为系统默认的路由:

$route['default_controller'] = 'welcome';

这个路由表明了当URI中不包含要访问的类和控制器信息的(即只访问根目录的情况,如http://localhost/ci)将要加载哪个控制器。上例中,系统将加载 "welcome" 这个类(控制器)。你应该保证设置一个默认路由,不然你的首页将会显示 404 错误。

第二个为404页面的路由:

$route['404_override'] = '';

这个路由标识了如果请求的控制器无法访问的时候将加载哪个控制器。它相当于覆盖了默认的404错误页面(即提供了自己定义404页面的功能)。但它不会影响show_404()这个方法,这个方法依然会加载默认的位于application/errors/error_404.php的error_404.php页面。

 

 

错误处理
show_error('消息' [, int $status_code = 500 ] [, string $heading = 'An Error Was Encountered'])
这个函数将会使用以下错误模版来显示错误消息:

application/errors/error_general.php

可选参数 $status_code 决定在显示错误的同时将会发送哪种 HTTP 状态代码。

可选参数 $heading 决定错误模版h1标签内容。

show_404('页面' [, 'log_error'])
这个函数将会使用以下错误模版来显示 404 错误信息:

application/errors/error_404.php

传递给该函数的字符串代表的是找不到的文件路径。注意CodeIgniter会在找不到目标控制器情况下,自动显示404消息。

CodeIgniter自动记录任何 show_404() 函数调用。设置第二个可选的参数为FALSE将跳过记录

log_message('级别', '消息')
这个函数可以让你将消息写入记录文件中。你必须在第一个参数中选择三个“级别“中的任何一个, 指明它是那一类消息(调试 debug, 错误 error, 信息info)。 第二个参数是消息本身。 例如:

if ($some_var == "")
{
log_message('error', 'Some variable did not contain a value.');
}
else
{
log_message('debug', 'Some variable was correctly set');
}

log_message('info', 'The purpose of some variable is to provide some value.');

有三种不同类型的消息:

错误类型的消息。 这种是真正的错误消息. 例如PHP错误或者用户错误。
调试类型的消息。 这种是用来帮助调试的消息。 例如, 如果当一个类被初始化时,你可以将这个初始化纪录下来,然后用于调试。
信息类型的消息。 这种是最低优先级别的消息,它只是简单的提供了关于运行的一些信息。 CodeIgniter 不会自动产生任何信息类型的消息,但是你可能会在你的程序里使用它

意: 确保"logs" 文件夹是可写的,才能准确地将消息写入记录文件中。此外, 你必须设置application/config/config.php文件中的"threshold"设定,通过设置“threshold“,你可以只记录错误类型的消息,而不用记录其他两种。如果你将“threshold“设为0,记录就会被禁止。

 

网页缓存

CI支持每个页面单独缓存,而且可以设置缓存更新时间。当一个网页第一次被加载的时候,缓存文件将被保存到application/cache文件夹。下次访问的时候,系统就会直接读取缓存文件,然后返回给用户的浏览器。如果缓存文件过期,它将被删除并重新生成。


启动缓存
启用缓存功能,只需要将下面的代码放入你的任何一个控制器(controller)的方法(function)内:

$this->output->cache(n);
如果你不再想使用缓存,仅需将上面的代码从你的controller里面删除即可


调试你的应用程序

激活分析器
$this->output->enable_profiler(TRUE);
分析器激活后将产生一个报告并插入您的页面底部

使用以下方法禁用该分析器:

$this->output->enable_profiler(FALSE);


启用和禁用分析数据中的字段
分析数据中的每个字段可通过设置相应的控制变量TRUE or FALSE来启用和禁用. 其中的一个方法是:你可以在application/config/profiler.php 配置文件里设置整个程序的全局默认值.

$config['config'] = FALSE;
$config['queries'] = FALSE;

另一种方法是:你可以在控制器中通过调用set_profiler_sections() 来覆盖全局设置和默认设置,详细可见: Output class:

$sections = array(
'config' => TRUE,
'queries' => TRUE
);

$this->output->set_profiler_sections($sections);

 


管理你的应用程序
如果你要对 application 进行重命名, 你需要打开 index.php 文件,对变量 $application_folder 进行更改:

$application_folder = "application";

更改你的应用程序的文件夹路径
你可以将 application文件夹从system 文件夹中挪放到服务器的其他的位置。但是你还要更改 index.php 文件里将$application_folder变量设置为服务器的全路径。

$application_folder = "/Path/to/your/application";

在一个 CodeIgniter 下运行多个应用程序
如果你想要多个应用程序共享同一个 CodeIgniter, 你要将 application 下所有的文件夹放在不同的应用程序的文件夹内。

例如,你要建立两个应用程序 "foo" 和 "bar",你的应用程序文件夹的结构可能会像下面的这样:

applications/foo/
applications/foo/config/
applications/foo/controllers/
applications/foo/errors/
applications/foo/libraries/
applications/foo/models/
applications/foo/views/
applications/bar/
applications/bar/config/
applications/bar/controllers/
applications/bar/errors/
applications/bar/libraries/
applications/bar/models/
applications/bar/views/

要选择使用某个应用程序,你需要打开主 index.php 文件,并且设置 $application_folder 变量为目标路径。例如,通过如下设置,就可以选择使用 "foo" 应用程序:

$application_folder = "applications/foo";

 

 

 

 

 

 

 

 

 

 

 

 

 

 


视图文件的 PHP 替代语法
如果你不使用 CodeIgniter 的模板引擎,则你可以在视图文件中使用原始 PHP 代码。要使 PHP 代码达到最精简并使其更容易辨认,因此建议你使用 PHP 替代语法控制结构及短标记的 echo 语句。 建议你使用 PHP 的语法为你的控制结构和简短的输出标签。如果你还不熟悉这个语法,下面你将学会如何从代码中消灭大括号和“echo”语句。

 


替代 Echo
正常的 echo 和 print 输出一般是这样的形式:

<?php echo $variable; ?>

使用替代语法,你能改成这样的形式:

<?=$variable?>

替代控制结构
控制结构,像 if,for,foreach,和 while 也可以写成简化的形式。这里是一个用 foreach 的例子:

<ul>

<?php foreach ($todo as $item): ?>

<li><?=$item?></li>

<?php endforeach; ?>

</ul>

注意,这里没有大括号。相反,结束大括号被替换成了 endforeach。上面列出的每一个控制结构也有相似的关闭语法:endif,endfor,endforeach,和 endwhile

并且在每个结构以后注意不要使用分号(除了最后一个),用冒号。这是很重要的!

这有另一个例子,使用 if/elseif/else。注意冒号:

<?php if ($username == 'sally'): ?>

<h3>Hi Sally</h3>

<?php elseif ($username == 'joe'): ?>

<h3>Hi Joe</h3>

<?php else: ?>

<h3>Hi unknown user</h3>

<?php endif; ?>

 


安全
本页描述了一些关于 Web 安全的“最佳实践”,并详细说明了 CodeIgniter 的内部安全特性。

URI 安全
CodeIgniter 严格限制 URI 中所能包含的字符,以此帮助你设计的程序减少被恶意数据入侵的可能。URI 一般只包含下列内容:

字母和数字(Alpha-numeric text)
波浪符(Tilde): ~
句号(Period): .
冒号(Colon): :
下划线(Underscore): _
破折号(Dash): -
Register_globals
系统初始化期间所有的全局变量都被 unset,除了那些在 $_GET、$_POST 和 $_COOKIE 数组中的数据。实际上 unsetting 实例程序的作用与register_globals = off 相同。

error_reporting
在生产环境中,往往有必要通过设置内部的error_reporting值为0来禁用PHP错误报告。 这可以防止可能含有敏感信息的原始PHP错误报告输出。

在 index.php 设置CodeIgniter的 ENVIRONMENT 常量为 'production' 将会关闭这些错误(报告)。在开发模式下,推荐设为 'development'。 更多关于各环境间区别的信息可以在处理多环境一章找到。

magic_quotes_runtime
在系统初始化期间 magic_quotes_runtime 指令被关闭以便在数据库检索数据时不必去掉反斜线。

最佳实践
在接收任何数据到你的程序之前,不管是表单提交的 POST 数据、COOKIE 数据、URI 数据、XML-RPC 数据、还是 SERVER 数组中的数据,我们都推荐你实践下面的三个步骤:

过滤不良数据.
验证数据以确保符合正确的类型, 长度, 大小等. (有时这一步骤也可取代第一步骤)
在提交数据到你的数据库之前将其转换.
CodeIgniter 提供了下列函数以辅助这个过程:

XSS 过滤
CodeIgniter带有一个跨站脚本过滤器. 这个过滤器会查找那些用通常手段嵌入到你数据中恶意的Javascript,或其它一些试图欺骗cookie类型的或者做其它恶意事情的代码. XSS Filter的详细描述在 这里.

验证数据
CodeIgniter 有一个表单验证类用来帮助验证、过滤和预处理数据。

插入数据库之前转义所有数据
不要插入未转义的信息到你的数据库中。要了解更多信息请参阅查询章节。

 

 


开发规范:*****************************


文件格式
文件应该使用 Unicode (UTF-8) 编码保存。同时不要使用 字节序标记(BOM) 。

尾标签
所有的php文件应该省略这个php闭合标签,并插入一段注释来标明这是文件的底部并定位这个文件在这个应用的相对路径。这样有利于你确定这个文件已经结束而不是被删节的。

不当的: <?php echo "Here's my code!"; ?> 适当的: <?php echo "Here's my code!"; /* End of file myfile.php */ /* Location: ./system/modules/mymodule/myfile.php */

 

类和方法(函数)的命名规则
类名的首字母应该大写。如果名称由多个词组成,词之间要用下划线分隔,不要使用骆驼命名法。类中所有其他方法的名称应该完全小写并且名称能明确指明这个函数的用途,最好用动词开头。尽量避免过长和冗余的名称
不当的: class superclass class SuperClass 适当的: class Super_class

方法:
不当的: function fileproperties() // 方法名没有清晰的描述以及下划线分割单词 function fileProperties() // 方法名没有清晰的描述以及使用了驼峰法命名 function getfileproperties() // 还可以!但是忘记了下划线分割单词 function getFileProperties() // 使用了驼峰法命名 function get_the_file_properties_from_the_file() // 方法名太冗长 适当的: function get_file_properties() // 清晰的方法名描述,下划线分割单词,全部使用小写字母

 

 


变量命名
变量名应该只包含小写字母,用下划线分隔,并且能适当地指明变量的用途和内容


注释
通常,代码应该被详细地注释。这不仅仅有助于给缺乏经验的程序员描述代码的流程和意图,而且有助于给你提供丰富的内容以让你在几个月后再看自己的代码时仍能很好的理解。 注释没有强制规定的格式,但是我们建议以下的形式。

文档块(DocBlock) 式的注释要写在类和方法的声明前,这样它们就能被集成开发环境(IDE)捕获:

/** * Super Class * * @package Package Name * @subpackage Subpackage * @category Category * @author Author Name * @link http://example.com */ class Super_class {

/** * Encodes string for use in XML * * @access public * @param string * @return string */ function xml_encode($str)

使用行注释时,在大的注释块和代码间留一个空行。

// break up the string by newlines $parts = explode("\n", $str); // A longer comment that needs to give greater detail on what is // occurring and why can use multiple single-line comments. Try to // keep the width reasonable, around 70 characters is the easiest to // read. Don't hesitate to link to permanent external resources // that may provide greater detail: // // http://example.com/information_about_something/in_particular/ $parts = $this->foo($parts);

 

常量
常量命名除了要全部用大写外,其他的规则都和变量相同


TRUE, FALSE, 和 NULL 关键字应该总是完全大写的。

|| 有时让人底气不足,不容易辨识,因为在某些输出设备上它不够清晰(可能看起来像数字11). && 要优先于 AND ,不过两者都可以被接受, 使用 ! 时要在其前后都加一个空格。

不当的: if ($foo || $bar) if ($foo AND $bar) // 可以,但有时不被常用的语法程序高亮推荐(高亮标识) if (!$foo) if (! is_array($foo)) 恰当的: if ($foo OR $bar) if ($foo && $bar) // 推荐 if ( ! $foo) if ( ! is_array($foo))

 

在返回和检查你自己的变量时也要遵循这种严格的方法,必要时使用=== 和 !== 。
不当的: // 如果 'foo' 位于此字符串的起始处,strpos将返回 0, // 此处条件判断的结果为TRUE if (strpos($str, 'foo') == FALSE) 恰当的: if (strpos($str, 'foo') === FALSE)
不当的: function build_string($str = "") { if ($str == "") // uh-oh! 如果传递的参数是FALSE或者整数0那会怎么样? { } } 恰当的: function build_string($str = "") { if ($str === "") { } }

 


在已提交的附加组件所在的地方不能有调试代码,它们被注释掉的情况除外,例如,创建附加组件时不能调用 var_dump(), print_r(), die(), 以及 exit() ,除非它们已经被注释掉了。

// print_r($foo);

 

当你的类或文件名是一个常见词语时,或者是很可能与另一个PHP脚本同名时,使用一个唯一的前缀来避免冲突。你必须始终明白这一点:你的最终用户可能会运行其它第三方的附加组件或者PHP脚本。选择一个能够唯一标识开发者或公司的前缀。

 

数据库表名
你的附加组件所用到的任何表都必须使用 'exp_' 这个前缀,然后是一个能够唯一标识开发者或公司的前缀,最后才是一个简短的描述性的表名。你不需要担心用户安装时所使用的数据库前缀,因为CodeIgniter的数据库类将根据实际情况自动地对 'exp_' 进行转换。

不当的: email_addresses // 缺少这两个前缀 pre_email_addresses // 缺少 exp_ 前缀 exp_email_addresses // 缺少唯一前缀 恰当的: exp_pre_email_addresses

一个文件一个类

在代码中使用tab代替空格。这虽然看起来像是小事,但是使用tab代替空格有利于那些阅读你的代码的开发者在他们各自所使用的应用程序中自定义缩进方式。此外还有一个好处是,使用这种方式保存的文件稍微紧凑一点。

文件必须使用Unix换行符保存。这对于那些在Windows下的开发者来说更为重要,但无论如何,确保你的文本编辑器已经设置为使用Unix换行符来保存文件。

使用 Allman 风格缩进。除了类声明以外,括号总是独占一行,且缩进与“属于”它的控制语句同级。

方括号及圆括号内的空格符
通常情况下,不要在方括号"[]"和圆括号"()"内增加任何空格符。唯一的例外就是为了提高可读性和区别开它们与函数,在接受参数的PHP语法控制结构所使用的括号里,需要增加空格符(declare, do-while, elseif, for, foreach, if, switch, while)。

不恰当的: $arr[ $foo ] = 'foo'; 正确的: $arr[$foo] = 'foo'; // 数组键值的方括号内没有空格 不恰当的: function foo ( $bar ) { } 正确的: function foo($bar) // 函数声明的圆括号内没有空格 { } 不恰当的: foreach( $query->result() as $row ) // PHP语法控制结构之后有空格,但不是在圆括号内 正确的: foreach ($query->result() as $row)

 

私有方法和变量
Methods and variables that are only accessed internally by your class, such as utility and helper functions that your public methods use for code abstraction, should be prefixed with an underscore.

如果方法和变量只在类的内部使用,应当使用下划线作为前缀。

每行一条语句


字符串
一直使用单引号除非你需要解析变量,如果需要解析变量请使用大括号, to prevent greedy token parsing. 如果字符串包含单引号的话你可以使用双引号,这样就不用转义了。


MySQL 的关键字一直大写: SELECT, INSERT, UPDATE, WHERE, AS, JOIN, ON, IN等等


函数的默认参数
可能的话,请提供函数的默认参数,这样可以阻止诸如错误的调用的 PHP 错误,同时可以获取公用的返回值,节约很多行代码。例:

function foo($bar = '', $baz = FALSE)

 

 

 

 

 

 

 

 

 

 

 

 


准备数据
在验证函数的基础上,你可以使用不同的方法准备好你的数据,例如,你可以建立这样的规则:

$rules['username'] = "trim|required|min_length[5]|max_length[12]|xss_clean";
$rules['password'] = "trim|required|matches[passconf]|md5";
$rules['passconf'] = "trim|required";
$rules['email'] = "trim|required|valid_email";

任何只有一个参数的 PHP 原生函数都可以被用作一个规则,比如 ``htmlspecialchars``, ``trim`` 等等。

上面的例子中,我们“修剪”内容,转换密码区域为 MD5 编码,通过“XSS_CLEAN”函数检测用户名,移除危险的数据。

默认的PHP函数能为一个规则使用一个参数,像 htmlspecialchars, trim, MD5, 等等.

 

 

 

 

 

 

 

 

 


数组的关键字实际上是表单域的名字,对应的值是你想要在错误信息中显示的全名。

现在你控制器中的index函数看起来应该像这样:

function index()
{
$this->load->helper(array('form', 'url'));

$this->load->library('validation');

$rules['username'] = "required";
$rules['password'] = "required";
$rules['passconf'] = "required";
$rules['email'] = "required";

$this->validation->set_rules($rules);

$fields['username'] = 'Username';
$fields['password'] = 'Password';
$fields['passconf'] = 'Password Confirmation';
$fields['email'] = 'Email Address';

$this->validation->set_fields($fields);

if ($this->validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}

现在打开你的视图文件myform.php,根据每个表单域的名字更新它们的值。

<html>
<head>
<title>My Form</title>
</head>
<body>

<?=$this->validation->error_string; ?>

<?php echo form_open('form'); ?>

<h5>Username</h5>
<input type="text" name="username" value="<?php echo $this->validation->username;?>" size="50" />

<h5>Password</h5>
<input type="text" name="password" value="<?php echo $this->validation->password;?>" size="50" />

<h5>Password Confirm</h5>
<input type="text" name="passconf" value="<?php echo $this->validation->passconf;?>" size="50" />

<h5>Email Address</h5>
<input type="text" name="email" value="<?php echo $this->validation->email;?>" size="50" />

<div><input type="submit" value="Submit" /></div>

</form>

</body>
</html>


现在重新加载你的页面,提交表单并触发一个错误。你的表单将会被重新填充而且错误信息也会包含更多相关的表单域的名字。

 

单独显示错误
如果你想要在每个表单域旁显示错误,而不是显示一个错误列表,你可以像这样修改你的表单:

<h5>Username</h5>

<?php echo $this->validation->username_error; ?>
<input type="text" name="username" value="<?php echo $this->validation->username;?>" size="50" />

<h5>Password</h5>
<?php echo $this->validation->password_error; ?>
<input type="text" name="password" value="<?php echo $this->validation->password;?>" size="50" />

<h5>Password Confirm</h5>
<?php echo $this->validation->passconf_error; ?>
<input type="text" name="passconf" value="<?php echo $this->validation->passconf;?>" size="50" />

<h5>Email Address</h5>
<?php echo $this->validation->email_error; ?>
<input type="text" name="email" value="<?php echo $this->validation->email;?>" size="50" />
如果没有错误,不会显示任何东西。如果有错误发生,消息将会使用你设置的分割标记显示(<p> 标记是默认值)。

Note: 要这样显示错误信息,你必须之前使用$this->validation->set_fields 函数描述。错误将会被转换成表单域名加"_error"后缀的变量。例如,你的用户名错误的值可以这样访问:
$this->validation->username_error.

 


处理选择菜单,单选按钮,和复选框
如果你使用了选择菜单,单选按钮,和复选框,你会想在出错时保持原先的选择。验证类有三个函数帮助你完成这些:

set_select()
允许你显示和提交时状态一致的菜单项。第一个参数是选择菜单的名字,第二个参数必须包含每个选项的值。例如:

<select name="myselect">
<option value="one" <?php echo $this->validation->set_select('myselect', 'one'); ?> >One</option>
<option value="two" <?php echo $this->validation->set_select('myselect', 'two'); ?> >Two</option>
<option value="three" <?php echo $this->validation->set_select('myselect', 'three'); ?> >Three</option>
</select>
set_checkbox()
允许你显示和提交时状态一致的复选框。第一个参数是复选框的名字,第二个参数必须包含它的值,例如:

<input type="checkbox" name="mycheck" value="1" <?php echo $this->validation->set_checkbox('mycheck', '1'); ?> />

set_radio()
允许你显示和提交时状态一致的单选按钮。第一个参数是单选按钮的名字,第二个参数必须包含它的值:例如:

<input type="radio" name="myradio" value="1" <?php echo $this->validation->set_radio('myradio', '1'); ?> />

 

 


下表列出了所有可用的原生规则:

规则 参数 描述 例子
required No 如果表单元素为空,返回 FALSE
matches Yes 如果表单元素值与参数中对应的表单字段的值不相等,返回 FALSE matches[form_item]
regex_match Yes 如果表单元素不匹配正则表达式,返回 FALSE regex_match[/regex/]
differs Yes 如果表单元素值与参数中对应的表单字段的值相等,返回 FALSE differs[form_item]
is_unique Yes 如果表单元素值在指定的表和字段中并不唯一,返回 FALSE 注意:这个规则需要启用 查询构造器 is_unique[table.field]
min_length Yes 如果表单元素值的长度小于参数值,返回 FALSE min_length[3]
max_length Yes 如果表单元素值的长度大于参数值,返回 FALSE max_length[12]
exact_length Yes 如果表单元素值的长度不等于参数值,返回 FALSE exact_length[8]
greater_than Yes 如果表单元素值小于或等于参数值或非数字,返回 FALSE greater_than[8]
greater_than_equal_to Yes 如果表单元素值小于参数值或非数字,返回 FALSE greater_than_equal_to[8]
less_than Yes 如果表单元素值大于或等于参数值或非数字,返回 FALSE less_than[8]
less_than_equal_to Yes 如果表单元素值大于参数值或非数字,返回 FALSE less_than_equal_to[8]
in_list Yes 如果表单元素值不在规定的列表中,返回 FALSE in_list[red,blue,green]
alpha No 如果表单元素值包含除字母以外的其他字符,返回 FALSE
alpha_numeric No 如果表单元素值包含除字母和数字以外的其他字符,返回 FALSE
alpha_numeric_spaces No 如果表单元素值包含除字母、数字和空格以外的其他字符,返回 FALSE 应该在 trim 之后使用,避免首尾的空格
alpha_dash No 如果表单元素值包含除字母/数字/下划线/破折号以外的其他字符,返回 FALSE
numeric No 如果表单元素值包含除数字以外的字符,返回 FALSE
integer No 如果表单元素包含除整数以外的字符,返回 FALSE
decimal No 如果表单元素包含非十进制数字时,返回 FALSE
is_natural No 如果表单元素值包含了非自然数的其他数值 (不包括零),返回 FALSE 自然数形如:0、1、2、3 .... 等等。
is_natural_no_zero No 如果表单元素值包含了非自然数的其他数值 (包括零),返回 FALSE 非零的自然数:1、2、3 .... 等等。
valid_url No 如果表单元素值包含不合法的 URL,返回 FALSE
valid_email No 如果表单元素值包含不合法的 email 地址,返回 FALSE
valid_emails No 如果表单元素值包含不合法的 email 地址(地址之间用逗号分割),返回 FALSE
valid_ip No 如果表单元素值不是一个合法的 IP 地址,返回 FALSE 通过可选参数 “ipv4” 或 “ipv6” 来指定 IP 地址格式。
valid_base64 No 如果表单元素值包含除了 base64 编码字符之外的其他字符,返回 FALSE
注解

这些规则也可以作为独立的函数被调用,例如:

$this->form_validation->required($string);
注解

你也可以使用任何一个接受两个参数的原生 PHP 函数(其中至少有一个参数是必须的,用于传递域值)
预处理参考
下表列出了所有可用的预处理方法:

名称 参数 描述
prep_for_form No 将特殊字符的转换,以便可以在表单域中显示 HTML 数据,而不会破坏它
prep_url No 当 URL 丢失 “http://” 时,添加 “http://“
strip_image_tags No 移除 HTML 中的 image 标签,只保留 URL
encode_php_tags No 将 PHP 标签转成实体
注解

你也可以使用任何一个接受一个参数的原生 PHP 函数。 例如: trim() 、 htmlspecialchars() 、 urldecode() 等


 CI“超级对象”的问题
当Rick刚开始开发CI时,为了让CI在PHP4和PHP5下行为一致,他必须在Base4文件中使用比较“丑陋”的代码,不管丑不丑,我们不用关心,只要CI能够在PHP4环境下工作得和PHP5一样好就行了。

还有两个问题值得在这里提一下:

你可以尝试开发一个全新的对象并让它参与工作。
你必须小心地为你的网站设计架构,因为你不能在一个控制器里调用另一个控制器里的方法。
让我们一个一个地来分析这两个问题。 你记得我提到的T恤衫的那件事吗?在调用一个成员函数时我一直收到“Call to a member function on a non-object”的出错信息,这个出错信息产生的原因一般是因为你调用了一个类方法,但是忘了装载这个类。换句话说,你写了下列语句:

复制代码到剪贴板PHP 代码$this->Model_name->function();但是忘记在它之前调用:

复制代码到剪贴板PHP 代码$this->load->model('Model_name');还有一些其它情况,比如,你在类的一个方法中装载了模型,然后你尝试在另一个方法里调用模型的方法,虽然在同一个对象中,这样做也不行。所以最好的方法是在类的构造函数中装载模型,然后可以在这个类的所有方法中使用。

问题也可能更严重。如果写你自己的类,举例来说,你可能想要使用这个类存取数据库, 或在你的config文件中读取信息,换句话说,让这个类存取CI超级对象的某些部分。(如何装载你自己的类和类库会在第13章中讨论。)概括起来,除非你的新类是一个控制器,一个模型或视图,它不能在CI超级对象中被构造。因此你不能在你的新类中写这样的代码:

复制代码到剪贴板PHP 代码$this->config->item('base_url');这不会工作的,因为对你的新类来说,$this-> 意味着它本身,而不是CI超级对象。取而代之地,你必须通过调用Instance类用另一个变量名(通常是 $obj)把你的新类载入CI超级对象:

复制代码到剪贴板PHP 代码$obj =& get_instance();现在你能像调用CI超级对象一样地调用它:

复制代码到剪贴板PHP 代码$obj->config->item('base_url');并且这次它能工作了。

因此,当你编写你的新类时,记得它有它自己的标识符。让我们使用一个较简短的例子来把这个问题讲得更清楚一点。

你想要写一个library类,用向你的服务器发出页面请求的URL查找它的地理位置。这个library类有点像netGeo类,你可以在下列网址找到它:

http://www.phpclasses.org/browse/package/514.html

这个类使用一个switch函数,根据URL的地域分派不同的网页,比如来自英国和美国的URL请求,你就返回一个英语网页,德国和奥地利的URL请求就返回一个德语网页等等。现在,完整的URL会分成两个部分:基本URL(www.mysite.com/index.php)和附加的URL部分(mypage/germanversion)。

你需要从CI的config文件中取得基本URL部分。后半段网址通过你的新类的构造函数中的switch语句生成,如果这个客户在德国,调用德国的页面函数,依次类推。当这个工作在构造函数中做完以后,你需要把结果放到一个类属性中,所以可以在同一个类的其它函数中使用,这意味着:

基本URL从CI config文件中取得,这个只能通过CI超级对象的引用获得,换句话说,你可以用 $obj->config->item('base_url'); 获得
URL的后半部分由你的新类的构造函数生成,并写到一个类属性中:$base。这个属性与CI超级对象无关,它属于你的新类,被引用为 $this->base。
装载时会用到两个关键词:$this-> 和 $obj->,在同一段代码中被引用,举例来说:

复制代码到剪贴板PHP 代码class my_new_class{
var $base;
My_new_class()
{
$obj =& get_instance();
// geolocation code here, returning a value through a switch statement
//this value is assigned to $local_url
$this->base = $obj->config->item('base_url');
$this->base .= $local_url;
}如果你不清楚这些概念,“Call to a member function on a non-object”就会频繁的出现。上例中,如果你试着调用 $obj->base或 $this->config->item() 时,这个出错信息就出现了。

 

CI 有三个函数、 show_error() 、 show_404() 和 log_message(),控制错误如何在你的系统上被显示。 (不同寻常地,这些函数是全局性的: 你不需要装载就能使用他们,用就行了!)。 事实上, show_error() 和 show_404() 通常默认产生; 前一个在屏幕顶端的一个整洁的小 HTML 格式的框子中显示你的错误; 后一个在你企图请求一个不存在的网页时显示一个'404'页。

第三个函数,log_message(), 更有趣。你可能想要开发你自己的错误日志,原因有多种多样的,其中一个是也许因为你不能访问在你的ISP的Apache上的日志文件。 首先, 你需要设定权限确保 /system/logs目录是可读写的。 然后你在config文件中设定logging的级别:

复制代码到剪贴板PHP 代码/*
|--------------------------------------------------------------------------
| Error Logging Threshold
|------------------------------------------------------------------------
|
| If you have enabled error logging, you can set an error threshold to
| determine what gets logged. Threshold options are:
|
| 0 = Disables logging
| 0 = Error logging TURNED OFF
| 1 = Error Messages (including PHP errors)
| 2 = Debug Messages
| 3 = Informational Messages
| 4 = All Messages
|
| For a live site you'll usually only enable Errors (1) to be logged
| otherwise your log files will fill up very fast.
|
*/
$config['log_threshold'] = 4;这样会开启日志。

如果你修改 index.php 关闭错误信息显示并不会使错误日志不工作。 因此你能看到信息,但你的用户看不到。

当你开启日志后, CI 每天产生新的记录文件, 并把信息写入这个文件。 但是小心, 这些记录文件能快速地变得很大。

 

在实际使用过程中,你可能需要开发在某件事发生时显示特定出错信息的错误处理代码。

 


。。。。。。。。。。。。。。。。。。测试运行时间等等

profiler 类非常精彩,你在你的类的一个函数中插入一行代码(它在构造函数中工作,因此放在那里才有意义.) 这行代码是:

复制代码到剪贴板PHP 代码$this->output->enable_profiler(TRUE);如果你改变主意了, 你可以修改它:

复制代码到剪贴板PHP 代码$this->output->enable_profiler(FALSE);插入这行代码得到的回报,就是你能在你的屏幕上得到一个完整的报告。显示CI超级对象和你的控制器的时间花销以及$_POST数组和数据库查询等等所用的时间。在开发阶段,这个特别有用。

如果你加上你自己的基准测试,它也会显示这些。 你必须使用特别的名字命名你的基准测试-他们必须包括在"_start"和"_end"中,每一组的命名都要不一样:

复制代码到剪贴板PHP 代码$this->benchmark->mark('fred_start');并且, 还有:

复制代码到剪贴板PHP 代码$this->benchmark->mark('fred_end');

posted @ 2016-09-05 15:45  的士特啰嗦司机  阅读(1124)  评论(0编辑  收藏  举报