前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Phalcon入门教程之模型

Phalcon入门教程之模型

作者头像
Marser
发布2018-06-25 17:47:53
8160
发布2018-06-25 17:47:53
举报
文章被收录于专栏:智能合约智能合约

Phalcon 提供了四种方式操作Mysql数据库:模型、PHQL、数据库抽象层以及原生SQL。不论何种方式,首先都需要在DI中注册 db 服务才能正常使用:

DI注册db服务

代码语言:javascript
复制
//  文件路径: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;
});

数据库连接信息配置如下:

代码语言:javascript
复制
// 文件路径: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 服务如下:

代码语言:javascript
复制
//文件路径: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如下:

代码语言:javascript
复制
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 类:

代码语言:javascript
复制
// 文件路径: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() 方法设置:

代码语言:javascript
复制
// 文件路径:app/frontend/models/ArticlesModel.php
class Articles extends \Marser\App\Frontend\Models\BaseModel {
  public function initialize()
    {
        $this->setSource("articles_tags");
    }
}

在项目开发中,建议一个数据表对应着一个模型类。即使是关联表,也强烈建议创建其对应的模型类,因为 Phalcon 中提供的连表操作,都是基于模型类的(后续的教程会分享)。

设置表前缀

在进行数据库表设计的时候,有时会在表名前加上一段前缀,如 test_articles 。我们依然可以通过 setSource() 映射数据表:

代码语言:javascript
复制
// 文件路径: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个模型类,不仅耗时耗力还麻烦。我们尝试着将此处理过程提取出来进行封装:

代码语言:javascript
复制
// 文件路径: 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() 方法定义如下:

代码语言:javascript
复制
// 文件路径: 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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:201705-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DI注册db服务
  • 记录底层SQL语句
  • 创建模型
  • 数据库表映射
  • 设置表前缀
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档