本文共 5292 字,大约阅读时间需要 17 分钟。
原文发表于:
Phalcon
提供了四种方式操作Mysql数据库:模型、PHQL、数据库抽象层以及原生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"); } $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.phpreturn array( //数据库表配置 'database' => array( //数据库连接信息 'db' => array( 'host' => '127.0.0.1', 'port' => 3306, 'username' => 'admin', 'password' => 'admin', 'dbname' => 'test', 'charset' => 'utf8', ), //表前缀 'prefix' => 'test_', ),);
在我们开发过程中,有时候需要通过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.phpclass 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.phpclass Articles extends \Marser\App\Frontend\Models\BaseModel { public function initialize() { $this->setSource("articles_tags"); }}
在项目开发中,建议一个数据表对应着一个模型类。即使是关联表,也强烈建议创建其对应的模型类,因为 Phalcon
中提供的连表操作,都是基于模型类的(后续的教程会分享)。
在进行数据库表设计的时候,有时会在表名前加上一段前缀,如 test_articles
。我们依然可以通过 setSource()
映射数据表:
// 文件路径:app/frontend/models/ArticlesModel.phpclass Articles extends \Marser\App\Frontend\Models\BaseModel { public function initialize() { $this->setSource("test_articles"); }}
假设,我们的项目中有100张数据表,那么就意味着有100个模型类。此时我们在每个模型类中都必须调用 setSource()
来映射完整的表名。如果某天我们需要修改这100张表的前缀,那么将要修改这100个模型类,不仅耗时耗力还麻烦。我们尝试着将此处理过程提取出来进行封装:
// 文件路径: app/frontend/models/ArticlesModel.phpclass 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.phpclass 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
的表前缀配置。
prefix
配置即可。 以上代码已托管在github:
最后,欢迎大家加入QQ群交流讨论:
转载地址:http://zseal.baihongyu.com/