directory search
阅读前篇 简介 Yii 是什么 从 Yii 1.1 升级 入门 安装 Yii 运行应用 第一次问候 使用Forms 数据库应用 使用 Gii 生成代码 进阶 应用结构 概述 入口脚本 应用(Applications) 应用组件(Application Components) 控制器(Controllers) 模型(Models) 视图(views) 模块(Modules) 过滤器(Filters) 小部件(Widgets) 前端资源(Assets) 扩展(Extensions) 请求处理 运行概述 启动引导(Bootstrapping) 路由和创建URL 请求(Requests) 响应(Responses) Sessions 和 Cookies 错误处理(Handling Errors) 日志(Logging) 关键概念 组件(Component) 属性(Property) 事件(Events) 行为(Behaviors) 配置(Configurations) 别名(Aliases) 类自动加载(Autoloading) 服务定位器(Service Locator) 依赖注入容器(Dependency Injection Container) 配合数据库工作 数据库访问 (Data Access Objects) 查询生成器(Query Builder) 活动记录(Active Record) 数据库迁移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用户数据 创建表单(Creating Forms) 输入验证(Validating Input) 文件上传(Uploading Files) 收集列表输入(Collecting Tabular Input) 多模型的复合表单(Getting Data for Multiple Models) 显示数据 格式化输出数据(Data Formatting) 分页(Pagination) 排序(Sorting) 数据提供器(Data Providers) 数据小部件(Data Widgets) 客户端脚本使用(Working with Client Scripts) 主题(Theming) 安全 认证(Authentication) 授权(Authorization) 处理密码(Working with Passwords) 客户端认证(Auth Clients) 最佳安全实践(Best Practices) 缓存 概述 数据缓存 片段缓存 页面缓存 HTTP 缓存 RESTfull Web服务 快速入门(Quick Start) 资源(Resources) 控制器(Controllers) 路由(Routing) 格式化响应(Response Formatting) 授权认证(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 错误处理(Error Handling) 开发工具 调试工具栏和调试器 使用Gii生成代码 生成API文档 测试 概述(Overview) 配置测试环境(Testing environment setup) 单元测试(Unit Tests) 功能测试(Function Tests) 验收测试(Acceptance Tests) 测试夹具(Fixtures) 高级专题 高级应用模板 创建自定义应用程序结构 控制台命令 核心验证器(Core Validators) 国际化 收发邮件 性能优化 共享主机环境 模板引擎 集成第三方代码 小部件 Bootstrap 小部件 Jquery UI 助手类 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
characters

使用数据库

使用数据库

本章节将介绍如何如何创建一个从数据表country中读取国家数据并显示出来的页面。为了实现这个目标,你将会配置一个数据库连接,创建一个活动记录类,并且创建一个操作及一个视图。

贯穿整个章节,你将会学到:

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

请注意,为了掌握本章你应该具备最基本的数据库知识和使用经验。尤其是应该知道如何创建数据库,如何通过数据库终端执行 SQL 语句。

准备数据库

首先创建一个名为yii2basic的数据库,应用将从这个数据库中读取数据。你可以创建 SQLite,MySQL,PostregSQL,MSSQL 或 Oracle 数据库,Yii 内置多种数据库支持。简单起见,后面的内容将以 MySQL 为例做演示。

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

CREATETABLE`country`(`code`CHAR(2)NOTNULLPRIMARYKEY,`name`CHAR(52)NOTNULL,`population`INT(11)NOTNULLDEFAULT'0')ENGINE=InnoDBDEFAULTCHARSET=utf8;INSERTINTO`country`VALUES('AU','Australia',18886000);INSERTINTO`country`VALUES('BR','Brazil',170115000);INSERTINTO`country`VALUES('CA','Canada',1147000);INSERTINTO`country`VALUES('CN','China',1277558000);INSERTINTO`country`VALUES('DE','Germany',82164700);INSERTINTO`country`VALUES('FR','France',59225700);INSERTINTO`country`VALUES('GB','United Kingdom',59623400);INSERTINTO`country`VALUES('IN','India',1013662000);INSERTINTO`country`VALUES('RU','Russia',146934000);INSERTINTO`country`VALUES('US','United States',278357000);

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

配置数据库连接

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

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

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

config/db/php是一个典型的基于文件的配置工具。这个文件配置了数据库连接 yii\db\Connection 的创建和初始化参数,应用的 SQL 查询正是基于这个数据库。

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

补充:config/db.php将被包含在应用配置文件config/web.php中,后者指定了整个应用如何初始化。请参考配置章节了解更多信息。

创建活动记录

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

namespaceapp\models;useyii\db\ActiveRecord;classCountryextendsActiveRecord{ }

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

补充:如果类名和数据表名不能直接对应,可以覆写 yii\db\ActiveRecord::tableName() 方法去显式指定相关表名。

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

useapp\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();

补充:活动记录是面向对象、功能强大的访问和操作数据库数据的方式。你可以在活动记录章节了解更多信息。除此之外你还可以使用另一种更原生的被称做数据访问对象的方法操作数据库数据。

创建操作

为了向最终用户显示国家数据,你需要创建一个操作。相比之前小节掌握的在site控制器中创建操作,在这里为所有和国家有关的数据新建一个控制器更加合理。新控制器名为CountryController,并在其中创建一个index操作,如下:

namespaceapp\controllers;useyii\web\Controller;useyii\data\Pagination;useapp\models\Country;classCountryControllerextendsController{publicfunctionactionIndex(){$query= Country::find();$pagination=newPagination(['defaultPageSize'=>5,'totalCount'=>$query->count(), ]);$countries=$query->orderBy('name') ->offset($pagination->offset) ->limit($pagination->limit) ->all();return$this->render('index', ['countries'=>$countries,'pagination'=>$pagination, ]); } }

把上面的代码保存在controllers/CountryController.php文件中。

index操作调用了活动记录Country::find()方法,去生成查询语句并从country表中取回所有数据。为了限定每个请求所返回的国家数量,查询在 yii\data\Pagination 对象的帮助下进行分页。Pagination对象的使命主要有两点:

  • 为 SQL 查询语句设置offsetlimit从句,确保每个请求只需返回一页数据(本例中每页是 5 行)。
  • 在视图中显示一个由页码列表组成的分页器,这点将在后面的段落中解释。

在代码末尾,index操作渲染一个名为index的视图,并传递国家数据和分页信息进去。

创建视图

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

useyii\helpers\Html;useyii\widgets\LinkPager;?>

Countries

    foreach($countriesas$country):?>
  • = Html::encode("{$country->name} ({$country->code})")?>:=$country->population?>
  • endforeach;?>
= LinkPager::widget(['pagination'=>$pagination])?>

这个视图包含两部分用以显示国家数据。第一部分遍历国家数据并以无序 HTML 列表渲染出来。第二部分使用 yii\widgets\LinkPager 去渲染从操作中传来的分页信息。小部件LinkPager显示一个分页按钮的列表。点击任何一个按钮都会跳转到对应的分页。

试运行

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

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

国家列表

首先你会看到显示着五个国家的列表页面。在国家下面,你还会看到一个包含四个按钮的分页器。如果你点击按钮 “2”,将会跳转到显示另外五个国家的页面,也就是第二页记录。如果观察仔细点你还会看到浏览器的 URL 变成了:

http://hostname/index.php?r=country/index&page=2

在这个场景里,yii\data\Pagination 提供了为数据结果集分页的所有功能:

  • 首先 yii\data\Pagination 把 SELECT 的子查询LIMIT 5 OFFSET 0数据表示成第一页。因此开头的五条数据会被取出并显示。
  • 然后小部件 yii\widgets\LinkPager 使用 yii\data\Pagination::createUrl() 方法生成的 URL 去渲染翻页按钮。URL 中包含必要的参数page才能查询不同的页面编号。
  • 如果你点击按钮 “2”,将会发起一个路由为country/index的新请求。yii\data\Pagination 接收到 URL 中的page参数把当前的页码设为 2。新的数据库请求将会以LIMIT 5 OFFSET 5查询并显示。

总结

本章节中你学到了如何使用数据库。你还学到了如何取出并使用 yii\data\Pagination 和 yii\widgets\LinkPager 显示数据。

下一章中你会学到如何使用 Yii 中强大的代码生成器 Gii,去帮助你实现一些常用的功能需求,例如增查改删(CRUD)数据表中的数据。事实上你之前所写的代码全部都可以由 Gii 自动生成。
Previous article: Next article: