[关闭]
@Purpose 2017-03-12T08:09:02.000000Z 字数 8419 阅读 1752

YII框架学习笔记——基础篇

YII学习笔记

Yii的安装

在官网下载Yii框架之后,首先检测环境是否符合Yii框架的要求
requirement.php 查看需要的配置环境

The OpenSSL PHP extension is not installed
在php.ini取消extension=php_opensll.dll的分号

config/web.php 'cookieValidationKey' => '这里随便填一些东西' 作用为了防止cookie攻击的
此时,Yii框架安装完成


Yii框架的处理流程示意图此处输入图片的描述


预备知识——命名空间

当两个php文件中的类名字冲突的时候,可以使用命名空间来避免冲突
在php文件的开头写上namespce a\b\c;这样就为这个类名分配了一个命名空间
此时想要实例化该类的话,要加上命名空间

  1. $a_app = new a\b\c\Apple();

如果觉得这样的代码很冗余,可以用use关键字,默认使用该命名空间

  1. use a\b\c\Apple;
  2. $a_app = new Apple();

使用了一次use之后,如果想另外一个命名空间中的类名也得到简化,可以使用use as

  1. use d\e\f\Apple as BApple;
  2. $b_app = new BApple();

此时就可以使用它来使用B中的类
如果在C中没有设置命名空间,那它就是顶层的全局类,需要使用反斜杠

  1. $c_app = new \Apple();

此时就可以使用全局类了


Control控制器


基本使用方法

YII中的控制器在Controller中,命名要最后要为Controller,比如HelloController.php
类的命名空间要设置为app\controllers,并且要继承 Controller这个父类
因为要继承一个父类,所以要使用父类的命名空间

  1. use yii\web\Controller;

在控制器中的方法在yii中被称为操作,要创建一个的话,其函数名必须要以action开头
比如index操作,要命名为actionIndex
如果在页面中想交给HelloController控制器进行index操作,路径改写成

  1. index.php?r=hello/index

其中r后面跟着的是控制器的名字,斜杠后面的是操作的名字


参数

在请求中可以在后面加上参数,

  1. index.php?r=hello/index&id=3

如果想要获得这个id参数的话,需要在使用请求组件,该组件需要调用全局变量YII
在index操作中

  1. $request = \YII::$app->request;

通过$request->get('id');就可以获得传过来的参数
如果没有get到数据的话,可以在get方法后面添加一个多一个默认值参数

  1. $request->get('id', 20);

这个时候如果没有get到东西,该值默认为20
post方法和get方法类似,

  1. $request->post('id', 20);

如果可以isPostisGet这两个方法来判断请求是通过post还是get方法传递过来的


响应

在操作里,函数处理完一个请求之后会把信息打包发会给服务器,这就称之为响应
想要进行响应 的操作,需要使用响应组件,该组件同样需要全局的类YII

  1. $res = \YII::$app->response;
  2. $res->statusCode = '404';
  3. //可以通过组件中的状态码来设置响应

此时操作返回的就是404 not found
如果没有设置。默认就是200 (ok)
在该组件中还可以控制响应页面的头部处理,即$res->headers
该操作可以设置页面的许多信息
添加header:

  1. $res->headers->add("pragma", "no-cache"); //告诉浏览器不要缓存该页面

修改header:

  1. $res->headers->set("pragma", "max-age=5"); //让浏览器缓存该页面5秒钟

删除header:

  1. $res->headers->remove("pragma"); //删除缓存参数

跳转:

  1. $res->headers->add("location", "http://www.baidu.com"); //转跳到百度首页

也可以使用Controller的类中提供的方法
重定向:

  1. $this->redirect("http://www.baidu.com", "302"); //302表示状态码

文件下载:

  1. $res->headers->add("content-disposition", "attachment; filename="a.jpg"); //让浏览器下载文件

也可以使用Controller的类中提供的方法

  1. $res->sendFile("./robots.txt");

这个可以让浏览器下载请求的文件的目录下的robots.txt文件


SESSION

SESSION的使用需要对应的应用组件
获取方式,也是和以上的一样

  1. $seesion = \YII::$app->session //调用session组件
  2. if($session->isActive) //判断session是否开启
  3. {
  4. echo "Session is not active";
  5. }
  6. elseif(!$session->isActive)
  7. {
  8. echo "Session is acive";
  9. }
  10. $session -> open; //开启session
  11. $session -> set('user','张三'); //设置session值
  12. echo $session -> get('user'); //获取session值
  13. $session -> remove('user'); //删掉session值

在php.ini文件中的session.save_path的设置中可以查看session的数据

TIPS1:不同浏览器会产生不同的session,系统是根据sessionID来进行识别的
TIPS2: 即可通过对象的方式操作session,也可以通过数组的方式来操作session

通过数组方式来操作session

  1. $session['user'] = "张三"; // 设置session值
  2. echo $session['user']; //取出session数据
  3. unset($session['user']); //通过unset 来删除session

浏览器响应的时候添加cookie,请求的时候获取cookie
cookies的组件在响应的组件当中,所以老规矩,YII调用

  1. $cookies = \YII::$app->response->cookies;
  2. $cookie_data = array('name'=>'user', 'value'=>'zhangsan'); //注意要传入参数

此时要生成一个cookie的对象,注意,这个时候要注明它的命名空间

  1. use yii\web\Cookie;
  2. $cookies->add(new Cookie($cookie_data));
  3. // 删除cookie
  4. $cookies->remove('user');
  5. //获取请求时cookies
  6. $cookies = \YII::$app->request->cookies;
  7. $cookies->getValue('user', DefaultNullValue); //第二个参数是没有对应的cookie的时候,返回的默认值

cookies的value是会被加密的,里面的加密是通过之前上面设置的cookieValidationKey中的字符串来加密的


Views视图层


Controller和Views的关联

  1. return $this->renderpartial(“parm”);

视图创建的要点:
1. 在控制器中通过renderPartial('文件名')方法进行调用;
2. 调用的文件必须放在一个与控制器同名的文件夹中;


Controller和Views进行的数据交互


控制器和视图之间传递数据
  1. $hello="Hello World!"; //定义一个变量
  2. $date=array(); //声明一个数组
  3. //这里使用了关联数组,把这个字符串变量放到数组$date中
  4. $date['view_hello_str']=$hello;
  5. return $this->renderPartial(“index”,$date);
在视图中如何使用数据

也就是使用控制器传递过来的数组
这只需在模板中调用$data的key值(也就是数组下标),即可获得对应的value值
<?=$键名 ?> //?=之间不能有空格

数据安全

如果用户在输入框内输入js的代码,那么浏览器会直接解析执行其中的内容
我们必须对用户输入的内容进行转义

  1. use yii\helpers\Html
  2. Html::encode($view_hello_str);
  1. use yii\helpers\HtmlPurifier;
  2. HtmlPurifier::process$view_hello_str);

布局文件

yii中提供布局文件,布局文件放在views/layouts
设置 controller 类属性

  1. public $layout = "common" //common 为自定义的布局文件名

需要在action中使用render()方法 该方法默认将视图文件内容存放到一个$content变量中
在布局文件中通过<?=$content?> 可以输出

同时通过使用

  1. echo $this->render('viewfile', array('variableName'=>'value'));

可以在一个视图文件中显示另一个视图文件的内容,
render 的第二个参数可以传递数据给视图文件,<?=$variableName;?>方式输出值,
显然,数组的key 为变量名,value为变量值


Model数据模型


数据库的配置

在视图中显示的数据一般会预先存储在数据库当中,Yii框架中为了方便到数据库中取(增删改查)这些数据,提供了一种数据模型的东西。Yii要想操控test这张表,必须知道test这张表在哪个数据库,数据库的地址在哪里,Yii框架专门提供了一个配置文件(basic/config/db.php)给我们。


创建活动记录


单表查询

  1. <?php
  2. //给HelloController创建命名空间
  3. namespace app\controller;
  4. //使用web里面的控制器
  5. use yii\web\Controller;
  6. //使用Test模型
  7. use app\models\Test;
  8. //创建一个Hello控制器并使用extends让它集成Controller控制器
  9. //创建一个公共的actionIndex方法
  10. public function actionIndex(){
  11. //查询数据
  12. $sql ='select*form test where id=1';
  13. //Test继承的ActiveRecord活动记录类里面有一个findBySql方法是运行sql语句的
  14. $rseults = Test::findBySql($sql)->all();
  15. }

降低内存多两种方案
1、将对象转化为数组:asArray()
$rseults = Test::findBySql($sql)->asArray()->all();
执行sql的查询语句之后返回的是一个对象,对象占用的内存空间大,而数组占用的内存空间小,使用数组能降低内存的使用
2、批量查询:batch()
Model::find()->batch(10)
这样的功能类似于文件读取中的管道读取,一次只加载部分到内存,这样可以节省内存,避免浪费(一次载入所有到内存然后慢慢处理,是会占用较多内存的)

使用占位符防止sql注入

  1. <?php
  2. public function actionIndex(){
  3. //:id 是占位符 把用户输入的数据当做一个整体防止sql注入
  4. $sql = 'select * from test where id = :id';
  5. //findBySql()中的第二个参数可以替代$sql中的占位符':id',通过数组的形式把值传过去,并通过内部的处理,从而过滤掉sql注入语句
  6. $result = Test::findBySql($sql, array(':id'=>1))->all();
  7. }
  8. ?>

使用find()->where()方法查询

  1. //查询id=1的数据
  2. $result = tableName::find()->where(['id'=>1])->all();
  3. //查询id>0的数据
  4. $result = tableName::find()->where(['>','id',0])->all();
  5. //查询1<=id<=2的数据
  6. tableName::find()->where('between','id',1,2)->all();
  7. // 查询 title like "%title1%"
  8. tableName::find()->where('like','title','title1')->asArray()->all;

单表删除

  1. <?php
  2. //删除数据,先取出要删除的数据
  3. $results = Test::find()->where(['id'=>1])->all();
  4. $results[0]->delete();//调用delete()方法就可以删除第一条数据
  5. //删除数据有个更快捷的方式:调用控制器当中的deleteAll()方法把整个表里的数据删掉;同时这个方法里也可以带上查询条件指定删除哪部分的数据。
  6. Test::deleteAll('id>0');
  7. Test::deleteAll('id>:id',array(':id'=>0));//deleteAll也支持占位符的功能

Test::deleteAll('id>:id',array(':id'=>0));这里数组对应的数据库中的ID是从0开始,也就是数据库第一条记录就是:id=>0
这里的Test是模型名称,当然在控制器使用模型时候必须告诉控制字自己来来自哪里:use app\models\Test; use yii\web\Controller;


单表添加数据

  1. /******HelloController.php******/
  2. //增加数据
  3. $test = new Test;//实例化Test模型并保存在$test变量中
  4. //id和title字段可以预先在保存之前通过属性的方式赋值
  5. $test->id = 3;
  6. $test->title = 'title3';
  7. //在保存数据的时候,这些数据是用户发送的请求当中获取的,保存前需要进行数据的合法性验证,Test模型里有专门的函数验证。
  8. $test->validate();//保存数据之前调用validate()方法启用验证器rules()去判断id和title符不符合保存的条件
  9. if ($test->hasErrors()) {
  10. echo 'data is error!';//如果发生校验错误,说明数据不合法。
  11. die;//结束掉程序,不让它保存
  12. }
  13. $test->save();//调用save()方法把它转化为一条数据并保存在表单中
  14. /******basic/models/Test.php******/
  15. //数据模型之单表添加数据
  16. //通过rules()函数验证保存前数据的合法性
  17. public function rules(){
  18. //返回一个数组,在数组里对每一个字段进行验证
  19. return[
  20. ['id','integer'],//Yii提供了一个验证器(每个验证器都是一个类)的东西,比如integer验证器。
  21. ['title','string','length'=>[0,5]]
  22. ];
  23. }

单表删除

  1. $test=Test::find()->where(['id'=>4])->one();//取出一条数据
  2. $test->title='title4444'; //修改数据
  3. $test->save(); //保存数据

关联查询

关联查询:
hasMany:一对多,hasOne:一对一
$customer->orders; 当没有orders属性时,$customer自动调用_get()方法,拼接调用getOrders()方法,并自动在后面加上all()方法或者one()方法,至于何时自动拼接all或者one,取决于关联查询是用的hasMany还是hasOne,如果是hasMany则拼接all,否则反之。

  1. //关联查询
  2. //根据顾客查询她/他的订单的信息
  3. $customer = Customer::find()->where(['name'=>'zhangsan'])->one();
  4. $order = $customer->hasMany('app\models\Order',['customer_id'=>'id'])->asArray()->all();
  5. $orders = $customer->getOrders();
  6. $orders = $customer->orders;
  7. print_r($orders);
  8. //根据订单查询顾客的信息
  9. $order = Order::find()->where(['id'=>1])->one();
  10. $customer = $order->customer; //以属性的方式获取数据
  11. print_r($customer);
  12. /***注:若使用以属性的方式获取数据,则在模型里面要定义一个方法,该方法要以get+属性的命名方式。***/

关联查询的缓存问题

在一个请求的生命周期中,调用了$customer->orders后,此属性会被缓存;
可以强制刷新可以使用unset,unset($customer->orders);
此时再调用该属性的时候系统不会在缓存区内读取数据而是重新执行sql语句向数据库进行数据查询读取,这就可以避免数据没有更新


关联查询的性能问题

多次执行sql: 每次调用未缓存的属性,都会执行一次sql,如果存在循环,就会多次执行;可以使用Customer::find()->where(...)->with('orders')解决,with会把循环中的语句集合为一条查询

  1. /***********************************************/
  2. //关联查询的时候涉及到性能问题。
  3. $customers=Customer::find()->all();
  4. //执行的sql语句为:select * from Customer;
  5. foreach($customers as $customer){
  6. $orders=$customer->orders; //每次循环都会执行一次sql语句
  7. //select * from order where customer_id = ...
  8. }
  9. /***********************************************/
  10. $custome=Customer::find()->with('orders')->all();
  11. //执行的sql语句为:select * from Customer;
  12. //select * from Order where customer_id in(...);
  13. foreach($customers as $customer){
  14. $orders=$customer->orders;
  15. //加上with('order')这时候遍历的时候就不需要再执行sql语句
  16. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注