Phalcon入門教程之模型
原文發表於: Phalcon入門教程之模型
Phalcon
提供了四種方式操作Mysql數據庫:模型、PHQL、數據庫抽象層以及原生SQL。不論何種方式,首先都需要在DI中注冊 db
服務才能正常使用:
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;
});
數據庫連接信息配置如下:
// 文件路徑: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
服務如下:
//文件路徑: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如下:
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執行時間(單位為秒)。
創建模型
模型類的命名必須符合駝峰命名法,而且須繼承自 Phalcon\Mvc\Model
類:
// 文件路徑: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
中提供的連表操作,都是基於模型類的(後續的教程會分享)。
設置表前綴
在進行數據庫表設計的時候,有時會在表名前加上一段前綴,如 test_articles
。我們依然可以通過 setSource()
映射數據表:
// 文件路徑: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個模型類,不僅耗時耗力還麻煩。我們嚐試著將此處理過程提取出來進行封裝:
// 文件路徑: 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/marser-phalcon-demo
最後,歡迎大家加入QQ群交流討論:
- 廣州PHP高端交流群:158587573
- Phalcon玩家群:150237524
最後更新:2017-05-25 15:31:14