Phalcon入門教程之模型CURD(1)

原文發表於: Phalcon入門教程之模型CURD(1)

上一篇《Phalcon入門教程之模型》中介紹了數據庫模型操做的一些基礎功能,本篇將介紹模型的 selectinsert 用法。因爲數據庫模型操做的內容比較多和細,因此本篇只是粗略的介紹基礎用法,以及補充文檔中沒有說起的一些用法和注意點。所以,強烈建議你們在熟讀文檔的前提下,再閱讀此篇教程。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, //偏移量
 ]);

所有的查詢選項,請查閱文檔。
不少朋友在羣裏問 inlike 在參數綁定下的用法,下面跟你們分享一下。

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/m...

最後,歡迎你們加入QQ羣交流討論:

  • 廣州PHP高端交流羣:158587573
  • Phalcon玩家羣:150237524
相關文章
相關標籤/搜索