CHtml::link("Hello",array('message/helloWorld')); Project::model()->findbyPk("");
rules()方法返回的是一个规则数组,一般每一个规则格式如下所示:
Array('Attribute List', 'Validator', 'on'=>'Scenario List', …additional options);
如果这里没有设置,该规则将适用于调用save()方法的所有情景。最后,additional options(附加选项)是name/value(键值对)出现的用来初始化validator(验证器)的属性。
validator(验证器)可以是模型类中的一个方法或一个单独的验证器类。如果定义为模型类中的方法,它的格式必须是如下的形式:
/** * @param string the name of the attribute to be validated * @param array options specified in the validation rule */ public function ValidatorName($attribute,$params) { ... }
如果我们使用一个validator(验证器)类,则这个类必须继承CValidator。其实有三种方法可以指定validator(验证器),包括前面提到的一种格式:
- 第一种是在模型类中定义验证方法
- 第二种是指定一个单独的验证器类(这个类继承CValidator)。
- 第三种是你可以使用Yii框架中现有的验证器,指定预定义的验证器别名即可。
Yii为你提供了很多预定义的验证器类,同时也指定了别名,用在定义规则时。Yii1.1版本,预定义的验证器别名的完整列表如下:
- boolean:它是CBooleanValidator类的别名,验证属性的值是布尔值(true或false)。
- captcha:它是CCaptchaValidator类的别名,验证属性的值等于一个显示的CAPTCHA(验证码)的值。
- compare:它是CCompareValidator类的别名,验证属性的值与另一个属性的值相等。
- email:它是CEmailValidator类的别名,验证属性的值为有一个有效的Email地址。
- default:它是CDefaultValidator类的别名,验证属性的值为分配的默认值。
- exist:它是CExistValidator类的别名,验证属性的值在表中的对应列中存在。
- file:它是CFileValidator类的别名,验证属性的值包含上传的文件。
- filter:它是CFilterValidator类的别名,用过滤器转换属性的值。
- in:它是CRangeValidator类的别名,验证属性值在一个预定义列表中。
- length:它是CStringValidator类的别名,验证属性值的长度在一个范围内。
- match:它是CRegularExpressionValidator类的别名,验证属性值匹配一个正则表达式。
- numerical:它是CNumberValidator类的别名,验证属性值是数字。
- required:它是CRequiredValidator类的别名,验证属性值必需有值,不能为空。
- type:它是CTypedValidator类的别名,验证属性值是一个指定的数据类型。
- unique:它是CUniquedValidator类的别名,验证属性值在表中的对应列中是唯一的。
- url:它是CUrlValidator类的别名,验证属性值是一个有效的URL。
public function search() { // Warning: Please modify the following code to remove attributes that // should not be searched. $criteria = new CDbCriteria; $criteria->compare('id', $this->id); $criteria->compare('name', $this->name, true); --------->代表是否模糊查询 $criteria->compare('description', $this->description, true); $criteria->compare('project_id', $this->project_id); $criteria->compare('type_id', $this->type_id); $criteria->compare('status_id', $this->status_id); $criteria->compare('owner_id', $this->owner_id); $criteria->compare('requester_id', $this->requester_id); $criteria->compare('create_time', $this->create_time, true); $criteria->compare('create_user_id', $this->create_user_id); $criteria->compare('update_time', $this->update_time, true); $criteria->compare('update_user_id', $this->update_user_id); return new CActiveDataProvider(get_class($this), array( 'criteria' => $criteria, )); }
safe属性解释:
As we have explicitly added the $password_repeat attribute to the User AR class,
and it is not a column in the underlying database table, we need to also tell the
model class to allow this field to be set in a bulk manner when the setAttributes()
method is called. We do this by explicitly adding our new attribute to the safe
attributes list for our User model class. To do this, add the following to the
User::rules() array:
array('password_repeat', 'safe'),
To explain this in a little more detail. When our form is submitted back to the
UserController::actionCreate() method, it uses the following code to set
the User model class attributes in a bulk manner:
$model->attributes=$_POST['User'];
What happens here is that for every key in the $_POST['User'] array that matches
the name of a safe attribute in the $model class, that class attribute's value is set to the
corresponding value in the array. By default, for a CActiveRecord model class, all
underlying database columns, except the Primary Key, are considered safe. As our
new $password_repeat is not a column of tbl_user, we need to explicitly add it
to this list of safe attributes.
echo $form->dropDownList($model,'type_id', $model- >getTypeOptions());
添加一个过滤器
现在,让我们添加一个过滤器到IssueController类中,来处理有效的项目(Project)。现在先使用最简单的方法,添加一个以filter开头的方法到类里。因为这个方法的调用是Yii框架自动执行的,所以,我们很难使用先行测试的流程来实现这个方法。在这个案例里面,我们会稍微打破一下惯例,添加个方法之前,我们不会写测试。
打开proteced/controllers/IssueController.php并且添加下面的方法到类的底部:
PHP代码:
public function filterProjectContext($filterChain)
{
$filterChain->run();
}
好了,现在我们已经定义了一个过滤器,但是却并没有做太多事情。它只是执行了$filterChain->run(),这个操作将继续进行过滤处理,并允许执行使用了这个过滤器的操作方法。这就带来了另一个问题:我们怎样定义指定的操作方法使用这个过滤器?
2
指定过滤动作
如果我们要指定在哪个动作方法中,应该应用过滤器,需要重载Yii框架中控制器的基类CController的方法filters()。事实上,这个方法已经在IssueController类中被重载了。是在我们使用Gii工具自动生成这个类的时候,就已经完成了。它已经帮我们添加了一个简单的访问控制过滤器accessControl,这个方法在CController基类中已经被定义过了,用来处理一些基本的验证以保证用户有足够的权限来执行特定的动作。我们将会在下一章中涉及到用户验证和鉴权。现在,我们只需要把这个过滤器添加到过滤器配置数组。为了让我们的新过滤器应用到创建动作,添加如下高亮处代码到IssueController::filters()方法中:
PHP代码:
/**
* @return array action filters
*/
public function filters()
{
return array(
'accessControl', //perform access control for CRUD operations
'projectContext + create', //check to ensure valid project context
);
}
filters()方法会返回一个包含了过滤器配置的数组。前面的方法返回了一个配置,指定了projectContext过滤器,该过滤器是在类中定义的方法,应用到actionCreate()上。这个配置的语法,允许“+”号和“-”号,用来指定是否要应用到一个方法上。例如,如果我们决定要将这个过滤器应用到除了actionUpdate()和actionView()之外的所有动作上,我们可以这样写:
PHP代码:
return array(
'projectContext - update, view' ,
);
你不能同时使用加号和减号。在任何给出的过滤器配置中,只能使用一个。加号操作符意味着“只在下列动作中使用过滤器”。减号则意味着“在除了下列动作之外的所有动作中应用过滤器”。如果既不使用‘+’,也不使用‘-’,那么过滤器会被应用到所有的动作中。
此时,我们将只限制创建动作。所以,先前用 + create来配置过滤器,我们的过滤器方法将在任何用户试图创建一个问题(Issue)时候被调用。
project中的relations
public function relations() { // NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array( 'issues' => array(self::HAS_MANY, 'Issue', 'project_id'), 'users' => array(self::MANY_MANY, 'User', 'tbl_project_user_assignment(project_id, user_id)'), ); }
public function getUserOptions() { $usersArray = CHtml::listData($this->users, 'id', 'username'); return $usersArray; }
有2个相关访问控制实现方法在这个文件中,ProjectController:filters()和ProjectController::accessRules()。第一个方法的代码如下:
/** * @return array action filters */ public function filters() { return array( 'accessControl', // perform access control for CRUD operations ); }
下面是第二个方法的代码:
/** *Specifies the access control rules. *This method is used by the 'accessControl' filter. *@return array access control rules */ public function accessRules() { return array( array('allow', // allow all users to perform 'index' and'view' actions 'actions'=>array('index','view'), 'users'=>array('*'), ), array('allow', // allow authenticated user to perform 'create' and 'update' actions 'actions'=>array('create','update'), 'users'=>array('@'), ), array('allow', // allow admin user to perform 'admin' and 'delete' actions 'actions'=>array('admin','delete'), 'users'=>array('admin'), ), array('deny', // deny all users 'users'=>array('*'), ), ); }
它拒绝了所有用户执行所有控制器的的所有action。
定义访问规则的时候可以使用一些 context parameters(内容参数)。前面提到的规则定义了行为和用户来组成规则的内容,下面是一个完整的参数列表:
- Controllers(控制器):这条规则指定了一个包含多个控制器ID的数组,来指明哪些规则需要被应用。
- Roles(角色):这条规则指定了一个将被规则使用的授权列表(包括角色,操作,权限等)。这些是为RBAC的一些功能服务的,我们将在下一个部分进行讨论。
- Ips(IP地址):这条规则指定了一组可以被施加到规则的客户端IP地址。
- Verbs(提交类型):这条规则制定了可以被施加到规则的HTTP请求类型。
- Expression(表达式):这个规则指定了一个PHP表达式,这个表达式的值被用来决定这个规则是否应该被使用。
- Actions(行为):这个规则指定了需要被规则匹配的对应action ID(行为ID)的方法。
- Users(用户):这个规则指定了应该被施加规则的用户。登录当前项目的用户名作为被匹配项。3个特殊字符可以被使用:
- *:任何用户
- ?:匿名用户
- @:登录用户/认证用户
$sql = "INSERT INTO tbl_project_user_assignment (project_id, user_id) VALUES (:projectId, :userId)"; $command = Yii::app()->db->createCommand($sql); $command->bindValue(":projectId", $this->id, PDO::PARAM_INT); $command->bindValue(":userId", $user->id, PDO::PARAM_INT); return $command->execute();
public function rules() { return array( // username and password are required array('username, role', 'required'), // password needs to be authenticated //array('username', 'verify'), array('username', 'exist', 'className'=>'User'), array('username', 'verify'), ); } /** * Authenticates the existence of the user in the system. * If valid, it will also make the association between the user, * role and project * This is the 'verify' validator as declared in rules(). */ public function verify($attribute,$params) { if(!$this->hasErrors()) // we only want to authenticate when no other input errors are present { $user = User::model()->findByAttributes(array('username'=> $this->username)); if($this->project->isUserInProject($user)) { $this->addError('username','This user has already been added to the project.'); } else { $this->project->associateUserToProject($user); $this->project->associateUserToRole($this->role, $user->id); $auth = Yii::app()->authManager; $bizRule='return isset($params["project"]) && $params["project"]->isUserInRole("'.$this->role.'");'; $auth->assign($this->role,$user->id, $bizRule); } } }
$users = User::model()->findAll(); $usernames=array(); foreach($users as $user) { $usernames[]=$user->username; } $form->project = $project; $this->render('adduser',array('model'=>$form, 'usernames'=>$usernames));
$this->menu=array( array('label'=>'List Project', 'url'=>array('index')), array('label'=>'Create Project', 'url'=>array('create')), array('label'=>'Update Project', 'url'=>array('update', 'id'=>$model->id)), array('label'=>'Delete Project', 'url'=>'#', 'linkOptions'=>array( 'submit'=>array('delete','id'=>$model->id), 'confirm'=>'Are you sure you want to delete this item?' ) ), array('label'=>'Manage Project', 'url'=>array('admin')), array('label'=>'Create Issue', 'url'=>array('issue/create', 'pid'=>$model->id)), ); if(Yii::app()->user->checkAccess('createUser',array('project'=>$mod el))) { $this->menu[] = array( 'label'=>'Add User To Project', 'url'=>array('adduser', 'id'=>$model->id) ); }
Yii中导入类名找不到的问题可能是:
include_path的设置
第一种方法:
修改php.ini文件中的include_path项。
include_path = .:/ usr / local / lib / php :./ include
第二个方法:
使用ini_set方法。
ini_set("include_path", ".:../:./include:../include");
3.注意
zendframework include 设置 index.php
set_include_path('.' .PATH_SEPARATOR.'../library/'.PATH_SEPARATOR.'./application/models/'.PATH_SEPARATOR.'./application/lib/' .PATH_SEPARATOR.get_include_path());
PATH_SEPARATOR是一个常量,在Linux系统中是一个" : "号,Windows上是一个";"号。
所以编写程序时最好用常量 PATH_SEPARATOR 代替,否则如果系统从linux移植到win系统或反过来移植会出错!
get_include_path取得当前已有的环境变量,加上前面的设置就是新的系统include
下面要把这两个属性加到rules里,作为safe方法,要不model不会把这两个属性赋值