控制器文件命名使用大驼峰,控制器名后面需要加上Controller
类名与控制器命名相同
控制器的命名空间是app/controllers;
我们的类需要继承controller类 使用use引入yii\web\Controller;
类中的操作(方法)必须以action开头后面接上方法名,首字母大写
Yii没有路由 直接使用url访问,index.php后面接上?r=类名\方法名(类名不用加Controller和方法名不用加action 且都是用的小写)
可以定义路由别名,以改变默认的路由规则
//yii请求的处理流程: 入口脚本->应用主体->加载应用组件及模块->控制器
请求
$request=\YII::$app->request;
接值 $request->get(‘变量名’,默认值); $request->post(‘变量名’,默认值);
判断请求类型 $request->isGet $request->isPost
获取用户ip $request->userIp
响应
$response=\YII::$app->resopnse;
设置响应状态码:
$response->statusCode=’状态码’;
设置响应头:
新增 $response->headers->add(‘pragme’,’no-cache’);
修改 $response->headers->set(‘pragme’,’max-age=5’);
删除 $response->headers->remove(‘pragme’);
(跳转 文件下载)
Session
$session = \YII::$app->session;
查看session是否开启 $session->isActive
开启 $session->open()
关闭 $session->close()
存储 $session->set(‘name’,’值’) / $session[‘name’]=值
读取 $session->get(‘name’) / $session[‘name’]
检查session中是否存在某个值 $session->has('language') / isset($session['language']
删除某个值 $session->remove(‘name’) / unset($session[‘name’])
删除所有的值 $session->destroy()
flash session值只能被使用一次 使用完立即清除
增
$session->setFlash('postDeleted', 'You have successfully deleted your post.');
查
echo $session->getFlash('postDeleted');
判断是否存在
$result = $session->hasFlash('postDeleted');
当使用 session 组件访问 session 数据时候, 如果 session 没有开启会自动开启
当 session 数据为数组时,session 组件会限制你直接修改数据中的单元项
注意: 如下代码不会生效
$session['captcha']['number'] = 5;
$session['captcha']['lifetime'] = 3600;
应使用如下方式声明
$session['captcha'] = ['number' => 5,'lifetime' => 3600];
Cookie
$cookie = \YII::$app->response->cookies
增 $cookie->add(new \yii\web\Cookie(值)) 自动加密了
删 $cookie->remove(‘name’) / unset($cookies['language']);
$cookie = \YII::$app->request->cookies;
查 $cookie->getValue(‘user’,默认值) 第二个参数可选 如果不存在则返回默认值 / $cookies['language']
判断值是否存在 $cookies->has('language') / isset($cookies['language'])
Cookie设置可以配置加密 在config文件中进行配置
View层
在view下新建文件夹与控制器同名 (小写 不用加controller) 文件夹下在建立视图文件
Yii防止xss攻击
在视图中加上 <?php use yii\helpers\Html ?>
要使用数据的地方加上 <?=Html::encode(值) ?> 将特殊字符转义 <?=HtmlPurifier::process(值) ?> 将特殊字符剥离掉
Yii防止csrf攻击
在控制器中生成KaTeX parse error: Undefined control sequence: \Yii at position 11: csrfToken=\̲Y̲i̲i̲::app->request->csrftoken 在渲染试图的时候将这个值传到视图页面
在表单中加上一个hidden属性的input框 name为_csrf value为<?=$csrfToken?>
Yii防止sql注入
Sql语句中的参数写成:name 在传sql函数的后面加上第二个参数[‘:name’=>$name]
Gii的使用
Model生成器
命名空间+模块名 模块id默认与模块名一致
会默认生成一个controller文件夹和view文件夹以model文件
再次生成时controller和view文件并不会重新生成,不利于代码的解耦,可以在命名空间上多加个文件名,使其模块化
CURD生成器
命名空间+模块名 model必须存在 model的命名根据文件中的命名空间 不要看文件夹
View前面必须加@ 不然会生成错位置
会自动生成controller文件 view文件夹 文件夹下自动生成五个文件
Controller 生成器
From表单 生成器
必须要选择model层的地址 会根据model对应的表中的字段生成表单
模块 生成器
会在model层生成model文件 controller文件夹 view文件夹
Yii自定义组件
1 写好控制器和方法
2 在config文件下的main.php或者main-local.php文件中components
中注册
3 使用Yii::$app调用
1 写好控制器和方法
2 在config文件下的main.php或者main-local.php文件中components
中注册
3 使用Yii::->app调用
属性如果在方法里已经被赋值 同时又在注册组件时被赋值 那么注册组件时赋的值会将方法里赋的值覆盖掉
yii中事件的基本原理
分页四步走
1 先查询出要展示的数据
$userInfo = User::find();
2 实例化分页类 并传入相关参数
$pagination = new Pagination([
‘defaultPageSize’ => 1, //每页显示多少条
‘totalCount’ => $userInfo->count(), //总条数
]);
3 设置数据取值限制
$countries =
u
s
e
r
I
n
f
o
−
>
o
r
d
e
r
B
y
(
′
n
a
m
e
′
)
−
>
o
f
f
s
e
t
(
userInfo->orderBy('name') ->offset(
userInfo−>orderBy(′name′)−>offset(pagination->offset)
->limit($pagination->limit)
->all();
4 渲染视图
return $this->render(‘index’, [
‘countries’ => $countries,
‘pagination’ => $pagination,
]);
助手函数
User::className(); 获取命名空间及类名
to与toRoute的区别
to要求一个路由必须用数组来指定。 如果传的参数为字符串,它将会被直接当做 URL
echo \yii\helpers\Url::toRoute(‘site/index’); 生成从根目录开始的路由
echo \yii\helpers\Url::to([‘post/view’, ‘id’ => 100, ‘name’=>‘hhh’]); //生成带参数的路由
echo \yii\helpers\Url::to([‘post/view’, ‘id’ => 100, ‘#’ => ‘content’]); //带定位参数的路由
echo \yii\helpers\Url::to([‘post/index’], true); //生成绝对路径的路由
echo \yii\helpers\Url::to([‘post/index’], ‘https’); //生成https请求的路由
echo \yii\helpers\Url::toRoute([‘post/index’], ‘https’); //生成https请求的路由
echo \yii\helpers\Url::home(); //入口文件路由
echo \yii\helpers\Url::base(); //到web文件夹路由
echo \yii\helpers\Url::canonical(); //当前方法的路由
\yii\helpers\Url::remember(); 先记住当前请求的url 再获取
echo \yii\helpers\Url::previous();
请求
$request = Yii::$app->request;
// 返回所有参数
$params = $request->bodyParams;
// 返回参数 "id"
$param = $request->getBodyParam('id');
判断请求类型
$request->isAjax
$request->isGet
$request->isPost
$request->isPut
//获取请求的url参数
var_dump(Yii::$app->request->url); 不包括host info部分 /yii2/yii2-app-advanced/backend/web/index.php?r=user/user
var_dump(Yii::$app->request->absoluteUrl); host infode的整个URL http://127.0.0.1/yii2/yii2-app-advanced/backend/web/index.php?r=user/user
var_dump(Yii::$app->request->hostInfo); 只有host info部分 http://127.0.0.1
var_dump(Yii::$app->request->pathInfo); 入口脚本之后,问号之前(查询字符串)的部分 ''
var_dump(Yii::$app->request->queryString); 问号之后的部分 r=user/user
var_dump(Yii::$app->request->baseUrl); host info之后, 入口脚本之前的部分 /yii2/yii2-app-advanced/backend/web
var_dump(Yii::$app->request->scriptUrl); 没有path info和查询字符串部分 /yii2/yii2-app-advanced/backend/web/index.php
var_dump(Yii::$app->request->serverName); URL中的host name 127.0.0.1
var_dump(Yii::$app->request->serverPort); web服务中使用的端口 80
http头
$headers = Yii::$app->request->headers;
// 返回 Accept header 值
$accept = $headers->get('Accept');
//检测是否存在
$headers->has('User-Agent');
客户端信息
$userHost = Yii::$app->request->userHost;
$userIP = Yii::$app->request->userIP;
*/
响应
设置状态码
Yii::$app->response->statusCode = 200;
抛异常
throw new \yii\web\HttpException(402);
或
throw new
yii\web\BadRequestHttpException:状态码 400。
yii\web\ConflictHttpException:状态码 409。
yii\web\ForbiddenHttpException:状态码 403。
yii\web\GoneHttpException:状态码 410。
yii\web\MethodNotAllowedHttpException:状态码 405。
yii\web\NotAcceptableHttpException:状态码 406。
yii\web\NotFoundHttpException:状态码 404。
yii\web\ServerErrorHttpException:状态码 500。
yii\web\TooManyRequestsHttpException:状态码 429。
yii\web\UnauthorizedHttpException:状态码 401。
yii\web\UnsupportedMediaTypeHttpException:状态码 415。
http头
$headers = Yii::$app->response->headers;
// 增加一个 Pragma 头,已存在的Pragma 头不会被覆盖。
$headers->add('Pragma', 'no-cache');
// 设置一个Pragma 头. 任何已存在的Pragma 头都会被丢弃
$headers->set('Pragma', 'no-cache');
// 删除Pragma 头并返回删除的Pragma 头的值到数组
$values = $headers->remove('Pragma');
响应主体
Yii::$app->response->content = 'hello world!';
在发送给终端用户之前需要格式化,应设置 format 和 data 属性,format 属性指定data中数据格式化后的样式
$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON;
$response->data = ['message' => 'hello world'];
format的格式
HTML: 通过 yii\web\HtmlResponseFormatter来实现.
XML: 通过 yii\web\XmlResponseFormatter来实现.
JSON: 通过 yii\web\JsonResponseFormatter来实现.
JSONP: 通过 yii\web\JsonResponseFormatter来实现.
RAW: 直接发送响应不使用任何格式化
跳转
return $this->redirect('http://example.com/new', 301);
\Yii::$app->response->redirect('http://example.com/new', 301)->send(); 确保没有其他内容追加到响应中。
发送文件
yii\web\Response::sendFile():发送一个已存在的文件到客户端
yii\web\Response::sendContentAsFile():发送一个文本字符串作为文件到客户端
yii\web\Response::sendStreamAsFile():发送一个已存在的文件流作为文件到客户端
model层的操作
//数据库 yii支持SQLite,MySQL,PostregSQL,MSSQL 或 Oracle 数据库
//model的类名一般和表明相对应 如果不一致可以重写tableName()方法指定相应的表明
//AR操作的save()方法 可能插入或者更新表的记录,这取决于 Active Record 实例的状态。 如果实例通过 new 操作符实例化,调用 save() 方法将插入新记录; 如果实例是一个查询方法的结果,调用 save() 方法 将更新这个实例对应的表记录行。
//当你调用 save() 时,默认情况下会自动调用 validate()。 只有当验证通过时,它才会真正地保存数据; 否则将简单地返回false, 您可以检查 errors 属性来获取验证过程的错误消息。 如果你确定你的数据不需要验证, 你可以调用 save(false) 来跳过验证过程。
文件名与表名相同,首字母大写 命名空间 app\models
继承 yii\db\ActiveRecoord
查询数据
1
先写sql语句 $sql=~~where id = :id’’;
执行操作
r
e
s
u
l
t
=
类
名
:
:
f
i
n
d
B
y
S
q
l
(
result = 类名::findBySql(
result=类名::findBySql(sql,[‘:id’=>’值’])->all() 返回数组 数组中的元素是对象
2
//查询 Id=1
Test::find()->where([‘id’=>1])->all();
//查询 id>1
Test::find()->where([‘>’,’id’,’1’])->all();
//between语句
Test::find()->where([‘between’,’id’,1,2,3])->all();
//like语句
Test::find()->where([‘like’ , ‘字段’ , ‘值’])->all();
加上asArray 结果转化为数组
属性标签
默认通过yii\base\Model::generateAttributeLabel()方法自动从属性名生成 它会自动将驼峰式大小写变量名转换为多个首字母大写的单词
如果你不想用自动生成的标签,可以覆盖 yii\base\Model::attributeLabels() 方法明确指定属性标签
public function attributeLabels()
{
return [
‘name’ => ‘Your name’,
‘email’ => ‘Your email address’,
‘subject’ => ‘Subject’,
‘body’ => ‘Content’,
];
}
场景(scenario)
yii\base\Model::scenarios() 方法提供两个用处:定义哪些属性应被验证,定义哪些属性安全
模型使用 yii\base\Model::$scenario 属性保持使用场景的跟踪, 默认情况下,模型支持一个名为 default 的场景
默认情况下,模型支持的场景由模型中申明的 验证规则 来决定, 但你可以通过覆盖yii\base\Model::scenarios()方法来自定义行为
scenarios() 方法默认实现会返回所有yii\base\Model::rules()方法申明的验证规则中的场景
场景特性主要在验证 和 属性块赋值 中使用。
public function scenarios()
{
return [
register => [‘username’, ‘password’],
login => [‘username’, ‘email’, ‘password’],
];
}
验证规则 (rules)
如果想一条规则只在某个 场景(scenario) 下应用,为此你可以指定规则的 on 属性
public function rules()
{
return [
// 在"register" 场景下 username, email 和 password 必须有值
[[‘username’, ‘email’, ‘password’], ‘required’, ‘on’ => ‘register’],
// 在 "login" 场景下 username 和 password 必须有值
[['username', 'password'], 'required', 'on' => 'login'],
];
}
一个属性只会属于scenarios()中定义的活动属性且在rules() 申明对应一条或多条活动规则的情况下被验证
块赋值
$model = new \app\models\ContactForm;
$model->attributes = \Yii::$app->request->post('ContactForm');
安全属性
块赋值只应用在模型当前scenario 场景yii\base\Model::scenarios()方法 列出的称之为 安全属性 的属性上
可以使用safe 的验证器来申明 哪些属性是安全的不需要被验证
public function rules()
{
return [
[['title', 'description'], 'safe'],
];
}
非安全属性
想验证一个属性但不想让他是安全的(可以被块赋值的) 可以在属性名加一个惊叹号 !
public function scenarios()
{
return [
'login' => ['username', 'password', '!secret'],
];
}
三个属性都会被验证, 但只有 username和 password 属性会被块赋值, 要对secret属性赋值,必须$model->secret = $secret;。
yii提供了在保存或修改数据的时候自动将数据库中的created_at/updated_at字段自动赋值时间戳,需要我们在model层重写behaviors方法
/**
* @inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
view层的操作
访问数据
在视图中有两种方式访问数据:推送和拉取。 推送方式是通过视图渲染方法的第二个参数传递数据 拉取 <?= $this->context->id ?>
设置页面标题
$this->title = 'My page title'; <title><?= Html::encode($this->title) ?></title>
控制器中声明$layout属性表明渲染那个视图布局文件 public $layout = ‘main’;
嵌套布局
<?php $this->beginContent('@app/views/layouts/base.php'); ?>
...child layout content here...
<?php $this->endContent(); ?>
子布局内容应在 beginContent() 和 endContent() 方法之间,传给 beginContent() 的参数指定父布局,父布局可为布局文件或别名。
使用数据块
<?php $this->beginBlock('block1'); ?>…content of block1…
<?php $this->endBlock(); ?>或
<?php if (isset($this->blocks['block1'])): ?><?= $this->blocks['block1'] ?>
<?php else: ?>
... default content for block1 ...
<?php endif; ?>
Yii模板继承
View中一个layout文件夹,在里面新建common.php文件,写上公共部分代码
在控制器方法中声明一个属性 public function
l
a
y
p
u
t
=
’
c
o
m
m
o
n
’
使
用
layput=’common’ 使用
layput=’common’使用this->render(‘视图文件名’)来渲染视图
此时 render会帮我们做两件事情 第一件事:把我们视图文件中的内容(就是render括号后面的文件中的内容)放到
c
o
n
t
e
n
t
变
量
中
第
二
件
事
情
:
在
上
面
声
明
了
content变量中 第二件事情:在上面声明了
content变量中第二件事情:在上面声明了layout=’common’就是让yii框架帮我们渲染common文件
Common.php中在需要渲染值得地方写上<?=$content;?> 这样就把$content
中的内容渲染到了common中了
视图文件中显示另一个视图文件
控制器中中正常使用 $this->renderpartai(‘视图文件名’)
在视图文件中加上 <?PHP echo $this->render(‘要包含进来的文件名’,值) ?>
如果render的第二个参数有值 那么表示需要向另一个文件中传值
另一个视图文件中渲染值 <?=$name ?>