1.3 Operations of sqlCon
数据库的连接已经实现了,具体的使用还没有进行封装。接下来进行链式操作的方法的封装,准备实现以下列表中的方法:
方法名 | 实现的功能 |
---|---|
table() | 指定要连接的表 |
field() | 指定要查询的字段 |
alias() | 别名 |
where() | 查询条件 |
join() | 关联 |
limit() | 查询数量限制 |
order() | 排序 |
group() | 分组 |
findAll() | 查询所有记录 |
findOne() | 查询单个记录 |
find() | 查询记录,数量由limit控制,默认全部 |
count() | 查询数量 |
sum() | 指定字段求和 |
value() | 查询指定字段的一条记录 |
column() | 查询指定字段的多条记录 |
insert() | 插入单条记录 |
insertAll() | 插入多条记录 |
update() | 数据更新 |
query() | 执行原生查询语句 |
execute() | 执行原生插入和更新语句 |
getDbError() | 获取本次数据库执行的错误信息 |
getSql() | 返回本次拼接后的完整SQL语句 |
Step1
:在core
下创建Db.php
,用于实现上述方法列表。主要的思想是在这些方法中接收参数,然后再在findAll/findOne/find/count/sum/value/column/insert/insertAll/update
等方法中组合得到需要执行的SQL
,再设定一个方法运行SQL
得到结果。以下是仅编写了find/findAll/findOne
之后的Db.php
:
<?php
namespace core;
use core\Config;
use core\db\Mysql;
class Db
{
public static $instance;
private static $dbCon;
public static $cfg;
private $tname;
private $fields = '';
private $alias;
private $condition;
private $join;
private $order;
private $limitStart;
private $limitEnd;
private function __construct()
{
// 装载配置文件
$config = new Config();
self::$cfg = $config->getConfig();
if (strtolower(self::$cfg['db_type']) == 'mysql') {
$mysqlCon = new Mysql(self::$cfg['db_host'], self::$cfg['db_user'], self::$cfg['db_passwd'], self::$cfg['db_name']);
self::$dbCon = $mysqlCon->getConnection();
}
}
private function __clone()
{
}
public static function getInstance()
{
if (self::$instance instanceof self) {
return self::$instance;
} else {
self::$instance = new Db();
return self::$instance;
}
}
public function table($tableName)
{
$this->tname = $tableName;
return $this;
}
public function field($fields)
{
if (is_array($fields)) {
$this->fields = implode(',', $fields);
} else {
$this->fields = $fields;
}
return $this;
}
public function alias($alias)
{
$this->alias = $alias;
return $this;
}
public function where($condition)
{
if (is_array($condition)) {
$this->condition = implode(' AND ', $condition);
} else {
$this->condition = ' ' . $condition . ' ';
}
return $this;
}
public function join($join)
{
$this->join = $join;
return $this;
}
public function limit($start, $end = 0)
{
$this->limitStart = $start;
$this->limitEnd = $end;
return $this;
}
public function order($order)
{
if (is_array($order)) {
$this->order = implode(',', $order);
} else {
$this->order = $order;
}
return $this;
}
/**
* 查询所有记录
*/
public function findAll()
{
$sql = $this->querySqlConcat('all');
$queryRes = $this->sqlQuery($sql);
return $this->formatQueryRes($queryRes);
}
/**
* 查询记录
*/
public function find()
{
$sql = $this->querySqlConcat('common');
$queryRes = $this->sqlQuery($sql);
return $this->formatQueryRes($queryRes);
}
/**
* 查询单条记录
*/
public function findOne()
{
$sql = $this->querySqlConcat('one');
// return $sql;
$queryRes = $this->sqlQuery($sql);
return $this->formatQueryRes($queryRes);
}
/**
* 拼接 query sql
*/
public function querySqlConcat($numLimit)
{
if ($this->tname == '') {
return '请指定要查询的数据表名称!';
}
if ($this->fields != '') {
$sql = 'SELECT ' . $this->fields . ' ';
} else {
$sql = 'SELECT * ';
}
$sql .= ' FROM ' . $this->tname . ' ';
if ($this->alias != '') {
$sql .= ' ALIAS ' . $this->alias . ' ';
}
if ($this->condition != '') {
$sql .= ' WHERE ' . $this->condition . ' ';
} else {
$sql .= ' WHERE 1=1 ' . ' ';
}
if ($this->order != '') {
$sql .= ' ORDER BY ' . $this->order . ' ';
}
switch ($numLimit) {
case 'all':
break;
case 'one':
$sql .= ' LIMIT 1 ';
break;
default:
if ($this->limitStart && $this->limitEnd) {
$sql .= ' LIMIT ' . $this->limitStart . ',' . $this->limitEnd . ' ';
} elseif ($this->limitStart) {
$sql .= ' LIMIT ' . $this->limitStart . ' ';
}
break;
}
return $sql;
}
/**
* 运行 query sql
*/
private function sqlQuery($sql)
{
return mysqli_query(self::$dbCon, $sql);
}
/**
* 格式化查询结果
*/
private function formatQueryRes($queryRes)
{
return $queryRes->fetch_all(MYSQLI_ASSOC);
}
}
Step2
:创建连接所用的测试数据表z_test
,SQL
语句如下:
DROP TABLE IF EXISTS `z_test`;
CREATE TABLE `z_test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`test_int` int(11) NOT NULL DEFAULT '0',
`test_char` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
INSERT INTO `z_test` VALUES ('1', '1', 'qwe');
INSERT INTO `z_test` VALUES ('2', '2', 'asd');
Step3
:修改App.php
的内容,尝试调用Db.php
,修改后的App.php
内容如下:
<?php
namespace core;
use core\Db;
class App
{
public static $cfg;
/**
* 框架运行入口
*/
public static function run()
{
$dbConnect = Db::getInstance();
$res = $dbConnect
->table('z_test')
->field(['id', 'test_int'])
->where('id > 0')
->order(['id ASC'])
->findAll();
return $res;
}
}
Step4
:刷新浏览器查看输出结果,预期如下:
array(2) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["test_int"]=>
string(1) "1"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["test_int"]=>
string(1) "2"
}
}
Step5
:可以尝试变换field/where/order/limit/findAll
等方法,观察不同的输出结果。到此,我们已经初步实现了数据库的连接和操作,上述表格中还有些方法尚未实现,待后续过程中慢慢完善。
项目结构
此时的项目目录结构:
start_php_framework [框架根目录]
├─ config [配置文件目录]
│ ├─ config.php [主配置文件]
│ └─ db.php [数据库配置文件]
├─ core [框架核心源码目录]
│ ├─ db [各类数据库驱动文件存储目录]
│ │ └─ Mysql.php [MySQL连接驱动]
│ ├─ App.php [应用启动文件]
│ ├─ Config.php [读取配置文件]
│ └─ Db.php [数据库操作文件]
├─ vendor [composer自有文件夹,将来存储第三方扩展]
│ ├─ composer [composer自有文件夹]
│ └─ autoload.php [自动加载关键文件,一定要在入口文件引用,且在App.php之前]
├─ web [框架入口]
│ └─ index.php [框架入口文件]
└─ composer.json [composer描述文件]