这是一个应用所应具有的基本功能之一,不用从零开发。Yii Extensions有现成的东西直接可用,或者在其基础上进行定制。
以Yii-UserModule为例。该扩展Module用于用户注册与管理。有用户注册、账号激活、密码修复、profile配置、用户CRUD功能。使用方法参见官网上的Yii-User extension。
1 数据表结构
该module的维护的用户数据有三张数据表,如下图:
通过UI维护profiles_fields表中的数据,详细定义了每个profile的名称、类型、验证、缺省等,运行时根据该表的CRUD操作对profiles的结构进行通过ALTER TABLE等语句重新重构。
首先,yii framework将 login请求转发到 yii usermodule,后者接管login流程,验证后,设置必要的状态并redirect返回。如图:
- 流程涉及framework和module两部分,左边蓝色两个类属于yii framework,右边黄色四个类属于YiiUser Module。
- 对于CWebUser的loginUrl的初始化值在protected/config/main.php中设置,参阅上篇文章,设为“user/login”,通过urlManager 指向了User Module的LoginController,该Controller中的defaultAction为login(步骤2)。
- UserIdentity扩展自framework的CBaseUserIdentity,验证username(或者email)、password正确后,设置_id和username属性。
- 登录成功后,UserLogin调用CWebUser的login方法,并将UserIdentity实例作为参数一并传递。CWebUser作为CWebApplication的属性,设置id、name、state等,这些信息在整个application范围内可通过Yii::app()->user访问。
- 在Session中设置User信息:UserIdentity验证通过后,此时该实例拥有User对象,可通过setState方法设置User的其他 信息,该信息随后经CWebUser的login方法处理进入session,可通过Yii::app()->user获取。
- login成功的后续操作:UserLogin调用CWebUser的login方法之后,此时成功login流程已走完,可在此追加记录用户登录IP、发送email、系统检查等其他操作。
通过tbl_users表中的supperuser属性,可标记用户是否属于administrator。
程序中通过Yii::app()->findModule("user")->isAdmin()来判断。
当然通过这种方式定义角色是比较简单的。yii社区还有其他的module,专门解决角色及访问控制问题的。
本文链接
bool assert ( mixed $assertion [, string $description ] ) — 检查一个断言是否为 FALSE
2 assert_options(ASSERT_WARNING, false);//在assert失败时不输出警告信息
3 assert_options(ASSERT_BAIL, true);//assert失败后终止代码执行
4 assert_options(ASSERT_CALLBACK, 'getMsg');//assert失败后终止代码执行。
5
6 echo '开始:<br/>';
7 assert('mysql_query("")');
8 echo '测试成功!';
9
10 function getMsg(){
11 echo '出错啦!';
12 }
mixed assert_options ( int $what [, mixed $value ] ) — 设置 assert() 的各种控制选项,或者查询当前的设置
ASSERT_ACTIVE : 是否启用 assert() 断言, ini配置 assert.active,默认值 1
ASSERT_WARNING :是否为每个失败的断言产生一个 PHP 警告,ini配置 assert.warning,默认1
ASSERT_BAIL :是否在断言失败时中止执行,ini配置 assert.bail,默认值0
ASSERT_QUIET_EVAL :是否在断言表达式求值时禁用 error_reporting,ini配置assert.quiet_eval,默认值0
ASSERT_CALLBACK :断言失败时调用回调函数,ini配置assert.callback
2 assert_options(ASSERT_WARNING, false);//在assert失败时不输出警告信息
3 assert_options(ASSERT_BAIL, true);//assert失败后终止代码执行
4 assert_options(ASSERT_CALLBACK, 'getMsg');//assert失败后终止代码执行。
5
6 echo '开始:<br/>';
7 assert(is_int(1.2));//检测结果为fales
8 echo '测试成功!';
9
10 function getMsg(){
11 echo '出错啦!';
12 }
bool dl( string $library ) — 获取 PHP 配置选项的值 载入指定的 PHP扩展
2 $prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' : '';
3 dl($prefix . 'sqlite.' . PHP_SHLIB_SUFFIX);
4 }
int gc_collect_cycles() — 强制收集所有现存的垃圾循环周期
void gc_disable ( void ) — 停用循环引用收集器
void gc_enable ( void ) — 激活循环引用收集器
bool gc_enabled ( void ) — 返回循环引用计数器的状态
string get_cfg_var ( string $option ) — 获取 PHP 配置选项的值获取 PHP 配置选项的值
string get_current_user ( void )— 获取当前 PHP 脚本所有者名称
array get_defined_constants ([ bool $categorize = false ] )— 返回所有常量的关联数组
array get_extension_funcs ( string $module_name )— 返回模块函数名称的数组
string get_include_path ( void ) — 获取当前的 include_path 配置选项
array get_included_files ( void )— 返回被 include 和 require 文件名的 array
2 include_once 'test2.php';
3 require 'test3.php';
4 require_once 'test4.php';
5
CodeIgniter为方便开发者提供了下载助手函数force_download('filename', 'data'),但需要使用file_get_contents()函数先将文件内容全部读入一个变量中,这在读取小文件时没什么问题,但读大文件时将会报内存不够的错误,所以我们一般使用readfile()函数读取或者使用fread()依次读取文件片段然后输出的方式下载文件。
CI3虽然还没有最终发布,但在Github中我们看到了将改进force_download()函数的功能,如果第二个参数为NULL,CI将视第一个参数为文件的路径名并使用fread()函数读取文件内容,我们可以将CI3的force_download()函数加入到现有的CI2的项目中,但需要做一些改动,在application/helpers目录下建立MY_download_helper.php文件:
2
3 if ( ! function_exists('force_download'))
4 {
5 /**
6 * Force Download
7 *
8 * Generates headers that force a download to happen
9 *
10 * @param string filename
11 * @param mixed the data to be downloaded
12 * @param bool whether to try and send the actual file MIME type
13 * @return void
14 */
15 function force_download($filename = '', $data = '', $set_mime = FALSE)
16 {
17 if ($filename === '' OR $data === '')
18 {
19 return FALSE;
20 }
21 elseif ($data === NULL)
22 {
23 if (@is_file($filename) && ($filesize = @filesize($filename)) !== FALSE)
24 {
25 $filepath = $filename;
26 $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
27 $filename = end($filename);
28 }
29 else
30 {
31 return FALSE;
32 }
33 }
34 else
35 {
36 $filesize = strlen($data);
37 }
38
39 // Set the default MIME type to send
40 $mime = 'application/octet-stream';
41
42 $x = explode('.', $filename);
43 $extension = end($x);
44
45 if ($set_mime === TRUE)
46 {
47 if (count($x) === 1 OR $extension === '')
48 {
49 /* If we're going to detect the MIME type,
50 * we'll need a file extension.
51 */
52 return FALSE;
53 }
54
55 // Load the mime types
56 if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
57 {
58 include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
59 }
60 elseif (is_file(APPPATH.'config/mimes.php'))
61