phalapi-入门篇5(数据库操作和Model层)

#phalapi-入门篇5(数据库操作和Model层)#

##前言## 先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个优秀的开源框架.

本小节主要讲解基于notorm的数据库操作以及使用Model层进行快速的数据层的开发,请确保装有PDO拓展.

附上:

官网地址:http://www.phalapi.net/

开源中国Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release

##1. 基于PDO的notorm进行的数据库操作##

phalapi的数据库操作是使用的开源的notorm进行的,notorm是基于PDO链接数据库,在框架内部默认链接的是mysql数据库,如需修改链接其他数据库请修改 /PhalApi/PhalApi/DB/NotORM.php中的getPdo方法:

 $dsn = sprintf('mysql:dbname=%s;host=%s;port=%d',
                $dbCfg['name'], 
                isset($dbCfg['host']) ? $dbCfg['host'] : 'localhost', 
                isset($dbCfg['port']) ? $dbCfg['port'] : 3306
            );

再讲之前其实这里是有一个坑的,机智的童鞋应该发现了框架自带的user数据库里面有一个以from命名字段,应为在notorm生成sql语句的时候不会给自动自动加上引号 ,所以在修改添加删除有涉及这个字段的时候会报错,所以我们在这里把它改成phone(所以大家要注意字段名不能为关键字)

下面我们正式来讲解如何使用,我们先在Demo/Api下面创建一个DB.php文件作为我们的DB模块,

<?php
/**
 * 数据库接口服务类
 */
class Api_DB extends PhalApi_Api{
    public function getRules(){
        return array(
            'insert' => array(
                'id'    => array('name' => 'id', 'require' => true, 'desc' => '用户Id'),
                'name'  => array('name' => 'name', 'require' => true, 'desc' => '用户名称'),
                'phone' => array('name' => 'phone', 'require' => true, 'desc' => '用户手机号码'),
            ),
            'select' => array(
                'id' => array('name' => 'id', 'require' => true, 'desc' => '用户Id'),
            ),
            'update' => array(
				'id'    => array('name' => 'id', 'require' => true, 'desc' => '用户Id'),
                'name'  => array('name' => 'name', 'require' => true, 'desc' => '用户名称'),
                'phone' => array('name' => 'phone', 'require' => true, 'desc' => '用户手机号码'),
            ),
            'delete' => array(
                'id' => array('name' => 'id', 'require' => true, 'desc' => '用户Id'),
            ),
        );
    }

一共是增删改查四个接口代表四种操作(这里一定要配置好数据库,以及运行框架自带的sql文件phalapi_test.sql)

###1.1 insert接口###

我们先写增加接口如下:

/**
 * 新增表服务
 * @return int id 新增列的Id
 */
public function insert(){
    $data = array(                                               //用数组构成需要插入键值一一对应
        'id'    => $this->id,
        'name'  => $this->name,
        'phone' => $this->phone,
    );
    $rs   = DI()->notorm->user->insert($data);                  //执行数据库操作user代表的是表,返回结果是插入成功的值
    return $rs['id'];                                           //返回插入的id
}

重要的是 $rs = DI()->notorm->user->insert($data); 这段代码执行了sql语句,user是表名(这里的表名会加下在dbs中配置的表前缀组成一个完整的表名)我们试着运行一下http://localhost/Public/?service=DB.insert&name=miaomi&phone=13010001000&id=2会得到以下结果

###1.2 select接口###

查询接口如下:

/**
 * 查询
 * @return array data 结果集
 */
public function select(){
    $data   = array();
    $data[] = DI()->notorm->user->select('name,phone')->where('id', $this->id)->fetch();
    $data[] = DI()->notorm->user->select('name,phone')->where('id = ?', $this->id)->fetchAll();
    $data[] = DI()->notorm->user->select('name,phone')->where('id != ?', $this->id)->fetchRows();
    return $data;
}

执行http://localhost/Public/?service=DB.select&id=2会得到以下结果

为什么会有这样的区别,通过下面的一些小提示大家就能看到区别在哪里:

####1.2.1 select方法####

select方法主要是用来指定返回值,接受的是一个string他的作用于真正查询语句select和from之间填充,大家如果把select('name,phone') 改为 select('*') 就会得到包括id的所有字段的返回

####1.2.2 where方法和排序####

where方法是查询中的重要的一个环节

where('id', $this->id)等同于where('id = ?', $this->id)

where('id != ?', $this->id)这种方式只要是为了指定条件大于,等于,小于,不等于

当然如果是需要有多个条件就使用连续的where就可以**->where('id != ?',1)->where('phone','1301000100')**这种形式

关于排序的使用其实和where差不多使用**->order('字段名')**如果要反排序在字段名后面加上DESC

####1.2.3 fetch,fetchAll和fetchRows####

大家有看到上面执行的三条查询语句后面的结束放到都不同这里讲解一下他们的区别和怎么用他们使用单独去执行sql语句

fetch方法是获取单独的一条数据返回结果是不带下标的数组 ,fetchAll和fetchRows不同在于他们返回的是包含多条数据一个带下标的数组,可以看到在条件一样的情况下第一条和第二条查询出来的结果区别是第二条多了一个0的下标,从此可得到如果是确定返回结果只有一条优先使用fetch,如果是多条结果优先使用fetchAll和fetchRows.

fetchAll和fetchRows还提供了一个功能就是单独执行sql语句

$sql = 'select * from tbl_user where id = :id';
$params = array(':id' => $this->id);                 //替换:id为请求参数的id
DI()->notorm->user->queryAll($sql, $params);         //或fetchRows($sql, $params)

这样就可以执行sql语句,包括一些复杂的查询sql可以使用此内方法执行(关联查询应当优先使用这种形式)

###1.3 update接口###

修改接口如下:

/**
 * 修改
 */
public function update(){
    $data = array(
        'name'  => $this->name,
        'phone' => $this->phone,
    );
    $rs   = DI()->notorm->user->where('id', $this->id)->update($data);
    if($rs === false){
        throw new PhalApi_Exception_BadRequest('修改数据失败');
    }
}

大家可以试一试执行之后是否有修改数据库http://localhost/Public/?service=DB.update&id=2&phone=13011112222&name=wenwenwen

使用其实和添加接口差不多只是一个是吧id作为值,一个是作为条件

比较值得讲一下的是为什么使用if($rs === false)

原因是这样的,这里执行update方法之后获取得是影响行数,如果原本值就是一样的那就回返回0,只有在真正语句失败的时候会返回false所以这里使用全等于false作为判断是否执行成功的条件

###1.4 delete接口###

删除接口如下:

/**
 * 删除
 */
public function delete(){
    $rs   = DI()->notorm->user->where('id', $this->id)->delete();
    if($rs === false){
        throw new PhalApi_Exception_BadRequest('删除数据失败');
    }
}

http://localhost/Public/?service=DB.delete&id=2

删除的操作也很简单,不过**if($rs === false)**就算没有删除到数据也会返回成功,只有当语句失败会反悔false,如果需要未删除到数据提示出错的同学可以把等号减少一个

###1.5 打印sql语句###

有的时候光靠自己去看代码很难确定是不是哪里写的有问题,但是如果查看生成出来的sql语句就能很快的确定问题出现在哪里

大家可以试试在请求参数中加上

就可以打印出来生成的sql语句方便调试

包括执行时间和先后顺序也一同打印出来了,也可以帮助大家找到慢查询在哪里

##2. 使用Model进行数据库操作##

使用Model操作是为了提高开发效率,让同样数据库操作可以进行高度的复用,也便于修改起来改一处则全改这种效果

###2.1 传统的Model操作###

所谓传统的Model操作也就是把数据操作封装起来,方便调用比如**/Model/User.php**下面的getByUserId方法

public function getByUserId($userId) {
    return DI()->notorm->user->select('*')->where('id = ?', $userId)->fetch();
}

在内部直接封装数据库操作使用如下代码调用

    $model = new Model_User();
    $rs = $model->getByUserId($userId);

###2.2 框架自带的Model操作###

当然这里介绍model的目的当然是解读一下phalapi内部提供的model操作

使用自带model操作只需要继承**PhalApi_Model_NotORM **在实现如下方法

protected function getTableName($id) {
	return 'user';
}

这个方法主要作用是为了添加这个model 的表名,其实这两个操作在**/Model/User.php**中已经实现了,我们来重构一下getByUserId方法如下

public function getByUserId($userId) {
    return $this->getORM()->select('*')->where('id = ?', $userId)->fetch();
}

$this->getORM()相当于DI()->notorm->(getTableName中设置的表名)

然后我们重写select接口如下:

public function select(){
    $model = new Model_User();
    return $model->getByUserId($this->id);
}

可以获得以下结果

在这里phalapi自带的model和传统的model对比起来区别在于,phalapi统一制定表名不会应为方法果断导致的表名写错的失误

另一方面phalapi自带的model提供了很多字基础操作,利用自动提示功能可以看到

我们来再次改造一下selete接口使用model自带的方法

public function select(){
    $model = new Model_User();
    return $model->get($this->id);
}

执行结果和上面是一样的,这里注意一点这里Id的名字是dbs中配置的**'key' => 'id',**要和数据库中的ID字段名对应,但是这样会有一些问题会在后面进阶篇提及到

##3. 总结##

在本小节着重讲了CURD操作,以及其中的一些操作的使用和怎么使用phalapi的model层,希望大家看完本小节之后进行一些练习来熟练的掌握使用phalapi对数据库的操作,关于数据库操作的一些小技巧会单独在进阶篇中抽出一小节来讲讲在实际项目开发中遇到的问题以及如何解决,希望大家进一步关注!

注:笔者能力有限有说的不对的地方希望大家能够指出,也希望多多交流!

官网QQ交流群:421032344 欢迎大家的加入!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏深度学习之tensorflow实战篇

python 生成内嵌式字典(dict)-案例从python提取内嵌json写入mongodb

从mongo查询利用python 读写如新的集合 import traceback, from gaode_hotel.conn_mongodb import ...

46050
来自专栏Python

Flask-SQLAlchemy

一.SQLAlchemy介绍 SQLAlchemy是一个基于Python实现的ORM框架。该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之...

1.5K90
来自专栏公众号_薛勤的博客

MongoDB非关系型数据库开发手册

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。

22820
来自专栏Golang语言社区

【Go 语言社区】JS 相关---Window Location

window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面。 Window Location window.locati...

32870
来自专栏深度学习之tensorflow实战篇

mongodb数据结构与基本操作增删改查整理(二)

mongodb数据结构学习–增删改查 插入文档 在数据库中,数据插入是最基本的操作,在MongoDB使用db.collection.insert(docum...

38940
来自专栏智能大石头

新生命开发团队Orm框架XCode v3.5.2009.0714源码发布(圣诞随心大礼包)

忙忙碌碌有一年!做了很多东西,到头来,似乎又什么都没有做。人继续变老,程序继续改进。     这段时间从我们各个系统抽取了基础的常用的部分,整理后形成了一个...

22270
来自专栏软件开发 -- 分享 互助 成长

文件重定向函数freopen

头文件:stdio.h FILE *freopen( const char *filename, const char *mode, FILE *stream ...

22770
来自专栏码匠的流水账

nginx limit配置参数解读

本文主要解析一下ngx_http_core_module、ngx_http_limit_conn_module以及ngx_http_limit_req_modu...

36120
来自专栏待你如初见

JavaIO流File类

11220
来自专栏Java架构沉思录

Java面试通关宝典(二)

前言 在之前的文章《Java面试通关宝典(一)》中,沉思君为大家介绍了几道常见的面试题与参考答案,有些题目还附有延伸问题,如果不清楚这些题目的思路,可以申请进...

29570

扫码关注云+社区

领取腾讯云代金券