原文發表於: 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羣交流討論: