yii快速入门教程6、绝对适合初学 [ 技术分享 ]
Ⅱ、使用表单 在 Yii 中处理表单时,通常需要以下步骤:
- 创建用于表现所要收集数据字段的模型类。
- 创建一个控制器动作,响应表单提交。
- 在视图脚本中创建与控制器动作相关的表单。 一、创建模型 在编写表单所需的 HTML 代码之前,我们应该先确定来自最终用户输入的数据的类型,以及这些数据应符合什么样的规则。模型类可用于记录这些信息。正如模型章节所定义的,模型是保存用户输入和验证这些输入的中心位置。 取决于使用用户所输入数据的方式,我们可以创建两种类型的模型。如果用户输入被收集、使用然后丢弃,我们应该创建一个表单模型; 如果用户的输入被收集后要保存到数据库,我们应使用一个Active Record。两种类型的模型共享同样的基类 CModel ,它定义了表单所需的通用接口。 1、定义模型类 例如创建为一个表单模型:
class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
}
LoginForm 中定义了三个属性: $username, $password 和 $rememberMe。他们用于保存用户输入的用户名和密码,还有用户是否想记住他的登录的选项。由于 $rememberMe 有一个默认的值 false,相应的选项在初始化显示在登录表单中时将是未勾选状态。 我们将这些成员变量称为特性(attributes)而不是属性(properties),以区别于普通的属性(properties)。特性(attribute)是一个主要用于存储来自用户输入或数据库数据的属性(propertiy)。 2、声明验证规则 一旦用户提交了他的输入,模型被填充,我们就需要在使用前确保用户的输入是有效的。这是通过将用户的输入和一系列规则执行验证实现的。我们在 rules() 方法中指定这些验证规则,此方法应返回一个规则配置数组。
class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
private $_identity;
public function rules()
{
return array(
array('username, password', 'required'), //username 和 password 为必填项
array('rememberMe', 'boolean'), //rememberMe 应该是一个布尔值
array('password', 'authenticate'), //password 应被验证(authenticated)
);
}
public function authenticate($attribute,$params)
{
$this->_identity=new UserIdentity($this->username,$this->password);
if(!$this->_identity->authenticate())
$this->addError('password','错误的用户名或密码。');
}
}
rules() 返回的每个规则必须是以下格式:
array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...附加选项)
其中: AttributeList(特性列表)是需要通过此规则验证的特性列表字符串,每个特性名字由逗号分隔; Validator(验证器) 指定要执行验证的种类; on 参数是可选的,它指定此规则应被应用到的场景列表; 附加选项 是一个名值对数组,用于初始化相应验证器的属性值。
有三种方式可在验证规则中指定 Validator: 第一, Validator 可以是模型类中一个方法的名字,就像上面示例中的 authenticate 。验证方法必须是下面的结构:
/**
* @param string 所要验证的特性的名字
* @param array 验证规则中指定的选项
*/
public function 验证器名称($attribute,$params) { ... } 第二,Validator可以是一个验证器类的名字,当此规则被应用时,一个验证器类的实例将被创建以执行实际验证。规则中的附加选项用于初始化实例的属性值。验证器类必须继承自 CValidator。 第三,Validator 可以是一个预定义的验证器类的别名。在上面的例子中,required 名字是 CRequiredValidator 的别名,它用于确保所验证的特性值不为空。下面是预定义的验证器别名的完整列表: boolean: CBooleanValidator 的别名,确保特性有一个 CBooleanValidator::trueValue 或 CBooleanValidator::falseValue 值。 captcha: CCaptchaValidator 的别名,确保特性值等于 CAPTCHA 中显示的验证码。 compare: CCompareValidator 的别名,确保特性等于另一个特性或常量。 email: CEmailValidator 的别名,确保特性是一个有效的Email地址。 default: CDefaultValueValidator 的别名,指定特性的默认值。 exist: CExistValidator 的别名,确保特性值可以在指定表的列中可以找到。 file: CFileValidator 的别名,确保特性含有一个上传文件的名字。 filter: CFilterValidator 的别名,通过一个过滤器改变此特性。 in: CRangeValidator 的别名,确保数据在一个预先指定的值的范围之内。 length: CStringValidator 的别名,确保数据的长度在一个指定的范围之内。 match: CRegularExpressionValidator 的别名,确保数据可以匹配一个正则表达式。 numerical: CNumberValidator 的别名,确保数据是一个有效的数字。 required: CRequiredValidator 的别名,确保特性不为空。 type: CTypeValidator 的别名,确保特性是指定的数据类型。 unique: CUniqueValidator 的别名,确保数据在数据表的列中是唯一的。 url: CUrlValidator 的别名,确保数据是一个有效的 URL。
下面我们列出了几个只用这些预定义验证器的示例:
// 用户名为必填项
array('username', 'required'),
// 用户名必须在 3 到 12 个字符之间
array('username', 'length', 'min'=>3, 'max'=>12),
// 在注册场景中,密码password必须和password2一致。
array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
// 在登录场景中,密码必须接受验证。
array('password', 'authenticate', 'on'=>'login'),
3、安全的特性赋值 在一个类的实例被创建后,我们通常需要用最终用户提交的数据填充它的特性。这可以通过如下块赋值(massive assignment)方式轻松实现:
$model=new LoginForm;
if(isset($_POST['LoginForm']))
$model->attributes=$_POST['LoginForm'];
最后的表达式被称作 块赋值(massive assignment) ,它将 $_POST['LoginForm'] 中的每一项复制到相应的模型特性中。这相当于如下赋值方法:
foreach($_POST['LoginForm'] as $name=>$value)
{
if($name 是一个安全的特性)
$model->$name=$value;
}
检测特性的安全非常重要,例如,如果我们以为一个表的主键是安全的而暴露了它,那么攻击者可能就获得了一个修改记录的主键的机会,从而篡改未授权给他的内容。 特性如果出现在相应场景的一个验证规则中,即被认为是安全的。例如:
array('username, password', 'required', 'on'=>'login, register'),
array('email', 'required', 'on'=>'register'),
如上所示, username 和 password 特性在 login 场景中是必填项。而 username, password 和 email 特性在 register 场景中是必填项。于是,如果我们在 login 场景中执行块赋值,就只有 username 和 password 会被块赋值。因为只有它们出现在 login 的验证规则中。另一方面,如果场景是 register ,这三个特性就都可以被块赋值。
// 在登录场景中
$model=new User('login');
if(isset($_POST['User']))
$model->attributes=$_POST['User'];
// 在注册场景中
$model=new User('register');
if(isset($_POST['User']))
$model->attributes=$_POST['User'];
那么为什么我们使用这样一种策略来检测特性是否安全呢?背后的基本原理就是:如果一个特性已经有了一个或多个可检测有效性的验证规则,那我们还担心什么呢? 请记住,验证规则是用于检查用户输入的数据,而不是检查我们在代码中生成的数据(例如时间戳,自动产生的主键)。因此,不要为那些不接受最终用户输入的特性添加验证规则。 有时候,我们想声明一个特性是安全的,即使我们没有为它指定任何规则。例如,一篇文章的内容可以接受用户的任何输入。我们可以使用特殊的 safe 规则实现此目的:
array('content', 'safe')
还有一个用于声明一个属性为不安全的 unsafe 规则:
array('permission', 'unsafe')
unsafe 规则并不常用,它是我们之前定义的安全特性的一个例外。
共 1 条回复
-
返回的规则验证数组,如果是多个特性需要被同一个规则验证,那么这里的多个特性应该被写成一个索引数组的形式。
题主的第一个规则:public function rules() { return array( array('username, password', 'required'), //username 和 password 为必填项 array('rememberMe', 'boolean'), //rememberMe 应该是一个布尔值 array('password', 'authenticate'), //password 应被验证(authenticated) ); }
不应该是这种写法吗?
public function rules() { return array( array(array('username', 'password'), 'required'), //username 和 password 为必填项 array('rememberMe', 'boolean'), //rememberMe 应该是一个布尔值 array('password', 'authenticate'), //password 应被验证(authenticated) ); }
lz19881123 深圳
最后登录:2019-05-26
在线时长:7小时52分
- 粉丝37
- 金钱1030
- 威望0
- 积分1100