YII框架使用
编码规范
- 文件不许写 PHP 结束语
- 命名空间与目录对应,文件名采用类名.php 格式,目录大小写与命名空间相同,类名大小写与文件名相同(psr-4规范)
- 视图目录名与 控制器名一致
- 类的命名必须遵循大写开头的大驼峰命名法(列如
UserController
)。 - 类中的常量所有字母必须大写,多个单词间用下划线分隔;
- 方法名必须遵循小写开头的小驼峰命名法(列如
actionlogin
); - 普通目录全小写格式,多个单词之间用中杠分隔(列如
memcahe-de
) - use Yii; 后下面使用Yii的函数就可以不要 \Yii::app这种形式,直接Yii::app就好
框架的特点
- YII是一个久经劳考验的全栈框架。注重安全和稳定,通常用于构建中大型项目;
- YII是完全面向对象,所有的功能都是以类的形式提供的,YII2需要
PHP 5.4
以上的版本; - YII采用MVC的设计模式,控制器支持action级别的代码重用,视图层多模版引擎支持,模型层提供了强大的ORM;
- YII使用组件来构建运用(
user,log,errorHandler
等) - YII提供了强大的界面组件和自动代码生成
- YII提供了事件处理机制和灵活的行为扩展
YII2 框架类
框架类如:'class' => ‘’yii\db\Connection',
//如果你想点击进入这个类的来源可以修改成以下 这样 class 或 className() 能获取到这个类的名称,点击 Connection 就能进入
1 'class' => yii\db\Connection::class,
2 'class' => yii\db\Connection::className(),
config配置文件
return $config
他return
出去的是一个数组$config
,是不定义常量的,像连接数据库也是不定义常量的
backend (后端目录)
解决一开始安装web/目录下没有入口index.php [ 2.0 版本 ]
对于一些刚使用Yii2的同学可能刚下载
advanced
版 在/frontend/web/
与/backend/web/
下找不到index.php
解决: 在advanced目录下有个 init.bat 文件 双击运行,会出现一个dos窗口 输入 0(开发模式) 或 1(产品模式) 按回车 再输入 yes 回车 这样就能生成入口文件了.
访问 web 这个目录 这个才是要发布出去的内容
frontend(前端目录)
如果不是通过
Composer
下载安装的 进入主页会报个错误 进入配置文件(config/web.php
)修改 config/web.php 文件,给 cookieValidationKey 配置项 添加一个密钥(若你通过 Composer 安装,则此步骤会自动完成): // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation (翻译)!!! 在下面插入一段密钥(若为空) - 以供 cookie validation 的需要 'cookieValidationKey' => '在此处输入你的密钥',
应用结构
应用中最重要的目录和文件(假设应用根目录是 basic):
basic/ 应用根目录
composer.json Composer 配置文件, 描述包信息
config/ 包含应用配置及其它配置
console.php 控制台应用配置信息
web.php Web 应用配置信息
commands/ 包含控制台命令类
controllers/ 包含控制器类
models/ 包含模型类
runtime/ 包含 Yii 在运行时生成的文件,例如日志和缓存文件
vendor/ 包含已经安装的 Composer 包,包括 Yii 框架自身
views/ 包含视图文件
web/ Web 应用根目录,包含 Web 入口文件
assets/ 包含 Yii 发布的资源文件(javascript 和 css)
index.php 应用入口文件
yii Yii 控制台命令执行脚本
项目基本概念
- 项目
project
- 应用
application
- 组件
component
- 模块
module
- 控制器
controller
- 动用
action
(控制器的方法 也可以是个类) - 路由
route
目录结构
基础应用结构
controllers
控制器views
视图models
模型web
浏览器访问应用的根目录config
配置文件runtime
运行时目录,放缓存,日志,调试信息等(在放到 web 服务器上【也就是在linx里面该目录 需要 写权限 】),不像TP框架那样不能删除,YII 不会给你自动生成assets
静态资源管理web/assets
框架管理的静态资源,请勿手动修改管理目录内容(这个是由框架开维护的,也需要写权限)
控制器
- 创建控制器
- 在
yii\web\Application
网页应用中,控制器应继承yii\web\Controller
或它的子类。 同理在
yii\console\Application
控制台应用中,控制器继承yii\console\Controller
或它的子类。 如下代码定义一个site
控制器:namespace app\controllers; use yii\web\Controller; class SiteController extends Controller { }
控制器与路由
- 控制器以
Controller
作为后缀,继承自yii\web\Controller
- 动作以
action
作为前缀,public 访问修饰(如:public function actionBoss()
访问的是 Boss) 控制器
id
–类名去后缀(后缀是值Controller
),在url中全部转为小写,如果是驼峰命名多个单词,转为中杠分隔。如:控制器的文件名(FooBasController.php);类名(FooBasController);方法名(actionBoss()); 在 url 中输入 index.php?r=default-com/boss 都需要是小写,中间用中杠分开
- 动作ID 去前缀(去掉前面的 action 取用 后面的如:actionLogin;取Login),在url中全部转为小写,如果是驼峰命名多个单词,转为中杠分隔。
- 路由如何指向动作,控制器 ID/动作ID(
r=default/index
) - 模块(module),模块/控制器 ID/动作ID(
r=admin/default/index
) - URL访问规则,
index.php?r=
路由 传参数使用&参数=值的方式 默认路由
site
定义在yii\web\Application::$defaultRoute
或 yii\base\Module::$defaultRote
意思是你刚进入web目录的时候默认的是 Sitel 控制器 而不是 index 控制器 `yii\web\Application::$defaultRoute` 或 `yii\base\Module::$defaultRote` 可以在这里面修改默认的控制器
默认动作ID
index
定义在yii\base\Controller::$defaultAction
意思是你刚进入web目录的时候默认的是 Sitel 控制器 下的 index 方法 `yii\base\Controller::$defaultAction` 在这里面也可以修改
url生成
Url帮助类的工作方式的演示(在TP框架中是 大U 方法)
意思也就是跳转 到别的地方
use yii\helpers\Url; 1)// 同一个控制器中其他的action echo Url::toRoute(['update','id'=>'1']);//如果没有参数,可以就直接写方法名 // 跳转到当前控制器下的方法 生成一个 url 连接 class DefaultController extends Controller { public function actionIndex() { echo Url::toRoute('default/index');//或者只写('index') 代表当前控制器下的 index 方法 //得到地址 /YII/Primary-application/basic/web/index.php?r=default%2Findex //如果需要传参数 echo Url::toRoute(['index','id'=>'1']); } } 2)// 不同控制器的 action (同以 module) echo URL::toRoute('post/index'); 3)//绝对路由(可以跳出当前 module 如果启用了 module,需要在前面加入 module的id) echo Url::toRoute('/site/index'); 4)//当前控制器,多个单词组成的 action,列如: actionUserInfo; echo Url::toRoute('user-info'); 5)//生成完整的Url,也就是带域名的(第二个参数 true); echo Url::toRoute('site/index',true); //得到地址:http://localhost/YII/Primary-application/basic/web/index.php?r=site%2Findex //一般用来做分享的 1:微信分享,分享出去一张图片,需要要绝对路径,不然分享出去的图片打不开;2:如果你是做支付的,支付里面会有一个 ‘回调地址’;银行会通知你 客户支付完成,银行需要你给他一个完成的 url 地址(相对路径是不行的); 6)//路由别名 echo Url::toRoute('@register');//路由别名,需要先注册别名,列如: Yii::setAlias('@register','site/register'); echo Url::to('@baidu'); //别名,列如 Yii::setAlias('@baidu','http://www.baidu.com/') 7) //拼接 images css等的路径(动态路径,项目改动是不会影响的) echo Url::base(); //得到的是你的 web 目录的路径;列如:/YII/Primary-application/basic/web/ echo Url::base(true);// 生成绝对地址:http://localhost/YII/Primary-application/basic/web/ //拼接图片地址 echo Url::base().'/images/2015626642448.jpg'; //得到的地址:/YII/Primary-application/basic/web/images/2015626642448.jpg echo Url::to(); //为空的时候 返回当前的 url; echo Url::to(数组); //等价与 echo Url::toRoute(数组);to() 只能传数组,toRoute() 还能传字符串
在控制器中跳转
createUrl // 只是生成url串
redirect // 只是跳转页面
return $this->redirect([‘foo-bar/index’,’password’=>123]); //
render // 是用来输出页面内容
class SiteController extends Controller { public function actionSay($message = 'Hello') { return $this->render('say', ['message' => $message]); } } <?php use yii\helpers\Html; ?> <?= Html::encode($message) ?> say 视图应该存为 views/site/say.php 文件。当一个操作中调用了 [[yii\web\Controller::render()|render()]] 方法时, 它将会按 views/控制器ID/视图名.php 路径加载 PHP 文件。
基础应用模块 去掉 Url 中的 ?r= 和index.php (也就是隐藏url) Apache 服务器
找到配置文件 (config->web.php) 'urlManager' => [ // URL管理器 'enablePrettyUrl' => true, // 美化URL 把 ? 好 r去掉了 'showScriptName' => false, // 指定是否在URL在保留入口脚本 index.php,apache 需要开启 rewrite,并添加.htaccess 文件 'rules' => [ ], ], //被注释掉了 打开就行 //开启apache rewrite_module 模块 LoadModule rewrite_module modules/mod_rewrite.so 去掉前面的 # 号 同时还要在index.php同级目录下新建.htaccess文件 <IfModule mod_rewrite.c> //表示重写引擎开 RewriteEngine on //请求的文件或路径是不存在的,如果文件或路径存在将返回已经存在的文件或路径 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] </IfModule> 3、.htaccess文件解释 概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。 通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、 允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
高级应用模块 请查看 另外一个文件
视图(使用$this->render(‘index’) 跳转)
默认在 views/控制器id/目录下,如果控制器有大写,列如:UserInfoController,对应view目录为 user-info
return $this->render('index') 跳转 // 名为 index 的视图文件 return $this->render('index',[ //携带数据到视图中 'username'=>'Ethan', 'age'=>'24', 'sex'=>'男',
]);
在视图模版中,不要直接echo变量,防止 xss 攻击(Cross Site Scripting跨站脚本攻击),需要使用
return htmlspecialchars($var, ENT_QUOTES | ENT_SUBSTITUTE,'UTF-8', true); YII提供了 \yii\helpers\Html::encode($var) 方法 在模版中输入:<?php echo \yii\helpers\Html::encode($var);?> 如果嫌弃写<?php echo 太麻烦了 可以写成 <?= 只应许在views模版中使用 php5.4 就支持 你想关都关不掉
布局 Layout
默认布局
yii\base\Application::$layout = 'main';
app\modules\admin\Modules::$layout = 'main';
- 不使用layout,在控制器中加入属性
public $layout =false
(这样是不继承layout所有的模版) 或方法中动态修改$this->layout = false
,
也可以使用$this->renderPartial()
代替$this->render()
; layout 目录中 main.php 是配置文件
<div class="container"> <?= Breadcrumbs::widget([ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], ]) ?> <?= $content ?> </div> // <?= $content ?> //这个是整个页面的内容 你要把他删掉了 你所有的内容就全没了
自己定义一个layout
自己在layout目录中创建一个 commom.php 文件 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <?php echo $content;?> //记住这个一定要加,不需要htmlspecialchars()编码 </body> </html> 在控制器中加入一个属性 public $layout = 'commom'; 如:class DefaultController extends Controller { public $layout = 'commom'; public function actionIndex() { return $this->render('index',[ 'username'=>'Ethan', 'age'=>'24', 'sex'=>'男', ]); } } Ajax 请求的时候返回数据 使用 `$this->renderPartial()` return $this->renderPartial('index',[ 'username'=>'Ethan', 'age'=>'24', 'sex'=>'男', ]);
基础的layout
是用来挂他的挂件,比如我需要在头部或者什么地方输出点东西,或者挂些什么插件上去,写模版的时候可以默认写上去
<?php use yii\helpers\html; ?> <?php $this->beginPage()?> <!doctype html> <html lang="<?= Yii::$app->language ?>"> <head> <meta charset="<?= Yii::$app->charset ?>"/> <title><?= Html::encode($this->title)?></title> <?php $this->head()?> </head> <body> <?php $this->beginBody()?> <div class="container"> <?= $content ?> </div> <footer calss="footer">@ 2016 me :)</footer> <?php $this->endBody()?> </body> </html> <?php $this->endPage() ?>
应用程序(Application)与组件配置
获取应用实列
yii\web\Application
var_dump(\Yii::$app) 在 web/index.php 入口文件中实例化
配置文件 配置应用属性
config/mian(或者是web).php
返回的数组,key 就是应用属性$config = [ 'id' => 'basic', //项目的名称,不要使用默认的 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'components' => [ 'request' => [ // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 'cookieValidationKey' => '_-ktlqzAfusuhunc54ze6xaZV0ElgXOu', ],
.
'id' => 'basic',
项目的id用于区分项目的,可能一台服务器上面有多个项目,用于区分里面的缓存文件与 session 的 YII 框架是不能直接操作 session 的 调用这个项目的ID echo \YII::$app->id;
'basePath' => dirname(__DIR__),
上面目录的上级目录用于上传文件,上传到 basePath 下面的的的 uploads 中 调用 echo \YII::$app->basePath;
YII框架定义的所有默认属性在
vendor\yii2\base\Application.php
中,只要该文件中有的属性都可以用echo \YII::$app->'属性名'
来调用;>>>进入这个文件 方法一: 直接进入 `vendor\yii2\base\Application.php` 方法二: echo \YII::$app->basePath; 按住 ctrl 鼠标点击 $app 进入里面的一个文件,他上面有一句注释的话 * @var \yii\console\ Application|\yii\web\Application the application instance 点击 Application 进去里面,当前的 class Application extends \yii\base\Application 点击 最后面的 Application 进入里面就OK了 ----------------------------------------------------------------------------------------------------------- 如果想要修改 列如:其中有一个属性 public $name = 'My Application'; 修改:在你的配置文件中 config\web.php 添加一条 $config = [ 'id' => 'YIIItemOne', 'name' => 'YII项目一', //新添加的 'basePath' => dirname(__DIR__), 输出:echo \YII::$app->name;
\YII::$app->name; 这个对象在哪里被实例化
在入口文件 web\index.php 中 (new yii\web\Application($config))->run();
components //组件
'components'=>[ 'request' => [ 'cookieValidationKey' => '_-ktlqzAfusuhunc54ze6xaZV0ElgXOu',], // request 应用输入 post get cookie 都是在这 里面 'cache' => ['class' => 'yii\caching\FileCache',], // 缓存,如查询一次数据库缓存20秒,20秒内数据都有用, 'user' => [ //用于做登录的,用于访问判断是谁 'identityClass' => 'app\models\User', 'enableAutoLogin' => true, ], 'errorHandler' => ['errorAction' => 'site/error',], // 错误处理 'mailer' => [ // 发信件的 'class' => 'yii\swiftmailer\Mailer', 'useFileTransport' => true, ], 'log' => [ //记日志的 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], ], ], 'db' => require(__DIR__ . '/db.php'), 'urlManager' => [ 这个是隐藏入口 url 中 index.php 的,URL管理器 'enablePrettyUrl' => true, // 美化URL 把 ? 好 r去掉了 'showScriptName' => false, // 指定是否在URL在保留入口脚本 index.php,apache 需要开启 rewrite,并添加.htaccess 文件 'rules' => [ ], ], ] -------------------------------------------------------------------------------------------------------- //配置文件的 内容可以被添加 'timeZone'=>'PRC'; //修改时区 中国 'language'=>'zh-CN'; //修改语言包 'defaultRoote'=>'home' //修改默认路由器,对应 Yii::$app->defaultRout 'params' //应用参 params.php 'adminEmail'=>'admin@example.com // echo Yii::$app->params['adminEmail']; --------------------------------------------------------------------------------------------------------
组件 config/main.php 返回数组中的 components 项
Web 应用核心组件 yii\web\Application::coreComponents();
[ 'request'=>['class'=>'yii\web\Request'], 'response'=>['calss'=>'yii\web\Response'], 'session'=>['class'=>'yii\web\Session'], 'user'=>['class'=>'yii\web\User'], 'errorHandler'=>['class'=>'yii\web\ErrorHandler'], ]
日志文件
Yii::waming()
日志文件rutime/logs/app.log
Yii::error()
;Yii::trace('调试内容','test')
;
自定义错误,直接写 不用写
echo
一定要写在return $this->render()
前面\Yii::error('1234'); // 第二个参数默认是 Application ,页面是看不到,在任务日志里面可以看的到 -------------------------------------------------------------------------------------------------------- \Yii::info('1234'); //把错误信息记下来 第二个参数默认是 Application 或者 Yii::info('1234','demo'); \Yii::trace('1234'); //把错误信息记下来 第二个参数默认是 Application 或者 Yii::trace('1234','demo1'); -------------------------------------------------------------------------------------------------------- \Yii::info(); 与 \Yii::trace(); 在页面的右下角 有个图标点开 选择 log 就可以查看的到 --------------------------------------------------------------------------------------------------------
图标中有很多东西 点击打开的图标 左上角
2.0.9 PHP 5.5.12
查看左边导航条Database 数据库生成的 sql 语句 Logs 错误日志
Modul模型
- 模型是 MVC 模式中的一部分,是代表业务数据,规则和逻辑的对象
- 默认情况下你的模型类直接从
yii\base\Model
继承,所有 非静态公有 成员变量都是属性! 例如:下述
ContactForm
模型类有4哥属性,name
,email
,subject
andcontent
。ContactForm
模型用来代表从HTML表单获取的输入数据Member.php文件|model模型文件 ------------------------------- namespace app\models; use yii\base\Model; class Member extends Model { public $name; public $email; public $subject; public $content; }
验证
- 当模型接受到终端用户输入的数据,数据应当满足某种规则(称为 验证规则 也成为 业务规则)
- 通过覆盖
yii\base\Model::rules()
方法指定模型属性应该满足的规则来申明模型相关验证规则。
- 父类方法(就是框架自带的
rules()
)是返回空的数组,自定义rules()
方法 来覆盖父类的方法,来达到验证效果 - 在控制器中(Controller)使用 $member->
- 父类方法(就是框架自带的
下述例子显示
ContactFrom
模型申明的验证规则;----------------------在模型中-------------------------------- //验证 public function rules() { return [ // 如果是多个需要验证的就写成数组 | required 必填 [['name','email','subject','content'],'required'], // emaile 必须是 email(必须是邮箱),但允许为空,为空的时候不验证 ['email','message'=>'提示信息'] ]; } ----------------------在控制器中------------------------------ $member = new Member(); $member->name = '刘杰'; $member->email = 'abc@qq.com'; //获取验证是否过关(获取错误信息) getFirstErrors() | getFirstError() | getErrors() if ($member->validate()) { return 'OK'; } else{ return $member->getFirstErrors(); }
安全规则 safe
[['name','email','subject','content'],'safe'],
反回错误信息
'message'=>'不能为空'
[['name','email','subject','content'],'required','on'=>'register','message'=>'不能为空'],
邮箱验证 [‘email’,’email’]
// email(字段) 必须是 email(必须是邮箱),但允许为空,为空的时候不验证 ['email','email','message'=>'提示信息']
compare 对比验证
$repassword; //在该类中添加这条属性,用于判断输入两次密码是否正确, ['name','compare','compareValue'=>'对比的值','message'=>'提示信息'], // 对比值 ['password','compare','compareAttribute'=>'repassword','message'=>'两次密码不一致'], // 对属性
double 双精度数字验证
['number','double','min'=>'1.2','max'=>'5.3','tooSamll'=>'小于1.2','tooBig'=>'大于5.3','message'=>'是不是数字']
number 整数范围
['number','double','min'=>'1','max'=>'5','tooSmall'=>'小于1','tooBig'=>'大于5','message'=>'不是整数'],
in 范围
['sex','in','range'=>['nan','nv'],'message'=>'不在范围内'],
match 正则验证
['字段','in','pattern'=>'/正则/','message'=>'提示信息'],
unique 唯一验证
['字段','unique','message'=>'提示信息'], //关系到数据库
srting 字段验证
['字段','srting','min'=>'字符串最小长度','max'=>'字符串最小长度','tooShort'=>'字符串过短提示','tooLong'=>'字符串过长提示',],
captcha 验证码验证
['字段','captcha','captchaAction'=>'login/captcha','message'=>'提示信息'], ------------------------------------------------------------------------ // 自定义验证规则 // 在里面添加一个验证码的属性 public $Verification; ['username','checkUsername(这里是自定义的函数名)','params'=>['message'=>'提示信息']], // 在该模型里面 定义函数 pubilc function checkUsername($attribute,$params){ if($this->$attribute != $this->Verification){ $this->addError($attribute,$params['message']); // 添加错误验证信息 } // $attribute 这个是你要验证的字段(username),$params 错误信息 ,$Verification 验证码 } // 在控制器中 public function actionIndex() { $data=[ 'Member'=>[ // 该控制器对应的类的名字 'name'=>'name', 'email'=>'133@qq.com', 'subject'=>'subject', 'content'=>'content', 'age'=>'2', 'Verification'=>'name', // 验证码,可以调用框架本身带有的验证码 ] ]; $member = new Member(); $member ->load($data); if($member->validate()){ return 1; } else{ var_dump($member->getErrors()); // 获取错误信息 } }
场景(在验证的时候的场景)
- 模型可能在多个场景使用,例如:User 模块可能会在手机用户登录输入,也可能会在用户注册时使用。
- 在不同的场景下,模型可能会使用不同的业务规则和逻辑,例如
email
属性在注册时强制要求,但在登录的时候不需要。 - 模型使用
yii\base\Model::scenario
属性保持使用换场景的跟踪(意思就是在别的地方也会使用到这条规则)。 注册
register
—- 登录login
return [ [['name','email','subject','content'],'required','on'=>'register','message'=>'不能为空'], ];
注册场景
'on'=>'register'
[['name','email','subject','content'],'required','on'=>'register'],
场景跟踪
$member->scenario = 'register'; // 场景跟踪
$member = new Member(); $member->scenario = 'register'; // 场景跟踪 在这个地方也能使用注册的那条规则 $member->name = '刘杰'; $member->email = 'abc@qq.com'; if ($member->validate()) { // 判断是否出错 return 'OK'; } else{ var_dump($member->getFirstErrors()); // 反回错误信息 }
块赋值(批量直接把值赋给类里面的属性)
$member->attributes = $_POST
;也可以接收 $_POST 的赋值-------------以下会造成类里面有的属性赋不了值--------------------- $member = new Member(); $_POST['name']='妹子'; $_POST['email']='2165465@qq.com'; $_POST['subject']='项目一'; $_POST['content']='协议内容'; $member->attributes = $_POST; //块赋值属性 ------------------------------------------------------------- //解决方案 在该 model 中 rules() 方法里面的规则中加一条 把你需要接受的这些字段设置为安全 public function rules() { return [ [['name','email','subject','content'],'safe'], //把你需要接受的这些字段设置为安全 ]; }
load() 方法接受 $_POST 的赋值
$data=[ 'Member' =>[ // model类的名字 'name'=>$_POST['name'], 'email'=>$_POST['email'], 'subject'=>$_POST['subject'], 'content'=>$_POST['content'], ], ]; $member-> load($data); // 记住也要在module类中的 rules() 方法里面的规则中加一条 把你需要接受的这些字段设置为安全 public function rules() { return [ [['name','email','subject','content'],'safe'], //把你需要接受的这些字段设置为安全 ]; }