Phalcon入門教程之模型CURD(1)
原文發表於:Phalcon入門教程之模型CURD(1)
上一篇《Phalcon入門教程之模型》中介紹了數據庫模型操作的一些基礎功能,本篇將介紹模型的 select
和 insert
用法。由於數據庫模型操作的內容比較多和細,所以本篇隻是粗略的介紹基礎用法,以及補充文檔中沒有提及的一些用法和注意點。因此,強烈建議大家在熟讀文檔的前提下,再閱讀此篇教程。
數據表
假設數據表名為 test_articles
,數據結構及記錄下:
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
是主鍵,其他每個字段的意思就不做介紹了。
查找記錄
Phalcon\Mvc\Model
為數據查詢提供了多種函數,下麵將直接用demo來介紹其用法。
查找多條記錄
使用 find()
函數可以查找多條記錄:
$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
循環輸出結果。也可以將結果集對象轉成一個二維數組:
$records = $result->toArray();
還可以統計結果集對象的記錄總數:
$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
在參數綁定下的用法,下麵跟大家分享一下。
in的用法
直接上示例代碼:
$result3 = $articleModel->find([
'conditions' => 'aid IN ({aids:array})',
'bind' => [
'aids' => [1, 2]
],
]);
like的用法
示例代碼如下:
$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/marser-phalcon-demo
最後,歡迎大家加入QQ群交流討論:
- 廣州PHP高端交流群:158587573
- Phalcon玩家群:150237524
最後更新:2017-07-20 17:02:54