原文发表于: Phalcon入门教程之模型CURD(1)
上一篇《Phalcon入门教程之模型》中介绍了数据库模型操做的一些基础功能,本篇将介绍模型的 select
和 insert
用法。因为数据库模型操做的内容比较多和细,因此本篇只是粗略的介绍基础用法,以及补充文档中没有说起的一些用法和注意点。所以,强烈建议你们在熟读文档的前提下,再阅读此篇教程。php
假设数据表名为 test_articles
,数据结构及记录下:html
mysql> select * from test_articles; +-----+--------------+--------------+--------+-------------+--------------+--------+-----------+---------------------+-----------+---------------------+ | aid | title | introduce | status | view_number | is_recommend | is_top | create_by | create_time | modify_by | modify_time | +-----+--------------+--------------+--------+-------------+--------------+--------+-----------+---------------------+-----------+---------------------+ | 1 | 英语演讲 | 纯口语式 | 1 | 0 | 0 | 0 | 1 | 2017-05-21 05:13:46 | 1 | 2017-05-21 05:13:46 | | 2 | 限购政策 | 快买房 | 1 | 0 | 0 | 0 | 1 | 2017-05-21 05:13:46 | 1 | 2017-05-21 05:13:46 | +-----+--------------+--------------+--------+-------------+--------------+--------+-----------+---------------------+-----------+---------------------+
其中 aid
是主键,其余每一个字段的意思就不作介绍了。mysql
Phalcon\Mvc\Model
为数据查询提供了多种函数,下面将直接用demo来介绍其用法。git
使用 find()
函数能够查找多条记录:github
$articleModel = new ArticlesModel(); //查询全部记录,返回一个对象 $result = $articleModel->find(); //循环输出结果 foreach($result as $record){ var_dump($record->aid); var_dump($record->title); }
find()
函数返回的是 Phalcon\Mvc\Model\Resultset\Simple
对象,咱们能够经过 foreach
循环输出结果。也能够将结果集对象转成一个二维数组:sql
$records = $result->toArray();
还能够统计结果集对象的记录总数:shell
$count = count($result);
查找单条记录,能够经过使用 findFirst()
函数来实现:数据库
$result1 = $articleModel->findFirst(1); print_r($result1->toArray());
findFirst()
返回的就是当前模型对象(若是不明白,能够打印 $result1
即会明白),toArray()
会将其转成一维数组。数组
细心的朋友可能会有疑问,findFirst(1)
是按什么字段作查询条件的? 经过监听打印SQL语句,能够看到在 Phalcon
中会默认使用主键做为查询条件:数据结构
SELECT * FROM `test_articles` WHERE `test_articles`.`aid` = 1 LIMIT :APL0
固然,咱们也可使用完整的查询条件:
$result2 = $articleModel->findFirst("aid = 1");
返回的结果,和上面的 findFirst(1)
是同样的。
仔细观察上面的SQL语句,会发现查询条件并无进行预处理。若是 aid
的值是经过外部数据(好比用户输入)或者变量传输进来,则有可能出现SQL注入的危险。咱们必需要用参数绑定的方式来防止SQL注入:
$result2 = $articleModel->find([ 'conditions' => 'aid = :aid: AND status = :status:', 'bind' => [ 'aid' => 2, 'status' => 1, ], ]);
生成的SQL语句以下:
SELECT * FROM `test_articles` WHERE `test_articles`.`aid` = :aid AND `test_articles`.`status` = :status
通过参数替换后的SQL语句以下:
SELECT * FROM `test_articles` WHERE `test_articles`.`aid` = 2 AND `test_articles`.`status` = 1
参数绑定支持字符串和整数占位符,本篇只介绍字符串占位符,整数占位符的用法可查阅文档。
Phalcon
提供了不少查询选项,经常使用的查询选项demo以下:
$articleModel->find([ 'columns' => 'aid, title', //查询字段 'conditions' => 'aid = :aid:', //查询条件 'bind' => [ //参数绑定 'aid' => 2 ], 'order' => 'aid DESC', //排序 'limit' => 10, //限制查询结果的数量 'offset' => 10, //偏移量 ]);
所有的查询选项,请查阅文档。
不少朋友在群里问 in
和 like
在参数绑定下的用法,下面跟你们分享一下。
直接上示例代码:
$result3 = $articleModel->find([ 'conditions' => 'aid IN ({aids:array})', 'bind' => [ 'aids' => [1, 2] ], ]);
示例代码以下:
$result4 = $articleModel->find([ 'conditions' => 'title like :title:', 'bind' => [ 'title' => '%英语%', ], ]);
添加单条记录可用 create()
函数:
$articleModel = new ArticlesModel(); $result = $articleModel->create([ 'title' => 'phalcon测试', 'introduce' => 'Phalcon入门教程', 'status' => 1, 'view_number' => 1, '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) { //添加记录失败,获取错误信息 $errorMessage = implode(',', $this->getMessages()); echo $errorMessage; }else { //添加记录成功,获取新增记录的主键aid $aid = $articleModel->aid; echo $aid; }
create()
函数返回的是 boolean
值。若是返回值为 false
,咱们能够经过模型的 getMessages()
函数来获取错误信息;若返回值为 true
,则能够直接获取最新的主键ID,即咱们一般所说的 lastInsertId
。
Phalcon
中并无提供批量添加记录的函数,须要开发者本身动手实现,本篇跟你们分享两种实现批量添加记录的方法。
经过循环逐次添加一条记录,这种方法在性能上损耗较大,不推荐使用。可是这种方法牵涉到 Phalcon
模型的底层实现原理,因此这里拿出来跟你们分析一下。上代码:
$articleModel = new ArticlesModel(); //var_dump($articleModel->title); //下面测试用 for ($i = 1; $i <= 10; $i++) { $data = [ 'title' => "phalcon测试{$i}", 'introduce' => "Phalcon入门教程{$i}", 'status' => $i, 'view_number' => $i, 'is_recommend' => 1, 'is_top' => 1, 'create_by' => $i, 'create_time' => date('Y-m-d H:i:s'), 'modify_by' => $i, 'modify_time' => date('Y-m-d H:i:s') ]; $result = $articleModel->create($data); if (!$result) { $errorMessage = implode(',', $articleModel->getMessages()); exit($errorMessage); }else { $aid = $articleModel->aid; echo $aid; //var_dump($articleModel->title); //下面测试用 } echo '<br />'; }
这段代码的运行结果可能会出乎不少人的意料,只有循环中的第一条数据入库成功,并返回了主键ID,其余的数据入库时直接报错:
Record cannot be created because it already exists
意思是由于记录已经存在,因此没法再次入库。在前面 添加单条记录 的时候,咱们有提到获取 lastInsertId
的方式,是直接经过模型的成员属性方式获取:
$aid = $articleModel->aid;
关键点就在这里,Phalcon
模型对象会把当前入库的数据,所有赋值给模型对象的成员属性,包括主键ID。咱们作个测试,打开上面代码中的两处注释部分,再次运行后能够看到,第一次打印 title
成员属性的时候,会报一个 Notice
错误,提示信息是未定义的成员属性。当第二次打印 title
成员属性的时候,却有值了,并且是循环中第一条记录的 title
值。看到这里,相信你们应该已经差很少能明白其中的实现原理了。由于入库成功那条记录返回的主键ID也被赋值给模型对象的成员属性,create()
函数内部会判断当前对象的主键成员属性是否有值,在有值的状况下,就再也不生成SQL语句发送到Mysql服务端,直接抛出错误信息。请记住这一点,Phalcon
模型的 update()
函数也是基于此原理实现的(下一篇教程会提到)。那么,经过循环逐条添加记录的方法要如何实现呢?请看代码:
$articleModel = new ArticlesModel(); for ($i = 1; $i <= 10; $i++) { $data = [ 'title' => "phalcon测试{$i}", 'introduce' => "Phalcon入门教程{$i}", 'status' => $i, 'view_number' => $i, 'is_recommend' => 1, 'is_top' => 1, 'create_by' => $i, 'create_time' => date('Y-m-d H:i:s'), 'modify_by' => $i, 'modify_time' => date('Y-m-d H:i:s') ]; $clone = clone $articleModel; //克隆一个新对象,使用新对象来调用create()函数 $result = $clone->create($data); if (!$result) { $errorMessage = implode(',', $clone->getMessages()); exit($errorMessage); }else { $aid = $clone->aid; echo $aid; } echo '<br />'; }
每循环一次,就克隆出一个新对象,经过新对象来调用 create()
函数添加数据记录。由于每一个对象间的成员属性都是独立的,因此所有数据都会添加成功。
咱们经常使用的批量添加方式是生成一条 insert
语句把数据添加入库,下面跟你们分享我在项目中封装的函数:
//文件路径:Marser\app\frontend\models\ArticlesModel.php class ArticlesModel extends \Marser\App\Frontend\Models\BaseModel { /*** 表名*/ const TABLE_NAME = 'articles'; public function initialize(){ parent::initialize(); $this->set_table_source(self::TABLE_NAME); } /** * 批量添加 * @param array $data * @return boolean * @throws \Exception */ public function batch_insert(array $data){ if (count($data) == 0) { throw new \Exception('参数错误'); } $keys = array_keys(reset($data)); $keys = array_map(function ($key) { return "`{$key}`"; }, $keys); $keys = implode(',', $keys); $sql = "INSERT INTO " . $this->getSource() . " ({$keys}) VALUES "; foreach ($data as $v) { $v = array_map(function ($value) { return "'{$value}'"; }, $v); $values = implode(',', array_values($v)); $sql .= " ({$values}), "; } $sql = rtrim(trim($sql), ','); //DI中注册的数据库服务名称为"db" $result = $this->getDI()->get('db')->execute($sql); if (!$result) { throw new \Exception('批量入库记录'); } return $result; } }
以上代码已托管在github:https://github.com/KevinJay/m...
最后,欢迎你们加入QQ群交流讨论: