Yii2.0笔记
整理的时候真尴尬,这笔记是去年记的,那会儿很多程序员之间的约定还不知道,结果我相当于重新理了一遍格式——所以:烂代码不一定不能用,一定很难看。
使用前提
- 前往Config文件夹,修改web.php,给cookieValidationKey添加一个值,用于加密数据。
- 前往Controller文件夹,创建
HelloController
控制器。注意UTF-8格式文件的BOM头。
调用及命名
路由:locallearn.cn/Yii/basic/web/?r=hello/index
// 文件开头
namespace app\controllers;
use yii\web\Controller;
// 非蓝色为强制命名,蓝色为自由命名,注意与地址栏对应。
class HelloController extends Controller{
public function actionIndex(){}
}
全局类YII
这是Yii框架中的一个全局类,包含了所学的请求组件、响应处理、Session处理、Cookie处理等组件。
请求处理
$req = /YII::$app->request;
// 获取$_GET['id']参数
// echo $req->get('id');
// 无参传输,可get('id', 20)设置默认
(/YII::$app->request):
- get方法,获取get传输的参数;post同似。
- isGet方法,类似isset函数;isPost同似。
- userIP方法:获取用户IP
响应处理
$res = \YII::$app->response;
处理结果打包为消息,响应组件处理响应。
statusCode方法:状态码,将页面处理结果认为改变,处理成功默认为200
headers方法:与头部打交道。
(YII::$app->response)->headers->add('pragma', 'no-cache')
headers->add方法增加头部设置,并初始化,(‘location’,’URL’)可以指向跳转;headers->set方法设置具体值;headers->remove方法移除头部设置,譬如pragma。pragma一般与浏览器缓存打交道,参数可设置为no-cache不缓存、max-age=Number缓存时间。
// 跳转
// headers->add(‘location’,’URL’);
// YII的Controller类提供了redirect方法
// $this->redirect(‘http://www.baidu.com’, 404);
// 文件下载
// $res->headers->add('content-disposition', 'attachment; filename="abc.i"');
// $res->sendFile('robots.txt');
Session处理
$session = \YII::$app->session;
//开启Session
$session->open();
// 判断Session开启
// if ($session->isActive) {
// echo "session is active";
// }
// 存放/取出/删除数据
// $session->set('user', '杭三');
// echo $session->get('user');
// $session->remove('user');
// 数组方式
// $session['user'] = '张三';
// echo "$session['user']";
// unset($session['user']);
Cookie处理
use yii\web\Cookie;
Cookie处理-生成、删除
$cookies = \YII::$app->response->cookies;
// 增加Cookie
$cookie_data = array('name' => 'user', 'value' => '乳白');
$cookies->add(new cookie($cookie_data));
// 删除Cookie
$cookies->remove('user');
Cookie处理-获取
$cookies = \YII::$app->request->cookies;
//从请求中取出Cookie,并在Cookie不存在时,设置默认值
// echo $cookies->getValue('user');
// echo $cookies->getValue('userNull', 'Cookie获取失败');
视图-创建
文档位置:Yii\basic\views\site_name(专门存放HTML、CSS、JS等代码)
文件位置:YII\basic\views\ControllerName\index.php
// 调用视图
return $this->renderPartial(‘index’);
视图-传参
/* HelloController.php */
$hello = 'Hello God!';
$hellos = array(5002, 2345);
//创建一个数组,将需要传递给视图的数据放到数组中。
$data = array('view_hello' => $hello, 'view_hellos' => $hellos);
// 调用视图
return $this->renderPartial('index.htm.php', $data);
/* view的index.php */
<h1><?=$view_hello; ?></h1>
<p><?=$view_hellos[0]; ?></p>
视图-安全
本部分未提及的代码,同上所述。
/* HelloController.php */
$hello = 'Hello God!<script>alert(3)</script>';
/* view的index.php */
<?php
//格式化可执行文本
use yii\helpers\Html;
//清理可执行文本
use yii\helpers\HtmlPurifier;
?>
<h1><?=Html::encode($view_hello); ?></h1>
<h1><?=HtmlPurifier::process($view_hello); ?></h1>
视图-分离
布局负责样式部分,内容负责内容部分。文档位置:Yii\basic\views\layouts(专门存放布局)
文件位置:YII\basic\views\layouts\common.php
/* HelloController.php */
public $layout = 'common'; // 调用common.php布局文件
public function actionIndex(){
// 调用视图
return $this->render('index'); // 将index.php文件里的内容,放置于$content
}
/* view的index.php */
hello index
/* common.php */
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<?=$content; ?>
</body>
</html>
视图-嵌套
/* HelloController.php */
// 调用视图
return $this->renderPartial('index.htm.php');
/* view的index.php */
<h1>hello index</h1>
<?php echo $this->render('about.htm.php', array('ar' => 8808)); ?>
/* view的about.php */
<h1>hello about</h1>
<?=$ar; ?>
视图-数据块
/* view的index.php */
<?php $this->beginBlock('block1'); ?>
<h1>Index</h1>
<p>……<p>
<?php $this->endBlock(); // 定义了一个数据块 ?>
/* common.php */
<body>
<?=$this->blocks['block1']; ?>
<?=$content; ?>
</body>
数据模型-配置
类似于PDO的初始化。
// 文件位置:Yii\basic\config\db.php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=rimworld',
'username' => 'rimworld',
'password' => 'nzOM80smKI',
'charset' => 'utf8',
];
数据模型-创建
文件位置:Yii\basic\models\Player.php
namespace app\models;
use yii\db\ActiveRecord;
class Player extends ActiveRecord
{
}
数据模型-单表查询
/* HelloController.php */
namespace app\controllers;
use yii\web\Controller;
use app\models\Player;
class HelloController extends Controller {
public function actionIndex() {
// 普通查询
$sql = 'select * from player where id=:id';
$results = Player::findBySql($sql, array(':id'=>'1 or 1=1'))->all(); // Yii自动防止SQL注入
print_r($results);
// 简洁查询
$results = Player::find()->WHERE(['id'=>1])->all();
print_r($results);
// ID > 0
$results = Player::find()->WHERE(['>', 'id', 0])->all();
print($results);
// 2 >= ID >= 1
$results = Player::find()->WHERE(['between', 'id', 1, 2])->all();
print_r(count($results));
// nickname like "%测试%"
$results = Player::find()->WHERE(['like', 'nickname', '测试'])->all();
print_r(count($results));
// 关于查询语句格式,具体内容参考Yii 2.0文档“Class yii\db\ActiveRecord”
}
}
数据模型-内存优化
/* HelloController.php */
// 查询结果转化成数组,数组相对于对象占内存更小
$results = Player::find()->WHERE(['like', 'nickname', '测试'])->asArray()->all();
print_r($results);
// 批量查询,第一次批量查询完毕,会清理内存,然后进行第二批查询,循环往复
// 每次到数据库里拿2条数据
foreach (Player::find()->batch(2) as $tests) { print_r(count($tests)); }
【数据模型-单表删除】:
/* HelloController.php */
// 普通删除
$results = Player::find()->WHERE(['id'=>1])->all();
$results[0]->delete();
// 简洁删除
Player::deleteAll('id>:id', array(':id'=>0));
数据模型-单表添加
/* HelloController.php */
// 增加
$test = new Player;
$test->id = 4;
$test->nickname = '测试者3';
$test->validate(); //使用验证器来确认数据合法性,具体内容参考Yii文档“核心验证器”
if ($test->hasErrors()) {
echo 'data is error';
die;
}
$test->save();
/* Player.php */
public function rules() {
// 验证器
return [
['id', 'integer'],
['title', 'string', 'length'=>[0,5]]
]
}
数据模型-单表修改
/* HelloController.php */
// 修改
$test = Player::find()->WHERE(['id'=>3])->one(); // One方法是All方法的简化
$test->nickname = '测试者Sis';
$test->save();
数据模型-关联查询
/* HelloController.php */
namespace app\controllers;
use yii\web\Controller;
use app\models\Customer;
use app\models\Order;
class HelloController extends Controller {
public function actionIndex() {
// 根据顾客,查询其订单
$customer = Customer::find()->WHERE(['name'=>'张三'])-one();
// $order = $customer->hasMany('app\models\Order', ['customer_id'=>'id'])->asArray()->all();
// $order = $customer->hasMany(Order::className(), ['customer_id'=>'id'])->asArray()->all(); // 修改点1
// $order = $customer->getOrders(); // 修改点2
$order = $customer->orders; // 修改点3
print_r($order);
}
}
// 根据订单,查询对应顾客
$order = Order::find()->WHERE(['id'=>1])->one();
$customer = $order->customer;
print_r($customer);
/* Customer.php,头部分与Player.php相同 */
// 修改点2
public function getOrders() {
// 获取订单信息
// $orders = $this->customer->hasMany(Order::className(), ['customer_id'=>'id'])->asArray()->all();
$orders = $this->customer->hasMany(Order::className(), ['customer_id'=>'id'])->asArray();// 修改点3。Yii中的__get,自动在其后添加->all(),对应hasMany
return $orders;
}
/* Order.php,头部分与Player.php相同 */
class Order extends ActiveRecord
{
// 获取顾客信息
public function getCustomer(){
return $this->hasOne(Customer::className(), ['id'=>'customer_id'])->asArray(); //Yii自动补one方法,对应hasOne
}
}
数据模型-关联查询的Tip与优化
第1+N次关联查询会读取首次查询的缓存,中间如果有所修改,就无法显现出来,可unset($customer->orders);
使用清理掉查询的缓存,然后再进行查询。
使用Foreach
进行多N次查询时,Class::find()->with(‘order’)->all();
可将N次查询简化为2次查询。