- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章PHP的Yii框架中Model模型的学习教程由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
模型是 MVC 模式中的一部分, 是代表业务数据、规则和逻辑的对象.
模型是 CModel 或其子类的实例。模型用于保持数据以及与其相关的业务逻辑.
模型是单独的数据对象。它可以是数据表中的一行,或者一个用户输入的表单。 数据对象的每个字段对应模型中的一个属性。每个属性有一个标签(label), 并且可以通过一系列规则进行验证.
Yii 实现了两种类型的模型:表单模型和 Active Record。二者均继承于相同的基类 CModel.
表单模型是 CFormModel 的实例。表单模型用于保持从用户的输入获取的数据。 这些数据经常被获取,使用,然后丢弃。例如,在一个登录页面中, 我们可以使用表单模型用于表示由最终用户提供的用户名和密码信息.
Active Record (AR) 是一种用于通过面向对象的风格抽象化数据库访问的设计模式。 每个 AR 对象是一个 CActiveRecord 或其子类的实例。代表数据表中的一行。 行中的字段对应 AR 对象中的属性.
可通过继承 yii\base\Model 或它的子类定义模型类,基类yii\base\Model支持许多实用的特性:
属性 。
模型通过 属性 来代表业务数据,每个属性像是模型的公有可访问属性, yii\base\Model::attributes() 指定模型所拥有的属性.
可像访问一个对象属性一样访问模型的属性
1
2
3
4
5
|
$model
=
new
\app\models\ContactForm;
// "name" 是ContactForm模型的属性
$model
->name =
'example'
;
echo
$model
->name;
|
也可像访问数组单元项一样访问属性,这要感谢yii\base\Model支持 ArrayAccess 数组访问 和 ArrayIterator 数组迭代器
1
2
3
4
5
6
7
8
9
10
|
$model
=
new
\app\models\ContactForm;
// 像访问数组单元项一样访问属性
$model
[
'name'
] =
'example'
;
echo
$model
[
'name'
];
// 迭代器遍历模型
foreach
(
$model
as
$name
=>
$value
) {
echo
"$name: $value\n"
;
}
|
定义属性 。
默认情况下你的模型类直接从yii\base\Model继承,所有 non-static public非静态公有 成员变量都是属性。 例如,下述ContactForm模型类有四个属性name, email, subject and body, ContactForm 模型用来代表从HTML表单获取的输入数据.
1
2
3
4
5
6
7
8
9
10
11
|
namespace
app\models;
use
yii\base\Model;
class
ContactForm
extends
Model
{
public
$name
;
public
$email
;
public
$subject
;
public
$body
;
}
|
另一种方式是可覆盖 yii\base\Model::attributes() 来定义属性,该方法返回模型的属性名。 例如 yii\db\ActiveRecord 返回对应数据表列名作为它的属性名, 注意可能需要覆盖魔术方法如__get(), __set()使属性像普通对象属性被访问.
属性标签 。
当属性显示或获取输入时,经常要显示属性相关标签,例如假定一个属性名为firstName, 在某些地方如表单输入或错误信息处,你可能想显示对终端用户来说更友好的 First Name 标签.
可以调用 yii\base\Model::getAttributeLabel() 获取属性的标签,例如:
1
2
3
4
|
$model
=
new
\app\models\ContactForm;
// 显示为 "Name"
echo
$model
->getAttributeLabel(
'name'
);
|
默认情况下,属性标签通过yii\base\Model::generateAttributeLabel()方法自动从属性名生成. 它会自动将驼峰式大小写变量名转换为多个首字母大写的单词,例如 username 转换为 Username, firstName 转换为 First Name.
如果你不想用自动生成的标签,可以覆盖 yii\base\Model::attributeLabels() 方法明确指定属性标签,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
namespace
app\models;
use
yii\base\Model;
class
ContactForm
extends
Model
{
public
$name
;
public
$email
;
public
$subject
;
public
$body
;
public
function
attributeLabels()
{
return
[
'name'
=>
'Your name'
,
'email'
=>
'Your email address'
,
'subject'
=>
'Subject'
,
'body'
=>
'Content'
,
];
}
}
|
应用支持多语言的情况下,可翻译属性标签, 可在 yii\base\Model::attributeLabels() 方法中定义,如下所示
1
2
3
4
5
6
7
8
9
|
public
function
attributeLabels()
{
return
[
'name'
=> \Yii::t(
'app'
,
'Your name'
),
'email'
=> \Yii::t(
'app'
,
'Your email address'
),
'subject'
=> \Yii::t(
'app'
,
'Subject'
),
'body'
=> \Yii::t(
'app'
,
'Content'
),
];
}
|
甚至可以根据条件定义标签,例如通过使用模型的 scenario场景, 可对相同的属性返回不同的标签.
补充:属性标签是 视图一部分,但是在模型中申明标签通常非常方便,并可行程非常简洁可重用代码。 场景 。
模型可能在多个 场景 下使用,例如 User 模块可能会在收集用户登录输入,也可能会在用户注册时使用。 在不同的场景下,模型可能会使用不同的业务规则和逻辑,例如 email 属性在注册时强制要求有,但在登陆时不需要.
模型使用 yii\base\Model::scenario 属性保持使用场景的跟踪, 默认情况下,模型支持一个名为 default 的场景,如下展示两种设置场景的方法
1
2
3
4
5
6
|
// 场景作为属性来设置
$model
=
new
User;
$model
->scenario =
'login'
;
// 场景通过构造初始化配置来设置
$model
=
new
User([
'scenario'
=>
'login'
]);
|
默认情况下,模型支持的场景由模型中申明的 验证规则 来决定, 但你可以通过覆盖yii\base\Model::scenarios()方法来自定义行为,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
namespace
app\models;
use
yii\db\ActiveRecord;
class
User
extends
ActiveRecord
{
public
function
scenarios()
{
return
[
'login'
=> [
'username'
,
'password'
],
'register'
=> [
'username'
,
'email'
,
'password'
],
];
}
}
|
补充:在上述和下述的例子中,模型类都是继承yii\db\ActiveRecord, 因为多场景的使用通常发生在Active Record 类中. scenarios() 方法返回一个数组,数组的键为场景名,值为对应的 active attributes活动属性。 活动属性可被 块赋值 并遵循验证规则在上述例子中,username 和 password 在login场景中启用,在 register 场景中, 除了 username and password 外 email也被启用.
scenarios() 方法默认实现会返回所有yii\base\Model::rules()方法申明的验证规则中的场景, 当覆盖scenarios()时,如果你想在默认场景外使用新场景,可以编写类似如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
namespace
app\models;
use
yii\db\ActiveRecord;
class
User
extends
ActiveRecord
{
public
function
scenarios()
{
$scenarios
= parent::scenarios();
$scenarios
[
'login'
] = [
'username'
,
'password'
];
$scenarios
[
'register'
] = [
'username'
,
'email'
,
'password'
];
return
$scenarios
;
}
}
|
场景特性主要在验证 和 属性块赋值 中使用。 你也可以用于其他目的,例如可基于不同的场景定义不同的 属性标签.
验证规则 。
当模型接收到终端用户输入的数据,数据应当满足某种规则(称为 验证规则, 也称为 业务规则)。 例如假定ContactForm模型,你可能想确保所有属性不为空且 email 属性包含一个有效的邮箱地址, 如果某个属性的值不满足对应的业务规则,相应的错误信息应显示,以帮助用户修正错误.
可调用 yii\base\Model::validate() 来验证接收到的数据, 该方法使用yii\base\Model::rules()申明的验证规则来验证每个相关属性, 如果没有找到错误,会返回 true,否则它会将错误保存在 yii\base\Model::errors 属性中并返回false,例如:
1
2
3
4
5
6
7
8
9
10
11
|
$model
=
new
\app\models\ContactForm;
// 用户输入数据赋值到模型属性
$model
->attributes = \Yii::
$app
->request->post(
'ContactForm'
);
if
(
$model
->validate()) {
// 所有输入数据都有效 all inputs are valid
}
else
{
// 验证失败:$errors 是一个包含错误信息的数组
$errors
=
$model
->errors;
}
|
通过覆盖 yii\base\Model::rules() 方法指定模型属性应该满足的规则来申明模型相关验证规则。 下述例子显示ContactForm模型申明的验证规则
1
2
3
4
5
6
7
8
9
10
|
public
function
rules()
{
return
[
// name, email, subject 和 body 属性必须有值
[[
'name'
,
'email'
,
'subject'
,
'body'
],
'required'
],
// email 属性必须是一个有效的电子邮箱地址
[
'email'
,
'email'
],
];
}
|
一条规则可用来验证一个或多个属性,一个属性可对应一条或多条规则。 更多关于如何申明验证规则的详情请参考 验证输入 一节. 。
有时你想一条规则只在某个 场景 下应用,为此你可以指定规则的 on 属性,如下所示
1
2
3
4
5
6
7
8
9
10
|
public
function
rules()
{
return
[
// 在"register" 场景下 username, email 和 password 必须有值
[[
'username'
,
'email'
,
'password'
],
'required'
,
'on'
=>
'register'
],
// 在 "login" 场景下 username 和 password 必须有值
[[
'username'
,
'password'
],
'required'
,
'on'
=>
'login'
],
];
}
|
如果没有指定 on 属性,规则会在所有场景下应用, 在当前yii\base\Model::scenario 下应用的规则称之为 active rule活动规则.
一个属性只会属于scenarios()中定义的活动属性且在rules()申明对应一条或多条活动规则的情况下被验证.
块赋值 。
块赋值只用一行代码将用户所有输入填充到一个模型,非常方便, 它直接将输入数据对应填充到 yii\base\Model::attributes 属性。 以下两段代码效果是相同的,都是将终端用户输入的表单数据赋值到 ContactForm 模型的属性, 明显地前一段块赋值的代码比后一段代码简洁且不易出错.
1
2
3
4
5
6
7
8
|
$model
=
new
\app\models\ContactForm;
$model
->attributes = \Yii::
$app
->request->post(
'ContactForm'
);
$model
=
new
\app\models\ContactForm;
$data
= \Yii::
$app
->request->post(
'ContactForm'
, []);
$model
->name = isset(
$data
[
'name'
]) ?
$data
[
'name'
] : null;
$model
->email = isset(
$data
[
'email'
]) ?
$data
[
'email'
] : null;
$model
->subject = isset(
$data
[
'subject'
]) ?
$data
[
'subject'
] : null;
$model
->body = isset(
$data
[
'body'
]) ?
$data
[
'body'
] : null;
|
安全属性 。
块赋值只应用在模型当前yii\base\Model::scenario场景yii\base\Model::scenarios()方法 列出的称之为 安全属性 的属性上,例如,如果User模型申明以下场景, 当当前场景为login时候,只有username and password 可被块赋值,其他属性不会被赋值.
1
2
3
4
5
6
7
|
public
function
scenarios()
{
return
[
'login'
=> [
'username'
,
'password'
],
'register'
=> [
'username'
,
'email'
,
'password'
],
];
}
|
补充: 块赋值只应用在安全属性上,因为你想控制哪些属性会被终端用户输入数据所修改, 例如,如果 User 模型有一个permission属性对应用户的权限, 你可能只想让这个属性在后台界面被管理员修改。 由于默认yii\base\Model::scenarios()的实现会返回yii\base\Model::rules()所有属性和数据, 如果不覆盖这个方法,表示所有只要出现在活动验证规则中的属性都是安全的.
为此,提供一个特别的别名为 safe 的验证器来申明哪些属性是安全的不需要被验证, 如下示例的规则申明 title 和 description都为安全属性.
1
2
3
4
5
6
|
public
function
rules()
{
return
[
[[
'title'
,
'description'
],
'safe'
],
];
}
|
非安全属性 。
如上所述,yii\base\Model::scenarios() 方法提供两个用处:定义哪些属性应被验证,定义哪些属性安全。 在某些情况下,你可能想验证一个属性但不想让他是安全的,可在scenarios()方法中属性名加一个惊叹号 !。 例如像如下的secret属性.
1
2
3
4
5
6
|
public
function
scenarios()
{
return
[
'login'
=> [
'username'
,
'password'
,
'!secret'
],
];
}
|
当模型在 login 场景下,三个属性都会被验证,但只有 username和 password 属性会被块赋值, 要对secret属性赋值,必须像如下例子明确对它赋值.
1
|
$model
->secret =
$secret
;
|
数据导出 。
模型通常要导出成不同格式,例如,你可能想将模型的一个集合转成JSON或Excel格式, 导出过程可分解为两个步骤,第一步,模型转换成数组;第二步,数组转换成所需要的格式。 你只需要关注第一步,因为第二步可被通用的数据转换器如yii\web\JsonResponseFormatter来完成.
将模型转换为数组最简单的方式是使用 yii\base\Model::attributes 属性,例如:
1
2
|
$post
= \app\models\Post::findOne(100);
$array
=
$post
->attributes;
|
yii\base\Model::attributes 属性会返回 所有 yii\base\Model::attributes() 申明的属性的值.
更灵活和强大的将模型转换为数组的方式是使用 yii\base\Model::toArray() 方法, 它的行为默认和 yii\base\Model::attributes 相同, 但是它允许你选择哪些称之为字段的数据项放入到结果数组中并同时被格式化。 实际上,它是导出模型到 RESTful 网页服务开发的默认方法,详情请参阅响应格式. 。
字段 。
字段是模型通过调用yii\base\Model::toArray()生成的数组的单元名.
默认情况下,字段名对应属性名,但是你可以通过覆盖 yii\base\Model::fields() 和/或 yii\base\Model::extraFields() 方法来改变这种行为, 两个方法都返回一个字段定义列表,fields() 方法定义的字段是默认字段,表示toArray()方法默认会返回这些字段。extraFields()方法定义额外可用字段,通过toArray()方法指定$expand参数来返回这些额外可用字段。 例如如下代码会返回fields()方法定义的所有字段和extraFields()方法定义的prettyName and fullAddress字段.
$array = $model->toArray([], ['prettyName', 'fullAddress']); 可通过覆盖 fields() 来增加、删除、重命名和重定义字段,fields() 方法返回值应为数组, 数组的键为字段名,数组的值为对应的可为属性名或匿名函数返回的字段定义对应的值。 特使情况下,如果字段名和属性定义名相同,可以省略数组键,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
// 明确列出每个字段,特别用于你想确保数据表或模型属性改变不会导致你的字段改变(保证后端的API兼容).
public
function
fields()
{
return
[
// 字段名和属性名相同
'id'
,
// 字段名为 "email",对应属性名为 "email_address"
'email'
=>
'email_address'
,
// 字段名为 "name", 值通过PHP代码返回
'name'
=>
function
() {
return
$this
->first_name .
' '
.
$this
->last_name;
},
];
}
// 过滤掉一些字段,特别用于你想继承父类实现并不想用一些敏感字段
public
function
fields()
{
$fields
= parent::fields();
// 去掉一些包含敏感信息的字段
unset(
$fields
[
'auth_key'
],
$fields
[
'password_hash'
],
$fields
[
'password_reset_token'
]);
return
$fields
;
}
|
警告:由于模型的所有属性会被包含在导出数组,最好检查数据确保没包含敏感数据, 如果有敏感数据,应覆盖 fields() 方法过滤掉,在上述列子中,我们选择过滤掉 auth_key, password_hash and password_reset_token。 最佳实践 。
模型是代表业务数据、规则和逻辑的中心地方,通常在很多地方重用, 在一个设计良好的应用中,模型通常比控制器代码多.
归纳起来,模型:
在开发大型复杂系统时应经常考虑最后一条建议, 在这些系统中,模型会很大并在很多地方使用,因此会包含需要规则集和业务逻辑, 最后维护这些模型代码成为一个噩梦,因为一个简单修改会影响好多地方, 为确保模型好维护,最好使用以下策略:
定义可被多个 应用主体 或 模块 共享的模型基类集合。 这些模型类应包含通用的最小规则集合和逻辑。 在每个使用模型的 应用主体 或 模块中, 通过继承对应的模型基类来定义具体的模型类,具体模型类包含应用主体或模块指定的规则和逻辑。 例如,在高级应用模板,你可以定义一个模型基类common\models\Post, 然后在前台应用中,定义并使用一个继承common\models\Post的具体模型类frontend\models\Post, 在后台应用中可以类似地定义backend\models\Post。 通过这种策略,你清楚frontend\models\Post只对应前台应用,如果你修改它,就无需担忧修改会影响后台应用.
最后此篇关于PHP的Yii框架中Model模型的学习教程的文章就讲到这里了,如果你想了解更多关于PHP的Yii框架中Model模型的学习教程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
目前我的后端和前端都有 2 个 Yii 安装设置。但是在处理这个问题时,它会变得有点困惑,我想知道这是否以正确的方式完成。下面是如何设置我的文件夹结构的示例。 - backend - assets
如何禁用通知,我在 idex.php 中尝试但通知是回声,我如何禁用它。 在 php.ini 最佳答案 更新 public/index.php
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
'urlManager'=>array( 'urlFormat'=>'path', 'rules'=>array( '' => array('site/page/vie
从 Yii 到 Yii 2.0 这行代码怎么写: Yii::app()->getRequest()->getRestParams() ? 最佳答案 在我看来,相当于 Yii::app()->getRe
我想使用多个调用构建查询,但在使用此代码时出现错误 $command = Yii::app()->db->createCommand() ->select('*') ->from('{
Yii中我的模型规则函数中的以下代码 public function rules() { // NOTE: you should only define rules for those att
我正在开发一个带有主数据库和多个数据库的系统,每个客户端一次。当客户填写并提交包含所有必需详细信息的表单时,将创建客户数据库及其表。 我的问题:Yii 框架是否支持动态创建数据库和表?如果是这样,是否
我知道我可以在 Yii 中注册一个新的元标记并且我知道怎么做,但是我需要 替换我设置的默认标签,因为当我在一篇文章时,我想插入 元标记中文章的简短描述; 如何管理元标记? 最佳答案 如果您使用的是最新
我尝试仅在管理模块中加载 Yii Bootstrap 扩展,但它不起作用。我假设我需要预加载它或以某种方式启动它......谢谢! class AdminModule extends CWeb
我已经建立了新的 Yii2 项目。现在我想 reorganize folder structure在“public”和“app”两个文件夹中(实际上代表 protected 文件)。 框架中的所有代码
页面 Controller 访问规则: public function accessRules() { $isadmin = User::loadUser(
代理人: agent_id (primary key) 用户: f_id (foreign key) type 我以这种方式创建了关系 public function relations() {
大家好,感谢阅读。 我想知道如何将数字格式化为货币,或者只是在末尾附加 €。我在 yii 框架的管理页面上的 gridview 中工作。 我有这个,例如 'columns'=>array(
如何禁用 Yii 的内置身份验证? (/site/login ). 我正在使用扩展程序进行身份验证并且不想让内置登录保持打开状态 - 这可能是一个安全问题。 最佳答案 我认为您可以删除站点 Contr
使用 Yii,我想删除所有不是今天的行。 我的解决方案好吗? $query = "delete from `user_login_hash` where `day`!='".(date('Y-m-d'
gridview yii如何在一列数组值中显示两个关系值 在我的模型代码中有关系 $criteria->compare('exp.ExperienceYear',$this->Experience,
是他们对的任何常用方法吗?为我的 yii 项目添加扩展 ? 如何向我的 yii 添加扩展名 请解释 步骤 最佳答案 “ 应用程序配置 ”在安装扩展时起着重要作用。默认情况下,此配置将位于 php 文件
如何在 yii 中使用场景禁用文本字段?我有 3 类帐户 super 管理员、管理员和普通用户。所有 3 类用户都有权更新有关他们的信息,但其中一个字段 accountId 只能由 super 管理员
我在 yii 中找不到太多关于将默认范围应用于模型的文档,我想知道是否有人可以解释或指出我正确的方向。 我的问题的快速版本: 是否可以向默认范围添加关系,或者默认情况下向模型上的每个 AR 搜索添加“
我是一名优秀的程序员,十分优秀!