分享好友 编程语言首页 频道列表

yii2的数据库层设计

PHP教程  2017-02-05 19:200

Yii2在M层的抽象做的很经典,值得分析理解。

QueryBuilder

不同的数据库引擎(mysql,oracle…)执行相同的SQL,可能语法有一些细微的差异,但是SQL整体语法差别不大,所以会定义一个QueryBuilder基类,它提供一般通用的SQL生成方法,具体每个数据库引擎继承QueryBuilder,如果存在细微差异只需覆盖特定的方法既可。

简单说,QueryBuilder用来构造SQL语句(读SQL和写SQL都可以),但是并不执行它,通过调用它的where,groupBy,orderBy,select,insert等方法传入结构化的语句组成部分,最终由QueryBuilder返回一个字符串的SQL语句。

Query

仅提供查询能力,不支持修改,它也提供where,groupBy,select等方法(注意不支持insert,update这种修改操作),但是它本身没有生成SQL的能力,仅仅是在QueryBulder之上提供一个通用层,最终在调用它的one或者all方法时会将SQL的各个组成部分一次性交给QueryBuilder构造出SQL语句,那么Query对象怎么知道用哪个QueryBuilder呢?

Query对象会通过application->get(“db”)拿到配置的数据库连接connection对象,这个connection对象自然是知道自己连接的是哪种数据库引擎,因此可以通过它拿到对应的queryBuilder对象。具体来说,connection对象创建时会从配置中取到这样的配置:

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

Connection对象根据dsn知道对应的数据库引擎,从而创建对应的schema对象:

public $schemaMap = [
    'pgsql' => 'yii\db\pgsql\Schema', // PostgreSQL
    'mysqli' => 'yii\db\mysql\Schema', // MySQL
    'mysql' => 'yii\db\mysql\Schema', // MySQL
    'sqlite' => 'yii\db\sqlite\Schema', // sqlite 3
    'sqlite2' => 'yii\db\sqlite\Schema', // sqlite 2
    'sqlsrv' => 'yii\db\mssql\Schema', // newer MSSQL driver on MS Windows hosts
    'oci' => 'yii\db\oci\Schema', // Oracle driver
    'mssql' => 'yii\db\mssql\Schema', // older MSSQL driver on MS Windows hosts
    'dblib' => 'yii\db\mssql\Schema', // dblib drivers on GNU/Linux (and maybe other OSes) hosts
    'cubrid' => 'yii\db\cubrid\Schema', // CUBRID
];

而这个Schema对象是每个数据库引擎各自实现的,它们有一个方法可以返回对应的QueryBuilder对象:

/**
* @return QueryBuilder the query builder for this connection.
*/
public function getQueryBuilder()
{
    if ($this->_builder === null) {
        $this->_builder = $this->createQueryBuilder();
    }
 
    return $this->_builder;
}

但是需要注意,虽然经过QueryBuilder生成了SQL,但是Query并不是自己直接执行这个SQL,而是将这个任务交给了下面这个类。

Command

这个类需要由connection对象创建的,内部保存了从connection对象取来的pdo数据库连接。command类的定位是直接执行SQL,也提供bind参数的能力,它不再限制SQL是读还是写,这也是为什么Query类不直接使用connection的pdo连接执行读SQL而是把构造来的SQL交给command,因为command类才是负责执行所有SQL的合适角色,职责集中在Command对象是一个合理的设计。

根据这个认识,我们知道Command类可以直接执行裸SQL,读和写都是可以的。

ActiveQuery

之前的Query算一个调度者,它从用户收集查询的组成要素,交给QueryBuilder生成SQL,最后交给Command完成SQL的执行,拿回来的结果都是数组形式的一行一行的数据。

ActiveQuery则是在Query基础上(继承自Query),额外提供了ORM能力,主要包含2点:数据库行映射为对象(就是指ActiveRecord,也是一个model),以及表的关联关系。

我们知道Query的one和all都是返回关联数组形式的结果集,而ActiveRecord则覆盖了这两个方法,为每一行数据生成对应的activeRecord对象并把列值填充到对象里,这样就实现了数据库行和程序对象的自动映射,大概就是这种关系了。

查看更多关于【PHP教程】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
Perl操作Mysql数据库 perl操作excel
一. 安装DBI模块步骤1:从TOOLS栏目中下载DBI.zip,下载完后用winzip解开到一个temp目录,共有三个文件:ReadmeDBI.ppdDBI.tar.gz步骤2: 在DOS窗口下,temp目录中运行下面的DOS命令:ppm install DBI.ppd 如果提示无效命令,可在perl/bin目录下运行 二. 安装DBD

0评论2023-02-09348

在OS X系统中配置Ruby on Rails使其可以访问Sql Server数据库
经过大半天的折腾,终于可以让RoR在OS X系统里访问Sql Server数据库了。这里记录一下操作的过程,免得以后忘了。第一步,安装FreeTDS从FreeTDS的官网上下载最新的稳定版的压缩包,然后,遵照这里的说明进行手工编译(好怀念微软的Setup.exe和*.msi啊),其中

0评论2023-02-09433

Mysql数据库一个小程序实现自动创建分表。
每当跨月的时候也是系统出问题最多的时候,没有表和字段缺失是两个最常见的错误。为了解决这个问题,研究了一下mysql的 information_schema 表:information_schema这张数据表保存了MySQL服务器所有数据库的信息。如数据库名,数据库的表,表栏的数据类型与访

0评论2023-02-09699

Delphi中多线程下使用使用 UniDAC+MSSQL 需要注意的问题(连接前调用CoInitialize)
一般解决方法是在线程开始启用 CoInitialize(nil),线程结束调用 CoUninitialize 。如果你使用多种数据库连接,比如三层中经常切换到MSSQL和Oracle,我们只需在判断 TUniConnection 的连接前事件 OnBeforeConnect 写下如下代码:  [delphi] view plain co

0评论2023-02-09466

Delphi XE中使用dbExpress连接MySQL数据库疑难问题解决(对三层的例子配置有帮助)
Delphi IDE中包含一个Data Explorer的组件,如下图所示:  该组件基于dbExpress(包含TSQLConnection、TSQLDataSet、TSQLQuery、TSQLStoredProc、TSQLTable、TsqlServerMethod、TSQLMonitor、TSimpleDataSet)。但是因为该组件只提供了各种数据库的抽象驱动

0评论2023-02-09410

DELPHI 10.2 TOKYO搭建LINUX MYSQL开发环境
DELPHI 10.2 TOKYO搭建LINUX MYSQL开发环境笔者使用ubuntu64位LINUX首先必须保证LINUX可以连互联网。安装MYSQLsudo apt-get update sudo apt-get install mysql-serversudo apt-get install mysql-clientsudo apt-get install libmysqlclient-dev复制MYSQL的

0评论2023-02-09635

delphi 连接PostgreSQL
最近使用PostgreSQL开始一个工具。借用以前的项目,使用delphi 6开发工具因此需要delphi 6能访问PostgreSQL 9.0.3推荐开源的ZEOSDBO 库安装方法:ZEOSDBO-6.6.6-stable.zip解压到delphi的安装文件夹的imports下然后打开packages下的delphi6然后打开ZComponent

0评论2023-02-09942

delphi操作sqlite3
Delphi SQLite 简明无废话上手指南SQLite下载http://www.sqlite.org/download.htmlSQLite FAQhttp://www.sqlitecn.org/faq.htmlSQLite中文论坛http://sqlite.com.cn/bbs/index.aspSQLite入门与分析http://www.cnblogs.com/hustcat/archive/2009/02/12/1389

0评论2023-02-09889

Centos7上安装MySQL5.5报错,/usr/bin/perl is needed by MySQL-server.rpm
今天在Centos7上安装MySQL5.5时报了如下错/usr/bin/perl is needed by MySQL-server-...按照网上的几种说法进行了尝试1、在perl官网下载perl后安装到相应的目录下,仍无法解决问题2、采用强制安装 rpm -ivh MySQL-server-5.6.22-1.el6.i686.rpm --nodeps 

0评论2023-02-09740

Perl/C#连接Oracle/SQL Server和简单操作 perl查找字符串
连接数据库是一个很常见也很必须的操作。先将我用到的总结一下。1. Perl 连接数据库Perl 连接数据库的思路都是:1)使用DBI模块; 2)创建数据库连接句柄dbh; 3)利用dbh创建语句句柄sth; 4)利用sth执行sql语句; 5)利用sth处理数据。连接Oracle:my $dbh

0评论2023-02-09547

数据库服务器 之 在Linux下使用perl通过unixODBC连接SQLServer2000
作者:tonyvicky来自:LinuxSir.Org摘要:MS从来没有提供过SQLServer for Linux,所以大家也不要去尝试在Linux系统安装SQLServer,但是可以通过ODBC连接Windows系统的SQLServer数据库;目录一、关于测试环境及Linux连接SQL Server 的说明;二、下载相关软件 uni

0评论2023-02-09326

用perl做数据库迁移,从MSSQL到MYSQL(三)--V1.1版~多线程+handlerSocket
从前边的程序的运行情况来看,程序是可以运行的,但速度太扯了,在读写1000W条之前速度还是可以的(大概2000条/秒左右),但过了1000W之后(变成400条/秒左右),当然这个与SQL SERVER读取,网络还有服务器等性能都是有关系的,但,这速度,不晓得有测试过的

0评论2023-02-09304

cocos2d-x 添加sqlite3 时 报 lua_Number 错误
1 f:\cocos2d-x\cocos2d-x\external\lua\lua\lua.h(99) : 参见“lua_Number”的声明1f:\cocos2d-x\cocos2d-x\external\sqlite3-ext\lsqlite3.c(1272): error C2146: 语法错误: 缺少“;”(在标识符“n”的前面)1f:\cocos2d-x\cocos2d-x\external\sqlite3-ext\l

0评论2023-02-09914

SQL Server数据库(SQL Sever语言 函数以及SQL编程)
1、数学函数:操作一个数据,返回一个结果--去上限: ceiling ☆select ceiling(price) from car--去下限:floor ☆select floor(price) from car--ABS 绝对值--PI(),圆周率,括号里不加任何东西--round() 四舍五入 ☆select round(3.76 ,0)--sqrt() 开根号--

0评论2023-02-09951

更多推荐