Phalcon入門教程之模型

原文發表於: Phalcon入門教程之模型

Phalcon 提供了四種方式操做Mysql數據庫:模型、PHQL、數據庫抽象層以及原生SQL。不論何種方式,首先都須要在DI中註冊 db 服務才能正常使用:php

DI註冊db服務

//  文件路徑:app/core/services.php
$di -> setShared('db', function () use($config) {
    $dbconfig = $config -> database -> db;
    $dbconfig = $dbconfig -> toArray();
    if (!is_array($dbconfig) || count($dbconfig)==0) {
        throw new \Exception("the database config is error");
    }
    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        "host" => $dbconfig['host'], "port" => $dbconfig['port'],
        "username" => $dbconfig['username'],
        "password" => $dbconfig['password'],
        "dbname" => $dbconfig['dbname'],
        "charset" => $dbconfig['charset'])
    );
    return $connection;
});

數據庫鏈接信息配置以下:html

// 文件路徑:app/config/system.php
return array(
    //數據庫表配置
    'database' => array(
        //數據庫鏈接信息
        'db' => array(
            'host' => '127.0.0.1',
            'port' => 3306,
            'username' => 'admin',
            'password' => 'admin',
            'dbname' => 'test',
            'charset' => 'utf8',
        ),

        //表前綴
        'prefix' => 'test_',
    ),
);

記錄底層SQL語句

在咱們開發過程當中,有時候須要經過SQL語句來分析定位問題。那麼,咱們須要將ORM生成的底層SQL記錄到日誌中。修改DI中註冊的 db 服務以下:git

//文件路徑:app/core/services.php
$di -> setShared('db', function () use($config) {
    $dbconfig = $config -> database -> db;
    $dbconfig = $dbconfig -> toArray();
    if (!is_array($dbconfig) || count($dbconfig)==0) {
        throw new \Exception("the database config is error");
    }
    $eventsManager = new \Phalcon\Events\Manager();
    // 分析底層sql性能,並記錄日誌
    $profiler = new Phalcon\Db\Profiler();
    $eventsManager -> attach('db', function ($event, $connection) use ($profiler) {
        if($event -> getType() == 'beforeQuery'){
            //在sql發送到數據庫前啓動分析
            $profiler -> startProfile($connection -> getSQLStatement());
        }
        if($event -> getType() == 'afterQuery'){
            //在sql執行完畢後中止分析
            $profiler -> stopProfile();
            //獲取分析結果
            $profile = $profiler -> getLastProfile();
            $sql = $profile->getSQLStatement();
            $params = $connection->getSqlVariables();
            (is_array($params) && count($params)) && $params = json_encode($params);
            $executeTime = $profile->getTotalElapsedSeconds();
            //日誌記錄
            $currentDay = date('Ymd');
            $logger = new \Phalcon\Logger\Adapter\File(ROOT_PATH . "/app/cache/logs/{$currentDay}.log");
            $logger -> debug("{$sql} {$params} {$executeTime}");
        }
    });

    $connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        "host" => $dbconfig['host'], "port" => $dbconfig['port'],
        "username" => $dbconfig['username'],
        "password" => $dbconfig['password'],
        "dbname" => $dbconfig['dbname'],
        "charset" => $dbconfig['charset'])
    );

    /* 註冊監聽事件 */
    $connection->setEventsManager($eventsManager);

    return $connection;
});

經過代碼能夠看到,不只是底層SQL,還將SQL綁定的參數(PDO預處理)和SQL執行時間也記錄到日誌中了。日誌記錄demo以下:github

SELECT `users`.`uid` AS `uid`, `users`.`mobile` AS `mobile` FROM `users` WHERE `users`.`uid` = :uid LIMIT :APL0 {"uid":1,"APL0":1} 0.034402132034302

花括號({})中的就是SQL預處理時綁定的參數,最後的浮點數就是SQL執行時間(單位爲秒)。sql

建立模型

模型類的命名必須符合駝峯命名法,並且須繼承自 Phalcon\Mvc\Model 類:shell

// 文件路徑:app/frontend/models/ArticlesModel.php
class Articles extends \Marser\App\Frontend\Models\BaseModel {
    // \Marser\App\Frontend\Models\BaseModel繼承自 \Phalcon\Mvc\Model 類。
    // 此處是再次封裝一個基礎模型類,  以方便後續的通用方法封裝
    //...
}

數據庫表映射

默認狀況下,Articles 模型類對應的數據表名是 articles ;如果 ArticlesTags 模型類,則對應的數據庫表名是 articles_tags , 即類名對應着表名。若是想映射到其餘數據庫表,可使用 setSource() 方法設置:數據庫

// 文件路徑:app/frontend/models/ArticlesModel.php
class Articles extends \Marser\App\Frontend\Models\BaseModel {
  public function initialize()
    {
        $this->setSource("articles_tags");
    }
}

在項目開發中,建議一個數據表對應着一個模型類。即便是關聯表,也強烈建議建立其對應的模型類,由於 Phalcon 中提供的連表操做,都是基於模型類的(後續的教程會分享)。json

設置表前綴

在進行數據庫表設計的時候,有時會在表名前加上一段前綴,如 test_articles 。咱們依然能夠經過 setSource() 映射數據表:app

// 文件路徑:app/frontend/models/ArticlesModel.php
class Articles extends \Marser\App\Frontend\Models\BaseModel {
  public function initialize()
    {
        $this->setSource("test_articles");
    }
}

假設,咱們的項目中有100張數據表,那麼就意味着有100個模型類。此時咱們在每一個模型類中都必須調用 setSource() 來映射完整的表名。若是某天咱們須要修改這100張表的前綴,那麼將要修改這100個模型類,不只耗時耗力還麻煩。咱們嘗試着將此處理過程提取出來進行封裝:frontend

// 文件路徑: 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);
    }
}

BaseModel 模型基類中的 set_table_source() 方法定義以下:

// 文件路徑: app/frontend/models/BaseModel.php
class BaseModel extends \Phalcon\Mvc\Model {

    public function initialize(){

    }

    /**
     * 映射數據表(補上表前綴)
     * @param string $tableName
     * @param null $prefix
     */
    protected function set_table_source($tableName, $prefix = null){
        //默認從配置中讀取表前綴配置
        empty($prefix) && $prefix = $this->getDI()->get('config')->database->prefix;
        //拼接成完整表名以後,再經過setSource()映射數據表
        $this->setSource($prefix . $tableName);
    }
}

咱們在每一個模型類中定義一個 類常量 來存儲無前綴的表名,再經過 set_table_source() 成員方法來拼接表前綴並映射。眼尖的讀者,應該在上面的數據庫鏈接信息配置中有看到 prefix 的表前綴配置。
仍是以上面爲例,此時咱們就不須要修改100個模型類的代碼,而只需修改配置文件中的 prefix 配置便可。

以上代碼已託管在github:https://github.com/KevinJay/m...

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

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