Phalcon入门教程之模型CURD(2)

上一篇 Phalcon入门教程之模型CURD(1) 中介绍了 Phalcon 模型的 insertselect 操作,本篇将介绍 updatedelete 的用法。文中所用的示例代码皆沿用上一篇的数据表,这里不在赘述。

更新记录

Phalcon 模型更新记录的示例代码如下:

$articleModel = new ArticlesModel();
//先调用 findFirst() 获取一条记录,返回值是当前模型对象
$article = $articleModel->findFirst([
    'conditions' => 'aid = :aid:',
    'bind' => [
        'aid' => 3
    ],
]);
if($article) {
    //使用返回的模型对象调用 update() 函数执行更新操作
    $result = $article->update([
        'title' => 'Phalcon更新测试1',
    ]);
    //update() 函数返回值为boolean
    var_dump($result);
}

监听到的SQL语句如下:

SELECT * FROM `test_articles` WHERE `test_articles`.`aid` = :aid LIMIT :APL0

UPDATE `test_articles` SET `title` = ?, `introduce` = ?, `status` = ?, `view_number` = ?, `is_recommend` = ?, `is_top` = ?, `create_by` = ?, `create_time` = ?, `modify_by` = ?, `modify_time` = ? WHERE `aid` = ?

通过代码和SQL语句,可以看出在调用 update() 函数之前,必须要先调用 findFirst() 函数获取一条记录。这是因为 update() 函数内部是默认使用主键作为更新条件的,所以 update() 函数没有更新条件这个参数,只能通过主键来更新。但是每次执行更新操作的时候,都要执行两条SQL语句(先 selectupdate ),在性能上会有所损耗。下面跟大家分享只执行一条 update SQL语句的办法( 前提是已经知道主键值):

$articleModel = new ArticlesModel();
$articleModel->aid = 3;  //为主键成员属性赋值 
$result = $articleModel->update([
    'title' => 'Phalcon更新测试',
]);

上述代码运行之后,抛出一个异常:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'introduce' cannot be null

意思是 introduce 字段值不能为空。我们回头再看前面监听到的 update SQL语句,执行 update() 函数的时候,把 test_articles 表中的所有字段都更新了。也就是说,调用 update() 函数的时候,需要更新表中的所有字段,而不能只更新某个字段或者一部分字段,所以此处,需要传入全部字段做为参数:

$articleModel = new ArticlesModel();
$articleModel->aid = 3;
$result = $articleModel->update([
    'title' => 'Phalcon更新测试',
    'introduce' => "Phalcon入门教程2",
    'status' => 2,
    'view_number' => 2,
    'is_recommend' => 1,
    'is_top' => 1,
    'create_by' => 1,
    'create_time' => date('Y-m-d H:i:s'),
    'modify_by' => 1,
    'modify_time' => date('Y-m-d H:i:s')
]);
if(!$result){
    throw new \Exception('数据更新失败');
}
//获取影响行数(假设DI中注册的数据库服务名称为“db”)
$affectedRows = $this->getDI()->get('db')->affectedRows();

每次更新数据的时候,都需要将所有字段全部更新,显然不符合咱天朝广大开发者的习惯,那有没有办法实现只更新部分字段呢?

更新部分字段

除了写原生SQL,或者通过PHQL的方式可以实现更新部分字段之外,Phalcon 中并没有提供可以直接使用的函数。不过,我们可以通过其他方法来曲线救国一下,下面是我封装的函数:

    //文件路径:marser/app/frontend/models/ArticlesModel.php

    /**
     * 封装phalcon model的update函数,实现仅更新数据变更字段,而非所有字段更新
     * @param array|null $data
     * @param null $whiteList
     * @return bool
     */
    public function iupdate(array $data = null, $whiteList = null)
    {
        if (count($data) > 0) {
            //获取当前模型驿应的数据表所有字段
            $attributes = $this->getModelsMetaData()->getAttributes($this);
            //取所有字段和需要更新的数据字段的差集,并过滤
            $this->skipAttributesOnUpdate(array_diff($attributes, array_keys($data)));
        }
        return parent::update($data, $whiteList);
    }

函数很简单,先获取当前模型对应数据表的所有字段,并和需要更新的数据字段之间取差集,然后调用 skipAttributesOnUpdate 函数进行过滤。上述更新部分字段的示例代码就可以修改成:

$articleModel = new ArticlesModel();
$articleModel->aid = 3;
//注意这里的函数名
$result = $articleModel->iupdate([
    'title' => 'Phalcon更新测试',
]);
if(!$result){
    throw new \Exception('数据更新失败');
}
$affectedRows = $this->getDI()->get('db')->affectedRows();

至此就能更新成功,并能获取影响行数。 这里提一下,Phalcon 模型的 update() 函数有一个注意点。当更新的数据和表中的数据相同时,update() 函数会返回 true 值,但是影响行数却是0。

save()

Phalcon 模型的 save() 函数会判断当前模型对象中主键成员属性是否有值,若有值,就内部调用 update() 函数执行更新操作;若没值,就内部调用 create() 函数执行插入操作。

删除记录

删除记录和更新记录类似,要先调用 findFirst() 之后,再调用 delete() 函数删除一条数据。我们在知道主键的情况,也可以直接给主键成员属性赋值:

$articleModel = new ArticlesModel();
$articleModel->aid = 4;
$result = $articleModel->delete();
$affectedRows = $this->getDI()->get('db')->affectedRows();

值得注意的是,不论主键ID是否存在,delete() 都会返回 true 值,而影响行数会正常返回。所以建议根据影响行数来判断是否执行成功。 如果需要批量删除,或者使用非主键作为删除条件,那么只能写原生SQL或者PHQL去删除数据,当然也可以自己封装一个函数。

以上代码已托管在github:https://github.com/KevinJay/marser-phalcon-demo

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿天地

mongodb java操作语法

之前都是通过spring-data框架来对mongodb操作,当然在很多老的项目中,由于jar包版本的问题,不太好升级到最新的版本,往往会采用mongodb-d...

27710
来自专栏技术专栏

慕课网Flask构建可扩展的RESTful API-7. 权限控制

1.204 的HTTP状态码代表的是NO CONTENT,无内容。所以如果状态码是204,那么无论返回什么,前端都接受不到,但是我们要尽量返回格式化的信息,让前...

2764
来自专栏铭毅天下

Elasticsearch 6.X 新类型Join深入详解

0、ES6.X 一对多、多对多的数据该如何存储和实现呢? 引出问题: “某头条新闻APP”新闻内容和新闻评论是1对多的关系? 在ES6.X该如何存储、如何进行高...

2.3K9
来自专栏微信公众号:Java团长

彻底解决MySQL中文乱码

mysql是我们项目中非常常用的数据型数据库。但是因为我们需要在数据库保存中文字符,所以经常遇到数据库乱码情况。下面就来介绍一下如何彻底解决数据库中文乱码情况。

1572
来自专栏python3

pymysql--插入300万数据

        (2)使用python协程(遇到I/O操作就切换任务,无需等待--提高效率)

1142
来自专栏蓝天

一个简单的支持MySQL和SQLite3的DB接口

simple_db.zip 相关联代码:https://github.com/eyjian/mooon/tree/master/common_library/...

972
来自专栏木头编程 - moTzxx

PHP 学习筆記[1] —— ThinkPHP 公共函数整理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

1154
来自专栏Linux驱动

46.Linux-创建rc红外遥控平台设备,实现重复功能(2)

在上章分析了红外platform_driver后,已经修改bug后,接下来我们自己创建一个红外platform_device平台设备,其实写一个平台设备很简单.

1352
来自专栏Java架构沉思录

如何优雅地实现分页查询

分页功能是很常见的功能,特别是当数据量越来越大的时候,分页查询是必不可少的。实现分页功能有很多种方式,如果使用的ORM框架是mybatis的话,有开源的分页插件...

1192
来自专栏社区的朋友们

MongoDb 简单介绍

最近一段时间使用 mongodb 做媒资数据的接入,简单介绍一下 mongodb 的特性和语法。希望对大家有所帮助。

1310

扫码关注云+社区