Yii快速入门(一)基本概念

一、入口文件

入口文件内容:一般格式如下:

<?php
$yii=dirname(__FILE__).'/../../framework/yii.php';//Yii框架位置
$config=dirname(__FILE__).'/protected/config/main.php';//当前应用程序的主配置文件位置
// 部署正式环境时,去掉下面这行
// defined('YII_DEBUG') or define('YII_DEBUG',true);//是否运行在调试模式下
require_once($yii);//包含Yii框架
Yii::createWebApplication($config)->run();//根据主配置文件建立应用实例,并运行。
                                          你可以在当前应用的任何位置通过Yii::app()来访问这个实例。

二、主配置文件

保存位置:你的应用/protected/config/main.php
文件内容:一般格式如下:

<?php
return array(
    'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..', //当前应用根目录的绝对物理路径
    'name'=>'Yii Blog Demo', //当前应用的名称
    // 预载入log(记录)应用组件,这表示该应用组件无论它们是否被访问都要被创建。
    //该应用的参数配置在下面以“components”为关键字的数组中设置。
    'preload'=>array('log'), //log为组件ID
    // 自动载入的模型和组件类
    'import'=>array(
        'application.models.*', //载入“application/models/”文件夹下的所有模型类
        'application.components.*', //载入“application/components/”文件夹下的所有应用组件类
    ),
    'defaultController'=>'post', //设置默认控制器类
    // 当前应用的组件配置。更多可供配置的组件详见下面的“核心应用组件”
    'components'=>array(
        'user'=>array( //user(用户)组件配置,“user”为组件ID
            // 可以使用基于cookie的认证
            'allowAutoLogin'=>true, //允许自动登录
        ),
        'cache'=>array( //缓存组件
                    'class'=>'CMemCache', //缓存组件类
                    'servers'=>array( //MemCache缓存服务器配置
                        //缓存服务器1
                        array('host'=>'server1', 'port'=>11211, 'weight'=>60),
                        //缓存服务器2 
                        array('host'=>'server2', 'port'=>11211, 'weight'=>40), 
                    ),
        ),
        'db'=>array( //db(数据库)组件配置,“db”为组件ID
            'connectionString' => 'sqlite:protected/data/blog.db', //连接数据库的DSN字符串
            'tablePrefix' => 'tbl_', //数据表前缀
        ),
        // 如果要使用一个MySQL数据库,请取消下面的注释
        'errorHandler'=>array(
            // 使用SiteController控制器类中的actionError方法显示错误
            //遇到错误时,运行的操作。控制器名和方法名均小写,并用斜线“/”隔开
            'errorAction'=>'site/error', 
        ),
      //URL路由管理器
        'urlManager'=>array(
//URL格式。 共支持两种格式:'path'格式(如:/path/to/EntryScript.php/name1/value1/name2/value2...)
//和'get'格式(如: /path/to/EntryScript.php?name1=value1&name2=value2...)。
//当使用'path'格式时,需要设置如下的规则:
            'urlFormat'=>'path', 
            'rules'=>array( //URL规则。语法:<参数名:正则表达式>
//将post/12/helloword指向post/view?id=12&title=helloword
                'post/<id:\d+>/<title:.*?>'=>'post/view', 
//将posts/hahahaha指向post/index?tag=hahahaha
                'posts/<tag:.*?>'=>'post/index', 
                '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
            ),
        ),
        'log'=>array(  //记录
            'class'=>'CLogRouter', //处理记录信息的类
            'routes'=>array(
                array(
                    'class'=>'CFileLogRoute', //处理错误信息的类
                    'levels'=>'error, warning', //错误等级
                ),
                // 如要将错误记录消息在网页上显示,取消下面的注释即可
            ),
        ),
    ), //应用组件配置结束
    // 使用Yii::app()->params['参数名']可以访问应用层的参数
    'params'=>require(dirname(__FILE__).'/params.php'),
);

核心应用组件:

Yii 预定义了一系列核心应用组件,提供常见 Web 应用中所用的功能。例如, request 组件用于解析用户请求并提供例如 URL,cookie 等信息。通过配置这些核心组件的属性,我们可以几乎任意的修改Yii 的默认行为。

下面我们列出了由 CWebApplication 预定义的核心组件。

assetManager: CAssetManager - 管理私有资源文件的发布。
authManager: CAuthManager - 管理基于角色的访问控制 (RBAC).
cache: CCache - 提供数据缓存功能。注意,你必须指定实际的类(例如CMemCache, CDbCache)。
                否则,当你访问此组件时将返回 NULL。
clientScript: CClientScript - 管理客户端脚本 (javascripts 和 CSS).
coreMessages: CPhpMessageSource - 提供 Yii 框架用到的核心信息的翻译。
db: CDbConnection - 提供数据库连接。注意,使用此组件你必须配置其 connectionString 属性。
errorHandler: CErrorHandler - 处理未捕获的 PHP 错误和异常。
format: CFormatter - 格式化数值显示。此功能从版本 1.1.0 起开始提供。
messages: CPhpMessageSource - 提供Yii应用中使用的信息翻译。
request: CHttpRequest - 提供关于用户请求的信息。
securityManager: CSecurityManager - 提供安全相关的服务,例如散列,加密。
session: CHttpSession - 提供session相关的功能。
statePersister: CStatePersister - 提供全局状态持久方法。
urlManager: CUrlManager - 提供 URL 解析和创建相关功能
user: CWebUser - 提供当前用户的识别信息。
themeManager: CThemeManager - 管理主题。

要访问一个应用组件,使用 Yii::app()->组件的ID

三、控制器(Controller)

控制器 是 CController 类的子类的实例。它在当用户请求时由应用创建。当一个控制器运行时,它执行所请求的动作(控制器类方法),动作通常会引入所必要的模型并渲染相应的视图。动作,就是一个名字以 action 开头的控制器类方法(action+大写首字母的动作名)。
控制器类文件保存位置protected/controllers/控制器和动作以 ID 识别。
控制器ID 是一种 '父目录/子目录/控制器名' 的格式,对应相应的控制器类文件 protected/controllers/父目录/子目录/大写首字母的控制器名Controller.php;
动作ID 是除去 action 前缀的动作方法名。

1、路由

用户以路由的形式请求特定的控制器和动作。路由是由控制器 ID 和动作 ID 连接起来的,两者以斜线分割。
例如,路由 post/edit 代表 PostController 及其 edit 动作。默认情况下,URL http://hostname/index.php?r=post/edit 即请求此控制器和动作。
注意: 默认情况下,路由是大小写敏感的。可以通过设置应用配置中的 CUrlManager::caseSensitive 为 false 使路由对大小写不敏感。当在大小写不敏感模式中时, 要确保你遵循了相应的规则约定,即:包含控制器类文件的目录名小写,且控制器映射 和 动作映射 中使用的键为小写。
路由的格式:控制器ID/动作ID 或 模块ID/控制器ID/动作ID(如果是嵌套模块,模块ID 就是父模块ID/子模块ID)

2、控制器实例化

应用将使用如下规则确定控制器的类以及类文件的位置:
1、如果指定了 CWebApplication::catchAllRequest , 控制器将基于此属性创建,而用户指定的控制器 ID 将被忽略。这通常用于将应用设置为维护状态并显示一个静态提示页面。
2、如果在 CWebApplication::controllerMap 中找到了 ID, 相应的控制器配置将被用于创建控制器实例。
3、如果 ID 为 'path/to/xyz'的格式,控制器类的名字将判断为 XyzController,相应的类文件则为 protected/controllers/path/to/XyzController.php。如果类文件不存在,将触发一个 404 CHttpException 异常。
在使用了模块的情况下,应用将检查此 ID 是否代表一个模块中的控制器。如果是的话,模块实例将被首先创建,然后创建模块中的控制器实例。

3、动作(action)

动作 就是被定义为一个以 action 单词作为前缀命名的方法。而更高级的方式是定义一个动作类并让控制器在收到请求时将其实例化。这使得动作可以被复用,提高了可复用度。
1、定义一个动作类,基本格式如下:

class UpdateAction extends CAction
{
    public function run()
    {
        // place the action logic here
    }
}

2、使用动作类:为了让控制器注意到这个动作,我们要用如下方式覆盖控制器类的actions() 方法:

class PostController extends CController
{
    public function actions()
    {
        return array(
//使用“应用程序文件夹/controllers/post/UpdateAction.php”文件中的类来处理edit动作          
        'edit'=>'application.controllers.post.UpdateAction', 
        );
    }
}

如上所示,我们使用了路径别名“application.controllers.post.UpdateAction”指定动作类文件为“protected/controllers/post/UpdateAction.php”。
通过编写基于类的动作,我们可以将应用组织为模块的风格。例如,如下目录结构可用于组织控制器相关代码:

protected/
    controllers/
        PostController.php
        UserController.php
        post/
            CreateAction.php
            ReadAction.php
            UpdateAction.php
        user/
            CreateAction.php
            ListAction.php
            ProfileAction.php
            UpdateAction.php

四、过滤器(filter)

过滤器是一段代码,可被配置在控制器动作执行之前或之后执行。
一个动作可以有多个过滤器。如有多个过滤器,则按照它们出现在过滤器列表中的顺序依次执行。过滤器可以阻止动作及后面其他过滤器的执行。
过滤器可以定义为一个控制器类的方法。过滤器方法名必须以 filter 开头。例如,现有的 filterAccessControl 方法定义了一个名为 accessControl 的过滤器。过滤器方法必须为如下结构:

public function filterAccessControl($filterChain)
{
    // 调用 $filterChain->run() 以继续后续过滤器与动作的执行。
}

$filterChain (过滤器链)是一个 CFilterChain 的实例,代表与所请求动作相关的过滤器列表。在过滤器方法中,我们可以调用 $filterChain->run() 以继续执行后续过滤器和动作。
如 动作 一样,过滤器也可以是一个对象,它是 CFilter 或其子类的实例。如下代码定义了一个新的过滤器类:

class PerformanceFilter extends CFilter
{
    protected function preFilter($filterChain)
    {
        // 动作被执行之前应用的逻辑
        return true; // 如果动作不应被执行,此处返回 false
    }
 
    protected function postFilter($filterChain)
    {
        // 动作执行之后应用的逻辑
    }
}

要对动作应用过滤器,我们需要覆盖 CController::filters() 方法。此方法应返回一个过滤器配置数组。例如:

class PostController extends CController
{
    ......
    public function filters()
    {
        return array(
//将postOnly过滤器应用于edit和create动作(这是基于方法的过滤器)
            'postOnly + edit, create', 
            array( //使用了数组来配置过滤器
//将application.filters.PerformanceFilter过滤器应用于除了edit和create之外的所有动作(这是基于对象的过滤器)              
                'application.filters.PerformanceFilter - edit, create', 
                'unit'=>'second', //初始化过滤器对象中的unit属性值为second
            ),
        );
    }
}

上述代码指定了两个过滤器: postOnly 和 PerformanceFilter。 postOnly 过滤器是基于方法的(相应的过滤器方法已在 CController 中定义);而 performanceFilter 过滤器是基于对象的。路径别名 application.filters.PerformanceFilter 指定过滤器类文件是 protected/filters/PerformanceFilter。我们使用一个数组配置 PerformanceFilter ,这样它就可被用于初始化过滤器对象的属性值。此处 PerformanceFilter 的 unit 属性值将被初始为 second。

使用加减号,我们可指定哪些动作应该或不应该应用过滤器。上述代码中, postOnly 应只被应用于 edit 和 create 动作,而 PerformanceFilter 应被应用于 除了 edit 和 create 之外的动作。如果过滤器配置中没有使用加减号,则此过滤器将被应用于所有动作。

五、模型(Model)

模型是 CModel 或其子类的实例。模型用于保持数据以及与其相关的业务逻辑。
模型是单独的数据对象。它可以是数据表中的一行,或者一个用户输入的表单。
数据对象的每个字段对应模型中的一个属性。每个属性有一个标签(label),并且可以通过一系列规则进行验证。
Yii 实现了两种类型的模型:表单模型和 Active Record。二者均继承于相同的基类 CModel。
表单模型是 CFormModel 的实例。表单模型用于保持从用户的输入获取的数据。这些数据经常被获取,使用,然后丢弃。例如,在一个登录页面中,我们可以使用表单模型用于表示由最终用户提供的用户名和密码信息。
Active Record (AR) 是一种用于通过面向对象的风格抽象化数据库访问的设计模式。每个 AR 对象是一个 CActiveRecord 或其子类的实例。代表数据表中的一行。行中的字段对应 AR 对象中的属性。

六、视图

视图是一个包含了主要的用户交互元素的PHP脚本.
视图有一个名字,当渲染(render)时,名字会被用于识别视图脚本文件。视图的名称与其视图脚本名称是一样的。例如:视图 edit 的名称出自一个名为 edit.php 的脚本文件。要渲染时,需通过传递视图的名称调用 CController::render()。这个方法将在“protected/views/控制器ID”目录下寻找对应的视图文件。
在视图脚本内部,我们可以通过 $this 来访问控制器实例。我们可以在视图里以“$this->属性名”的方式获取控制器的任何属性。
我们也可以用以下 推送 的方式传递数据到视图里:

$this->render('edit', array(
    'var1'=>$value1,
    'var2'=>$value2,
));

在以上的方式中, render() 方法将提取数组的第二个参数到变量里。其产生的结果是,在视图脚本里,我们可以直接访问变量 $var1 和 $var2。

1、布局

布局是一种用来修饰视图的特殊的视图文件。它通常包含了用户界面中通用的一部分视图。例如:布局可以包含header和footer的部分,然后把内容嵌入其间。

......header here......
<?php echo $content; ?>
......footer here......

其中的 $content 则储存了内容视图的渲染结果。
当使用render()时,布局被隐式应用。视图脚本 protected/views/layouts/main.php 是默认的布局文件。这可以通过改变 CWebApplication::layout 进行自定义。要渲染一个不带布局的视图,则需调用 renderPartial() 。

2、小物件

小物件是 CWidget 或其子类的实例。它是一个主要用于表现数据的组件。小物件通常内嵌于一个视图来产生一些复杂而独立的用户界面。例如,一个日历小物件可用于渲染一个复杂的日历界面。小物件使用户界面更加可复用。
我们可以按如下视图脚本来使用一个小物件:

<?php $this->beginWidget('小物件类的路径别名'[,'包含属性初始化值的数组']); ?>
...可能会由小物件获取的内容主体...
<?php $this->endWidget(); ?>

或者
<?php $this->widget('小物件类的路径别名'[,'包含属性初始化值的数组']); ?>
后者用于不需要任何 body 内容的组件。
小物件可通过配置来定制它的表现。这是通过调用 CBaseController::beginWidget 或 CBaseController::widget 设置其初始化属性值来完成的。
我们通过传递一个携带这些属性初始化值的数组来实现,该数组的键是属性的名称,而数组的值则是小物件属性所对应的值。如下所示 :

<?php
$this->widget('CMaskedTextField',array(
    'mask'=>'99/99/9999'
));
?>

继承 CWidget 并覆盖其init()和run()方法,可以定义一个新的小物件:

class MyWidget extends CWidget
{
    public function init()
    {
        // 此方法会被 CController::beginWidget() 调用
    }
    public function run()
    {
        // 此方法会被 CController::endWidget() 调用
    }
}

小物件可以像一个控制器一样拥有它自己的视图。
默认情况下,小物件的视图文件位于包含了小物件类文件目录的 views 子目录之下(protected/components/views)。这些视图可以通过调用CWidget::render()渲染,这一点和控制器很相似。唯一不同的是,小物件的视图没有布局文件支持。另外,小物件视图中的$this指向小物件实例而不是控制器实例。

3、系统视图

系统视图的渲染通常用于展示 Yii 的错误和日志信息。
系统视图的命名遵从了一些规则。比如像“errorXXX”这样的名称就是用于渲染展示错误号XXX的 CHttpException 的视图。例如,如果 CHttpException 抛出一个404错误,那么 error404 就会被显示。
在 framework/views 下, Yii 提供了一系列默认的系统视图. 他们可以通过在 protected/views/system 下创建同名视图文件进行自定义。

七、组件

Yii 应用建立于组件之上。组件是 CComponent 或其子类的实例。使用组件主要涉及访问它的属性以及触发或处理它的时间。基类 CComponent 指定了如何定义属性和事件。

1、组件属性

组件的属性就像对象的公共成员变量。它是可读写的。
要定义一个组件属性,我们只需在组件类中定义一个公共成员变量即可。
更灵活的方式是定义其 getter 和 setter 方法,例如:

public function getTextWidth()      // 获取 textWidth 属性
{
    return $this->_textWidth;
}
public function setTextWidth($value)    // 设置 TextWidth 属性
{
    $this->_textWidth=$value;
}

上述代码定义了一个可写的属性名为 textWidth(名字是大小写不敏感的)。当读取属性时,getTextWidth() 就会被调用,其返回值则成为属性值;相似的,当写入属性时,setTextWidth() 被调用。如果 setter 方法没有定义,则属性将是只读的,如果对其写入则会抛出一个异常。使用 getter 和 setter 方法定义一个属性有一个好处:即当读取或写入属性时,可以执行额外的逻辑(例如,执行验证,触发事件)。
注意: 通过 getter/setter 定义的属性和类成员变量之间有一个细微的差异:属性的名字是大小写不敏感的, 而 类成员变量是大小写敏感的。

2、组件事件

组件事件是一些特殊的属性,它们使用一些称作 事件句柄(event handlers)的方法作为其值。分配一个方法到一个事件将会引起方法在事件被唤起处自动被调用。因此,一个组件的行为可能会被一种在部件开发过程中不可预见的方式修改。
组件事件以 on 开头的命名方式定义。和属性通过 getter/setter 方法来定义的命名方式一样,事件的名称是大小写不敏感的。以下代码定义了一个 onClicked 事件:

public function onClicked($event)
{
    $this->raiseEvent('onClicked', $event);
}

这里作为事件参数的 $event 是 CEvent 或其子类的实例。
我们可以分配一个方法到此事件,如下所示:
$component->onClicked=$callback;
这里的 $callback 指向了一个有效的 PHP 回调。它可以是一个全局函数也可以是类中的一个方法。如果是后者,它必须以一个数组的方式提供: array($object,'methodName')。
事件句柄的结构如下:

function 方法名($event)
{
    ......
}

这里的 $event 即描述事件的参数(它来源于 raiseEvent() 调用)。$event 参数是 CEvent 或其子类的实例。至少,它包含了关于谁触发了此事件的信息。
事件句柄也可以是一个PHP 5.3以后支持的匿名函数。例如:

$component->onClicked=function($event) {
    ......
}

如果我们现在调用 onClicked(),onClicked 事件将被触发(在 onClicked() 中),附属的事件句柄将被自动调用。
一个事件可以绑定多个句柄。当事件触发时,这些句柄将被按照它们绑定到事件时的顺序依次执行。如果句柄决定组织后续句柄被执行,它会设置 $event->handled 为 true。

3、组件行为

组件已添加了对 mixin 的支持,并可以绑定一个或多个行为。行为是一个对象,其方法可以被它绑定的部件通过收集功能的方式来实现继承(inherited),而不是专有化继承(即普通的类继承)。一个部件可以以'多重继承'的方式实现多个行为的绑定。
行为类必须实现 IBehavior 接口。 大多数行为可以继承自 CBehavior 。如果一个行为需要绑定到一个模型, 它也可以从专为模型实现绑定特性的 CModelBehavior 或 CActiveRecordBehavior 继承。
要使用一个行为,它必须首先通过调用此行为的 attach() 方法绑定到一个组件。然后我们就可以通过组件调用此行为方法:

// $name 在组件中实现了对行为的唯一识别
$component->attachBehavior($name,$behavior);
// test() 是行为中的方法。
$component->test();

已绑定的行为可以像一个组件中的普通属性一样访问。例如,如果一个名为 tree 的行为绑定到了一个组件,我们就可以通过如下代码获得指向此行为的引用。

$behavior=$component->tree;
// 等于下行代码:
// $behavior=$component->asa('tree');
行为是可以被临时禁止的,此时它的方法就会在组件中失效。例如:
$component->disableBehavior($name);
// 下面的代码将抛出一个异常
$component->test();
$component->enableBehavior($name);
// 现在就可以使用了
$component->test();

两个同名行为绑定到同一个组件下是有可能的。在这种情况下,先绑定的行为则拥有优先权。
当和 events, 一起使用时,行为会更加强大。当行为被绑定到组件时,行为里的一些方法就可以绑定到组件的一些事件上了。这样一来,行为就有机观察或者改变组件的常规执行流程。
一个行为的属性也可以通过绑定到的组件来访问。这些属性包含公共成员变量以及通过 getters 和/或 setters 方式设置的属性。例如, 若一个行为有一个 xyz 的属性,此行为被绑定到组件 $a,然后我们可以使用表达式 $a->xyz 访问此行为的属性。

八、模块

模块是一个独立的软件单元,它包含 模型, 视图, 控制器和其他支持的组件。在许多方面上,模块看起来像一个应用。主要的区别就是模块不能单独部署,它必须存在于一个应用里。用户可以像他们访问普通应用的控制器那样访问模块中的控制器。
模块在一些场景里很有用。对大型应用来说,我们可能需要把它划分为几个模块,每个模块可以单独维护和部署。一些通用的功能,例如用户管理,评论管理,可以以模块的形式开发,这样他们就可以容易地在以后的项目中被复用。

1、创建模块

模块组织在一个目录中,目录名即为模块的唯一ID。模块目录的结构跟 应用基础目录 很相似。下面列出了一个 fourm 的模块的典型的目录结构:

forum/                  模块文件夹
ForumModule.php         模块类文件
components/             包含可复用的用户组件
views/                  包含小物件的视图文件
controllers/            包含控制器类文件
DefaultController.php   默认的控制器类文件
extensions/             包含第三方扩展
models/                 包含模型类文件
views/                  包含控制器视图和布局文件
layouts/                包含布局文件
default/                包含 DefaultController 的视图文件
index.php               首页视图文件

模块必须有一个继承自 CWebModule 的模块类。类的名字通过表达式 ucfirst($id).'Module' 确定, 其中的 $id 代表模块的 ID (或者说模块的目录名字)。模块类是存储模块代码间可共享信息的中心位置。例如,我们可以使用 CWebModule::params存储模块参数,使用 CWebModule::components 分享模块级的应用组件。

2、使用模块

要使用模块,首先将模块目录放在 应用基础目录的modules文件夹中。然后在应用的modules属性中声明模块ID。例如,为了使用上面的forum模块,我们可以使用如下应用配置:

return array(
    ......
    'modules'=>array('forum',...),
    ......
);

模块也可以在配置时带有初始属性值。做法和配置 应用组件 很类似。例如, forum 模块可以在其模块类中有一个名为 postPerPage 的属性,它可以在 应用配置 中配置如下:

return array(
    ......
    'modules'=>array(
        'forum'=>array(
            'postPerPage'=>20,
        ),
    ),
    ......
);

模块的实例可通过当前活动控制器的 module 属性访问。在模块实例中,我们可以访问在模块级中共享的信息。例如,为访问上面的 postPerPage 信息,我们可使用如下表达式:

$postPerPage=Yii::app()->controller->module->postPerPage;
// 如如$this引用的是控制器实例,则可以使用下行语句
// $postPerPage=$this->module->postPerPage;

模块中的控制器动作可以通过路由“模块ID/控制器ID/动作ID”或“模块ID/存放控制器类文件的子目录名/控制器ID/动作ID”访问。例如,假设上面的 forum 模块有一个名为 PostController 的控制器,我们就可以通过路由 forum/post/create 访问此控制器中的 create 动作。此路由对应的 URL 即 http://www.example.com/index.php?r=forum/post/create

3、嵌套的模块

模块可以无限级嵌套。这就是说,一个模块可以包含另一个模块,而这另一个模块又可以包含其他模块。我们称前者为 父模块 ,后者为子模块。子模块必须定义在其父模块的 modules 属性中,就像我们前面在应用配置中定义模块一样。
要访问子模块中的控制器动作,我们应使用路由 父模块ID/子模块ID/控制器ID/动作ID。

九、路径别名

Yii 中广泛的使用了路径别名。路径别名关联于一个目录或文件的路径。它以点号语法指定,类似于广泛使用的名字空间(namespace)格式:
RootAlias.path.to.target
其中的 RootAlias 是某个现存目录的别名,通过调用 YiiBase::setPathOfAlias(), 我们可以定义新的路径别名。为方便起见,Yii 预定义了以下几个根别名:

system: 表示 Yii 框架目录;
zii:    表示 Zii 库 目录;
application: 表示应用的 基础目录;
webroot: 表示 入口脚本 文件所在的目录。
ext: 表示包含了所有第三方 扩展 的目录。

额外的,如果应用使用了 模块, (Yii) 也为每个模块ID定义了根别名,指向相应模块的跟目录。
通过使用 YiiBase::getPathOfAlias(), 别名可以被翻译为其相应的路径。
使用别名可以很方便的导入类的定义。例如,如果我们想包含 CController 类的定义,我们可以调用如下代码
Yii::import('system.web.CController');
import方法跟 include 和 require 不同,它更加高效。导入(import)的类定义并不会真正被包含进来,直到它第一次被引用。多次导入同样的名字空间也会比 include_once 和 require_once 快得多。
我们还可以使用如下语法导入整个目录,这样此目录下的类文件就会在需要时被自动包含。
Yii::import('system.web.*');

除 import 外, 别名还在其他许多地方指向类。例如,路径别名可以传递给 Yii::createComponent() 以创建相应类的实例。即使类文件在之前从未被包含。
不要将路径别名和名字空间混淆了,名字空间是指对一些类名的一个逻辑组合,这样它们就可以相互区分开,即使有相同的名字。而路径别名是用于指向一个类文件或目录。路径别名与名字空间并不冲突。

十、开发规范

下面我们讲解 Yii 编程中推荐的开发规范。为简单起见,我们假设 WebRoot 是 Yii 应用安装的目录。

1、URL

默认情况下,Yii 识别如下格式的 URL:
http://hostname/index.php?r=ControllerID/ActionID
r变量意为 路由(route) ,它可以被Yii解析为 控制器和动作。如果 ActionID 被省略,控制器将使用默认的动作(在CController::defaultAction中定义);如果 ControllerID 也被省略(或者 r 变量不存在),应用将使用默认的控制器(在CWebApplication::defaultController中定义)。
通过 CUrlManager 的帮助,可以创建更加可识别,更加 SEO 友好的 URL,例如 http://hostname/ControllerID/ActionID.html

2、代码

Yii 推荐命名变量、函数和类时使用驼峰风格,即每个单词的首字母大写并连在一起,中间无空格。变量名和函数名应该使它们的第一个单词全部小写,以使其区别于类名。对私有类成员变量来说,我们推荐以下划线作为其名字前缀(例如: $_actionList)。
一个针对控制器类名的特殊规则是它们必须以单词 Controller 结尾。那么控制器ID就是类名的首字母小写并去掉单词Controller。例如,PageController类的ID就是 page。这个规则使应用更加安全。它还使控制器相关的URL更加简单(例如/index.php?r=page/index 而不是/index.php?r=PageController/index)

3、配置

配置是一个键值对数组。每个键代表了所配置的对象中的属性名,每个值则为相应属性的初始值。
类中任何可写的属性都可以被配置。如果没有配置,属性将使用它们的默认值。当配置一个属性时,最好阅读相应文档以保证初始值正确。

4、文件

命名和使用文件的规范取决于它们的类型。
类文件应以它们包含的公有类命名。例如,CController 类位于 CController.php 文件中。公有类是可以被任何其他类使用的类。每个类文件应包含最多一个公有类。私有类(只能被一个公有类使用的类)可以放在使用此类的公有类所在的文件中。
视图文件应以视图的名字命名。例如, index 视图位于 index.php 文件中。视图文件是一个PHP脚本文件,它包含了用于呈现内容的HTML和PHP代码。
配置文件可以任意命名。配置文件是一个PHP脚本,它的主要目的是返回一个体现配置的关联数组。

5、目录

Yii 假定了一系列默认的目录用于不同的场合。如果需要,每个目录都可以自定义。
WebRoot/protected: 这是 应用基础目录,是放置所有安全敏感的PHP脚本和数据文件的地方。Yii 有一个默认的 application 别名指向此目录。此目录及目录中的文件应该保护起来防止Web用户访问。它可以通过 CWebApplication::basePath自定义。

WebRoot/protected/runtime: 此目录放置应用在运行时产生的私有临时文件。
                           此目录必须对 Web 服务器进程可写。
                           它可以通过 CApplication::runtimePath自定义。
WebRoot/protected/extensions: 此目录放置所有第三方扩展。
                              它可以通过 CApplication::extensionPath 自定义。
WebRoot/protected/modules: 此目录放置所有的应用 模块,每个模块使用一个子目录。
WebRoot/protected/controllers: 此目录放置所有控制器类文件。
                               它可以通过 CWebApplication::controllerPath 自定义。
WebRoot/protected/views: 此目录放置所有试图文件,包含控制器视图,布局视图和系统视图。
                         它可以通过 CWebApplication::viewPath 自定义。
WebRoot/protected/views/ControllerID: 此目录放置单个控制器类中使用的视图文件。
                                      此处的 ControllerID 是指控制器的ID 。
                                      它可以通过 CController::viewPath 自定义。
WebRoot/protected/views/layouts: 此目录放置所有布局视图文件。
                                 它可以通过 CWebApplication::layoutPath 自定义。
WebRoot/protected/views/system: 此目录放置所有系统视图文件。系统视图文件是用于显示异常和错误的模板。
                                它可以通过CWebApplication::systemViewPath自定义。
WebRoot/assets: 此目录放置公共资源文件。资源文件是可以被发布的,可由Web用户访问的私有文件。
                此目录必须对 Web 服务器进程可写。它可以通过 CAssetManager::basePath 自定义
WebRoot/themes: 此目录放置应用使用的不同的主题。每个子目录即一个主题,主题的名字即目录的名字。
                它可以通过 CThemeManager::basePath 自定义。

6、数据库

多数Web 应用是由数据库驱动的。我们推荐在对表和列命名时使用如下命名规范。注意,这些规范并不是 Yii 所必须的。
㈠数据库表名和列名都使用小写命名。
㈡名字中的单词应使用下划线分割 (例如 product_order)。
㈢对于表名,你既可以使用单数也可以使用复数。但不要 同时使用两者。为简单起见,我们推荐使用单数名字。
㈣表名可以使用一个通用前缀,例如 tbl_ 。这样当应用所使用的表和另一个应用说使用的表共存于同一个数据库中时就特别有用。这两个应用的表可以通过使用不同的表前缀很容易地区别开。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,600评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,029评论 4 62
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,869评论 6 13
  • 在开发中扩展Yii是一个很常见的行为.例如,当你写一个新的控制器时,你通过继承 CController 类扩展了...
    layjoy阅读 374评论 0 1
  • Objective 你对今天学的记得什么? 一个很有意思的研究是大类资产配置,以美林投资时钟为基础。美林投资时钟在...
    甜甜的大橙子阅读 255评论 0 0