Yii2 Yes It is

Yii2 Yes It is

关于Yii

Yii 是什么

Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。 名字 Yii (读作 易)在中文里有“极致简单与不断演变”两重含义, 也可看作 Yes It Is! 的缩写。

Yii 版本

Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,现在处于维护状态。 2.0 版是一个完全重写的版本,采用了最新的技术和协议,包括依赖包管理器 ComposerPHP 代码规范 PSR命名空间Traits(特质)等等。 2.0 版代表新一代框架,是未来几年中我们的主要开发版本。

安装 Yii

  • 通过 Composer 安装
1
composer create-project --prefer-dist yiisoft/yii2-app-basic Yii2

验证安装的结果

当安装完成之后, 或配置你的Web服务器(看下面的文章)或使用内置Web Server, 当在项目 web 目录下可以通过下面的命令:

1
php yii serve

应用结构

  • Yii2 项目根目录
    • assets
    • commands 控制台命令类目录
    • config 应用配置及其它配置目录
      • console.php 控制台应用配置信息
      • web.php Web 应用配置信息
    • controllers 控制器类目录
    • mail 邮件类目录
    • models 模型类目录
    • runtime Yii 在运行时生成的文件,例如日志和缓存文件
    • tests 单元测试
    • vagrant
    • vendor 已经安装的 Composer 包,包括 Yii 框架自身
    • views 视图目录
    • web Web 应用根目录,包含 Web 入口文件
      • assets Yii 发布的资源文件(javascript 和 css)
      • index.php 应用入口文件
    • widgets
    • composer.json Composer 配置文件, 描述包信息
    • composer.lock
    • yii

一般来说,应用中的文件可被分为两类:在 basic/web 下的和在其它目录下的。 前者可以直接通过 HTTP 访问(例如浏览器),后者不能也不应该被直接访问。一般来说,应用中的文件可被分为两类:在 basic/web 下的和在其它目录下的。 前者可以直接通过 HTTP 访问(例如浏览器),后者不能也不应该被直接访问。

请求生命周期

    1. 用户提交指向 入口脚本 web/index.php的请求
    1. 入口脚本会加载 配置数组 并创建一个 应用 实例用于处理该请求
    1. 应用会通过 request(请求) 应用组件解析被请求的 路由
    1. 应用创建一个 controller(控制器) 实例具体处理请求
    1. 控制器会创建一个 action(动作) 实例并为该动作执行相关的 Filters(访问过滤器)
    1. 如果任何一个过滤器验证失败, 该动作会被取消
    1. 如果全部的过滤器都通过, 该动作就会被执行
    1. 动作后悔加载一个数据模型, 一般是从数据库中加载
    1. 动作后悔渲染一个View(视图), 并为其提供所需的数据模型
    1. 渲染得到的结果会返回给 response(响应) 应用组件
    1. 响应组件会把渲染结果发回给用户的浏览器

说声 Hello

这个章节,你将会掌握三件事:

  1. 如何创建一个动作去响应请求,
  2. 如何创建一个视图去构造响应内容,
  3. 以及一个应用如何分派请求给动作。

创建动作

操作必须声明在控制器中。为了简单起见, 你可以直接在 SiteController 控制器里声明 say 操作。 这个控制器是由文件 controllers/SiteController.php 定义的。以下是一个操作的声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
// ...现存的代码...

public function actionSay($message = 'Hello')
{
return $this->render('say', ['message' => $message]);
}
}

创建视图

视图是你用来生成响应内容的脚本。为了说 “Hello”, 你需要创建一个 say 视图,以便显示从操作方法中传来的 message 参数。

1
2
3
4
<?php
use yii\helpers\Html;
?>
<?= Html::encode($message) ?>

say 视图应该存为 views/site/say.php 文件。当一个操作中调用了 render() 方法时, 它将会按 views/控制器 ID/视图名.php 路径加载 PHP 文件。

试运行

创建完动作和视图后,你就可以通过下面的 URL 访问新页面了:

1
http://hostname/index.php?r=site/say&message=Hello+World

使用表单

这个章节,你将会掌握三件事:

  1. 创建一个模型代表用户通过表单输入的数据
  2. 声明规则去验证输入的数据
  3. 在视图中生成一个 HTML 表单

创建模型

模型类 EntryForm 代表从用户那请求的数据, 该类如下所示并存储在 models/EntryForm.php 文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace app\models;

use Yii;
use yii\base\Model;

class EntryForm extends Model
{
public $name;
public $email;

public function rules()
{
return [
[['name', 'email'], 'required'],
['email', 'email'],
];
}
}

创建动作

下面你得在 site 控制器中创建一个 entry 操作用于新建的模型。

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
28
<?php

namespace app\controllers;

use Yii;
use yii\web\Controller;
use app\models\EntryForm;

class SiteController extends Controller
{
// ...现存的代码...

public function actionEntry()
{
$model = new EntryForm;

if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// 验证 $model 收到的数据

// 做些有意义的事 ...

return $this->render('entry-confirm', ['model' => $model]);
} else {
// 无论是初始化显示还是数据验证错误
return $this->render('entry', ['model' => $model]);
}
}
}

表达式 Yii::$app 代表应用实例,它是一个全局可访问的单例。 同时它也是一个服务定位器, 能提供 requestresponsedb 等等特定功能的组件。 在上面的代码里就是使用 request 组件来访问应用实例收到的 $_POST 数据。

创建视图

最后创建两个视图文件 entry-confirmentry。 他们会被刚才创建的 entry 操作渲染。

entry-confirm 视图简单地显示提交的 nameemail 数据。视图文件应该保存在 views/site/entry-confirm.php

1
2
3
4
5
6
7
8
9
<?php
use yii\helpers\Html;
?>
<p>You have entered the following information:</p>

<ul>
<li><label>Name</label>: <?= Html::encode($model->name) ?></li>
<li><label>Email</label>: <?= Html::encode($model->email) ?></li>
</ul>

entry 视图显示一个 HTML 表单。视图文件应该保存在 views/site/entry.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'name') ?>

<?= $form->field($model, 'email') ?>

<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>

尝试下

用浏览器访问下面的 URL 看它能否工作:

1
http://hostname/index.php?r=site/entry

使用数据库

这个章节,你将会掌握四件事:

  1. 配置一个数据库连接
  2. 定义一个活动记录类
  3. 使用活动记录从数据库中查询数据
  4. 以分页方式在视图中显示数据

准备数据库

首先创建一个名为 yii2 的数据库,应用将从这个数据库中读取数据。

然后在数据库中创建一个名为 country 的表并插入简单的数据。可以执行下面的语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE `country` (
`code` CHAR(2) NOT NULL PRIMARY KEY,
`name` CHAR(52) NOT NULL,
`population` INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `country` VALUES ('AU','Australia',18886000);
INSERT INTO `country` VALUES ('BR','Brazil',170115000);
INSERT INTO `country` VALUES ('CA','Canada',1147000);
INSERT INTO `country` VALUES ('CN','China',1277558000);
INSERT INTO `country` VALUES ('DE','Germany',82164700);
INSERT INTO `country` VALUES ('FR','France',59225700);
INSERT INTO `country` VALUES ('GB','United Kingdom',59623400);
INSERT INTO `country` VALUES ('IN','India',1013662000);
INSERT INTO `country` VALUES ('RU','Russia',146934000);
INSERT INTO `country` VALUES ('US','United States',278357000);

此时便有了一个名为 yii2 的数据库,在这个数据库中有一个包含三个字段的数据表 country,表中有十行数据。

配置数据库连接

开始之前,请确保你已经安装了 PHP PDO 扩展和你所使用的数据库的 PDO 驱动(例如 MySQL 的 pdo_mysql)。 对于使用关系型数据库来讲,这是基本要求。

1
php -m // 查看即可

驱动和扩展安装可用后,打开 config/db.php 修改里面的配置参数对应你的数据库配置。 该文件默认包含这些内容:

1
2
3
4
5
6
7
8
9
<?php

return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
];

上面配置的数据库连接可以在应用中通过 Yii::$app->db 表达式访问。

创建活动记录

创建一个继承自活动记录类的类 Country, 把它放在 models/Country.php 文件,去代表和读取 country 表的数据。

1
2
3
4
5
6
7
8
9
<?php

namespace app\models;

use yii\db\ActiveRecord;

class A extends ActiveRecord
{
}

这个 Country 类继承自 yii\db\ActiveRecord。你不用在里面写任何代码。 只需要像现在这样,Yii 就能根据类名去猜测对应的数据表名。

使用 Country 类可以很容易地操作 country 表数据,就像这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use app\models\Country;

// 获取 country 表的所有行并以 name 排序
$countries = Country::find()->orderBy('name')->all();

// 获取主键为 “US” 的行
$country = Country::findOne('US');

// 输出 “United States”
echo $country->name;

// 修改 name 为 “U.S.A.” 并在数据库中保存更改
$country->name = 'U.S.A.';
$country->save();

创建动作

新控制器名为 CountryController,并在其中创建一个 index 操作, 如下:

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
28
29
30
31
32
33
<?php

namespace app\controllers;

use yii\web\Controller;
use yii\data\Pagination;
use app\models\Country;

class CountryController extends Controller
{
public function actionIndex()
{
$query = Country::find();

// 分页
$pagination = new Pagination([
'defaultPageSize' => 5,
'totalCount' => $query->count(),
]);

// 查询
$countries = $query->orderBy('name')
->offset($pagination->offset)
->limit($pagination->limit)
->all();

// 渲染
return $this->render('index', [
'countries' => $countries,
'pagination' => $pagination,
]);
}
}

创建视图

views 目录下先创建一个名为 country 的子目录。 这个目录存储所有由 country 控制器渲染的视图。在 views/country 目录下 创建一个名为 index.php 的视图文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
?>
<h1>Countries</h1>
<ul>
<?php foreach ($countries as $country): ?>
<li>
<?= Html::encode("{$country->name} ({$country->code})") ?>:
<?= $country->population ?>
</li>
<?php endforeach; ?>
</ul>

<?= LinkPager::widget(['pagination' => $pagination]) ?>

试运行

浏览器访问下面的 URL 看看能否工作:

1
http://hostname/index.php?r=country/index

打印SQL

1
2
3
4
5
6
7
8
9
10
11
// 1、查询结构
$record = Article::find()->joinWith('articleClass');

// 2、复制一下查询语句
$query = clone $record;

// 3、调用createComment()和getSql()方法
$sql = $query->createCommand()->getSql();

// 4、打印出来
var_dump($sql);die();

使用 Gii 生成代码

本章节, 你将学到:

  1. 在你的应用中开启 Gii
  2. 使用 Gii 去生成活动记录类
  3. 使用 Gii 去生成数据表操作的增查改删(CRUD)代码
  4. 自定义 Gii 生成的代码

开始 Gii

GiiYii 中的一个模块。 可以通过配置应用的 modules 属性开启它。通常来讲在 config/web.php 文件中会有以下配置代码:

1
2
3
4
5
6
7
8
$config = [ ... ];

if (YII_ENV_DEV) {
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
];
}

这段配置表明,如果当前是开发环境, 应用会包含 gii 模块,模块类是 yii\gii\Module

如果你检查应用的入口脚本 web/index.php, 将看到这行代码将 YII_ENV_DEV 设为 true

1
defined('YII_ENV') or define('YII_ENV', 'dev');

鉴于这行代码的定义,应用处于开发模式下,按照上面的配置会打开 Gii 模块。你可以直接通过 URL 访问 Gii

1
http://hostname/index.php?r=gii

信息: 如果你通过本机以外的机器访问 Gii,请求会被出于安全原因拒绝。 你可以配置 Gii 为其添加允许访问的 IP 地址:

1
2
3
4
'gii' => [
'class' => 'yii\gii\Module',
'allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*', '192.168.178.20'] // 按需调整这里
]

生成活动记录类

选择 “Model Generator” (点击 Gii 首页的链接)去生成活动记录类。并像这样填写表单:

  • Table Name: country
  • Model Class: Country

然后点击 “Preview” 按钮。你会看到 models/Country.php 被列在将要生成的文件列表中。可以点击文件名预览内容。

如果你已经创建过同样的文件,使用 Gii 会覆写它, 点击文件名旁边的 diff 能查看现有文件与将要 生成的文件的内容区别。

想要覆写已存在文件,选中 “overwrite” 下的复选框然后点击 “Generator”。如果是新文件,只点击 “Generator” 就好。

接下来你会看到一个包含已生成文件的说明页面。如果生成过程中覆写过文件, 还会有一条信息说明代码是重新生成覆盖的。

Generating code using template “/Users/caoxl/WWW/Yii2/vendor/yiisoft/yii2-gii/src/generators/model/default”…
overwrote models/Country.php
done!

生成 CRUD 代码

CRUD 代表增,查,改,删操作,这是绝大多数 Web 站点常用的数据处理方式。选择 Gii 中的 “CRUD Generator” (点击 Gii 首页的链接)去创建 CRUD 功能。本例 “country” 中需要这样填写表单:

  • Model Class: app\models\Country
  • Search Model Class: app\models\CountrySearch
  • Controller Class: app\controllers\CountryController

如果你之前创建过 controllers/CountryController.phpviews/country/index.php 文件(在指南的使用数据库章节), 选中 “overwrite” 下的复选框覆写它们(之前的文件没能全部支持 CRUD)。

Generating code using template “/Users/caoxl/WWW/Yii2/vendor/yiisoft/yii2-gii/src/generators/crud/default”…
overwrote controllers/CountryController.php
generated models/CountrySearch.php
generated views/country/_form.php
generated views/country/_search.php
generated views/country/create.php
overwrote views/country/index.php
generated views/country/update.php
generated views/country/view.php
done!

试运行

用浏览器访问下面的 URL 查看生成代码的运行:

1
http://hostname/index.php?r=country/index

下面列出由 Gii 生成的文件,以便你研习功能和实现, 或修改它们。

  • 控制器:controllers/CountryController.php
  • 模型:models/Country.phpmodels/CountrySearch.php
  • 视图:views/country/*.php

应用结构

入口脚本

入口脚本主要完成以下工作:

  • 定义全局常量;
  • 注册 Composer 自动加载器;
  • 包含 Yii 类文件;
  • 加载应用配置;
  • 创建一个应用实例并配置;
  • 调用 yii\base\Application::run() 来处理请求。

Web 应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

// 注册 Composer 自动加载器
require __DIR__ . '/../vendor/autoload.php';

// 包含 Yii 类文件
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';

// 加载应用配置
$config = require __DIR__ . '/../config/web.php';

// 创建、配置、运行一个应用
(new yii\web\Application($config))->run();
  • 当运行 入口脚本 处理请求时, 应用主体会经历以下生命周期:

    1. 入口脚本加载应用主体配置数组。
    1. 入口脚本创建一个应用主体实例:
    • 调用 preInit() 配置几个高级别应用主体属性, 比如 basePath
    • 注册 error handler 错误处理方法。
    • 配置应用主体属性。
    • 调用 init() 初始化,该函数会调用 bootstrap() 运行引导启动组件。
    1. 入口脚本调用 yii\base\Application::run() 运行应用主体:
    • 触发 EVENT_BEFORE_REQUEST 事件。
    • 处理请求:解析请求 路由 和相关参数; 创建路由指定的模块、控制器和动作对应的类,并运行动作。
    • 触发 EVENT_AFTER_REQUEST 事件。
    • 发送响应到终端用户。
    1. 入口脚本接收应用主体传来的退出状态并完成请求的处理。

过滤器

过滤器是 控制器动作 执行之前或之后执行的对象。

使用过滤器

过滤器本质上是一类特殊的 行为, 所以使用过滤器使用行为一样。 可以在控制器类中覆盖它的 behaviors() 方法来声明过滤器,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['index', 'view'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}

当一个动作有多个过滤器时,根据以下规则先后执行:

  • 预过滤
    • 按顺序执行应用主体中 behaviors() 列出的过滤器。
    • 按顺序执行模块中 behaviors() 列出的过滤器。
    • 按顺序执行控制器中 behaviors() 列出的过滤器。
    • 如果任意过滤器终止动作执行, 后面的过滤器(包括预过滤和后过滤)不再执行。
  • 成功通过预过滤后执行动作。
  • 后过滤
    • 倒序执行控制器中 behaviors() 列出的过滤器。
    • 倒序执行模块中 behaviors() 列出的过滤器。
    • 倒序执行应用主体中 behaviors() 列出的过滤器。

创建过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace app\components;

use Yii;
use yii\base\ActionFilter;

class ActionTimeFilter extends ActionFilter
{
private $_startTime;

public function beforeAction($action)
{
$this->_startTime = microtime(true);
return parent::beforeAction($action);
}

public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}

扩展

核心扩展

  • yiisoft/yii2-apidoc: 提供了一个可扩展的、高效的 API 文档生成器。核心框架的 API 文档也是用它生成的。
  • yiisoft/yii2-authclient: 提供了一套常用的认证客户端,例如 Facebook OAuth2 客户端、GitHub OAuth2 客户端。
  • yiisoft/yii2-bootstrap: 提供了一套挂件,封装了 Bootstrap 的组件和插件。
  • yiisoft/yii2-codeception: 提供了基于 Codeception 的测试支持。
  • yiisoft/yii2-debug: 提供了对 Yii 应用的调试支持。当使用该扩展是, 在每个页面的底部将显示一个调试工具条。 该扩展还提供了一个独立的页面,以显示更详细的调试信息。
  • yiisoft/yii2-elasticsearch: 提供对 Elasticsearch 的使用支持。它包含基本的查询/搜索支持, 并实现了 Active Record 模式让你可以将活动记录 存储在 Elasticsearch 中。
  • yiisoft/yii2-faker: 提供了使用 Faker 的支持,为你生成模拟数据。
  • yiisoft/yii2-gii: 提供了一个基于页面的代码生成器,具有高可扩展性,并能用来快速生成模型、 表单、模块、CRUD 等。
  • yiisoft/yii2-httpclient: 提供 HTTP 客户端。
  • yiisoft/yii2-imagine: 提供了基于 Imagine 的常用图像处理功能。
  • yiisoft/yii2-jui: 提供了一套封装 JQuery UI 的挂件以及它们的交互。
  • yiisoft/yii2-mongodb: 提供了对 MongoDB 的使用支持。它包含基本 的查询、活动记录、数据迁移、缓存、代码生成等特性。
  • yiisoft/yii2-queue: 通过队列异步提供运行任务的支持。 它支持基于 DB,Redis,RabbitMQ,AMQP,Beanstalk 和 Gearman 的队列。
  • yiisoft/yii2-redis: 提供了对 redis 的使用支持。它包含基本的 查询、活动记录、缓存等特性。
  • yiisoft/yii2-shell: 提供基于 psysh 的交互式 shell。
  • yiisoft/yii2-smarty: 提供了一个基于 Smarty 的模板引擎。
  • yiisoft/yii2-sphinx: 提供了对 Sphinx 的使用支持。它包含基本的 查询、活动记录、代码生成等特性。
  • yiisoft/yii2-swiftmailer: 提供了基于 swiftmailer 的邮件发送功能。
  • yiisoft/yii2-twig: 提供了一个基于 Twig 的模板引擎。

以下官方扩展适用于 Yii 2.1 及以上版本。 您不需要为 Yii 2.0 安装它们,因为它们包含在核心框架中。

  • yiisoft/yii2-captcha: 提供 CAPTCHA。
  • yiisoft/yii2-jquery: 为 jQuery 提供支持。
  • yiisoft/yii2-maskedinput: 提供基于 jQuery Input Mask plugin 的格式化输入小部件。
  • yiisoft/yii2-mssql: 提供对使用 MSSQL 的支持。
  • yiisoft/yii2-oracle: 提供对使用 Oracle 的支持。
  • yiisoft/yii2-rest: 提供对 REST API 的支持。

请求处理

请求

请求参数

要获取请求参数,你可以调用 request 组件的 get() 方法和 post() 方法。 他们分别返回 $_GET$_POST 的值。例如,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$request = Yii::$app->request;

$get = $request->get();
// 等价于: $get = $_GET;

$id = $request->get('id');
// 等价于: $id = isset($_GET['id']) ? $_GET['id'] : null;

$id = $request->get('id', 1);
// 等价于: $id = isset($_GET['id']) ? $_GET['id'] : 1;

$post = $request->post();
// 等价于: $post = $_POST;

$name = $request->post('name');
// 等价于: $name = isset($_POST['name']) ? $_POST['name'] : null;

$name = $request->post('name', '');
// 等价于: $name = isset($_POST['name']) ? $_POST['name'] : '';

请求方法

你可以通过 Yii::$app->request->method 表达式来获取当前请求使用的HTTP方法。

1
2
3
4
5
6
$request = Yii::$app->request;

if ($request->isAjax) { /* 该请求是一个 AJAX 请求 */ }
if ($request->isGet) { /* 请求方法是 GET */ }
if ($request->isPost) { /* 请求方法是 POST */ }
if ($request->isPut) { /* 请求方法是 PUT */ }

请求URLs

假设被请求的 URLhttp://example.com/admin/index.php/product?id=100, 你可以像下面描述的那样获取 URL 的各个部分:

  • url:返回 /admin/index.php/product?id=100, 此 URL 不包括主机信息部分。
  • absoluteUrl:返回 http://example.com/admin/index.php/product?id=100, 包含host info的整个URL。
  • hostInfo:返回 http://example.com, 只有主机信息部分。
  • pathInfo:返回 /product, 这个是入口脚本之后,问号之前(查询字符串)的部分。
  • queryString:返回 id=100,问号之后的部分。
  • baseUrl:返回 /admin,主机信息之后, 入口脚本之前的部分。
  • scriptUrl:返回 /admin/index.php,没有路径信息和查询字符串部分。
  • serverName:返回 example.com,URL 中的主机名。
  • serverPort:返回 80,这是 web 服务中使用的端口。

响应

状态码

1
Yii::$app->response->statusCode = 200;

尽管如此,大多数情况下不需要明确设置状态码, 因为 yii\web\Response::$statusCode 状态码默认为 200, 如果需要指定请求失败,可抛出对应的 HTTP 异常,如下所示:

1
throw new \yii\web\NotFoundHttpException;

HTTP 头部

可在 response 组件中操控 header collection 来发送 HTTP 头部信息, 例如:

1
2
3
4
5
6
7
8
9
10
$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\web\Response::$content 属性, 例如:

1
Yii::$app->response->content = 'hello world!';

发送响应

yii\web\Response::send() 方法调用前响应中的内容不会发送给用户, 该方法默认在 yii\base\Application::run() 结尾自动调用,尽管如此,可以明确调用该方法强制立即发送响应。

yii\web\Response::send() 方法使用以下步骤来发送响应:

  1. 触发 yii\web\Response::EVENT_BEFORE_SEND 事件。
  2. 调用 yii\web\Response::prepare() 来格式化 response dataresponse content
  3. 触发 yii\web\Response::EVENT_AFTER_PREPARE 事件。
  4. 调用 yii\web\Response::sendHeaders() 来发送注册的HTTP头
  5. 调用 yii\web\Response::sendContent() 来发送响应主体内容
  6. 触发 yii\web\Response::EVENT_AFTER_SEND 事件。

Sessions 和 Cookies

Sessions

开启和关闭 Sessions
1
2
3
4
5
6
7
8
9
10
11
12
13
$session = Yii::$app->session;

// 检查session是否开启
if ($session->isActive) ...

// 开启session
$session->open();

// 关闭session
$session->close();

// 销毁session中所有已注册的数据
$session->destroy();
访问 Session 数据
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
$session = Yii::$app->session;

// 获取session中的变量值,以下用法是相同的:
$language = $session->get('language');
$language = $session['language'];
$language = isset($_SESSION['language']) ? $_SESSION['language'] : null;

// 设置一个session变量,以下用法是相同的:
$session->set('language', 'en-US');
$session['language'] = 'en-US';
$_SESSION['language'] = 'en-US';

// 删除一个session变量,以下用法是相同的:
$session->remove('language');
unset($session['language']);
unset($_SESSION['language']);

// 检查session变量是否已存在,以下用法是相同的:
if ($session->has('language')) ...
if (isset($session['language'])) ...
if (isset($_SESSION['language'])) ...

// 遍历所有session变量,以下用法是相同的:
foreach ($session as $name => $value) ...
foreach ($_SESSION as $name => $value) ...

Cookies

读取 Cookies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 从 "request" 组件中获取 cookie 集合(yii\web\CookieCollection)
$cookies = Yii::$app->request->cookies;

// 获取名为 "language" cookie 的值,如果不存在,返回默认值 "en"
$language = $cookies->getValue('language', 'en');

// 另一种方式获取名为 "language" cookie 的值
if (($cookie = $cookies->get('language')) !== null) {
$language = $cookie->value;
}

// 可将 $cookies 当作数组使用
if (isset($cookies['language'])) {
$language = $cookies['language']->value;
}

// 判断是否存在名为 "language" 的 cookie
if ($cookies->has('language')) ...
if (isset($cookies['language'])) ...
发送 Cookies
1
2
3
4
5
6
7
8
9
10
11
12
13
// 从 "response" 组件中获取 cookie 集合(yii\web\CookieCollection)
$cookies = Yii::$app->response->cookies;

// 在要发送的响应中添加一个新的 cookie
$cookies->add(new \yii\web\Cookie([
'name' => 'language',
'value' => 'zh-CN',
]));

// 删除一个 cookie
$cookies->remove('language');
// 等同于以下删除代码
unset($cookies['language']);

错误处理

Yii 内置了一个 error handler 错误处理器,它使错误处理更方便, Yii错误处理器做以下工作来提升错误处理效果

使用错误处理器

error handler 注册成一个名称为errorHandler应用组件, 可以在应用配置中配置它类似如下:

1
2
3
4
5
6
7
return [
'components' => [
'errorHandler' => [
'maxSourceLines' => 20,
],
],
];

日志

日志消息

记录日志消息就跟调用下面的日志方法一样简单:

  • Yii::trace():记录一条消息去跟踪一段代码是怎样运行的。这主要在开发的时候使用。
  • Yii::info():记录一条消息来传达一些有用的信息。
  • Yii::warning():记录一个警告消息用来指示一些已经发生的意外。
  • Yii::error():记录一个致命的错误,这个错误应该尽快被检查。

Restful web 服务

助手类

Array 助手(ArrayHelper)

获取值(Getting Values)

1
$value = ArrayHelper::getValue($array, 'foo.bar.name');

设定值(Setting values)

1
2
3
4
5
6
7
8
9
$array = [
'key' => [
'in' => ['k' => 'value']
]
];

ArrayHelper::setValue($array, 'key.in', ['arr' => 'val']);
// 在 `$array` 中写入值的路径可以被指定为一个数组
ArrayHelper::setValue($array, ['key', 'in'], ['arr' => 'val']);

检查键名的存在(Checking Existence of Keys)

1
2
3
4
5
6
7
8
9
10
11
$data1 = [
'userName' => 'Alex',
];

$data2 = [
'username' => 'Carsten',
];

if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
echo "Please provide username.";
}

多维排序(Multidimensional Sorting)

1
2
3
4
5
6
$data = [
['age' => 30, 'name' => 'Alexander'],
['age' => 30, 'name' => 'Brian'],
['age' => 19, 'name' => 'Barney'],
];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);

对象转换为数组(Converting Objects to Arrays)

1
2
3
4
5
6
7
8
9
10
11
12
13
$posts = Post::find()->limit(10)->all();
$data = ArrayHelper::toArray($posts, [
'app\models\Post' => [
'id',
'title',
// the key name in array result => property name
'createTime' => 'created_at',
// the key name in array result => anonymous function
'length' => function ($post) {
return strlen($post->content);
},
],
]);

Html 助手(Html)

生成标签(Generating Tags)

1
<?= Html::tag('p', Html::encode($user->name), ['class' => 'username']) ?>

生成 CSS 类和样式(Forming CSS Classes and Styles)

1
2
3
4
5
6
7
8
9
10
$options = ['class' => 'btn btn-default'];

if ($type === 'success') {
Html::removeCssClass($options, 'btn-default');
Html::addCssClass($options, 'btn-success');
}

echo Html::tag('div', 'Pwede na', $options);

// in case of $type of 'success' it will render

创建表单(Creating Forms)

1
<?= Html::beginForm(['order/update', 'id' => $id], 'post', ['enctype' => 'multipart/form-data']) ?>

Url 助手(Url)

获得通用 URL(Getting Common URLs)

有两种获取通用 URLS 的方法 :当前请求的 home URLbase URL

  • 为了获取 home URL ,使用如下代码:
1
2
3
$relativeHomeUrl = Url::home();
$absoluteHomeUrl = Url::home(true);
$httpsAbsoluteHomeUrl = Url::home('https');
  • 如下代码可以获得当前请求的 base URL
1
2
3
$relativeBaseUrl = Url::base();
$absoluteBaseUrl = Url::base(true);
$httpsAbsoluteBaseUrl = Url::base('https');

创建 URLs(Creating URLs)

1
$url = Url::toRoute(['product/view', 'id' => 42]);

记住 URLs(Remember URLs)

1
2
3
4
5
6
7
8
// 记住当前 URL 
Url::remember();

// 记住指定的 URL。参数格式请参阅 Url::to()。
Url::remember(['product/view', 'id' => 42]);

// 记住用给定名称指定的 URL
Url::remember(['product/view', 'id' => 42], 'product');

检查相对 URLs(Checking Relative URLs)

1
$isRelative = Url::isRelative('test/it');

参考

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2023 Keep It Simple And Stupid All Rights Reserved.

访客数 : | 访问量 :