LoginSignup
4
4

More than 5 years have passed since last update.

FuelPHP+Doctrine2でSQLをログに出すためにやったこと

Last updated at Posted at 2014-06-27

正しくはDQLがログに出るのだけど、あった方が調査とかし易いのでログに書き出してみた。

FuelPHP+Doctrine2の構成は
http://qiita.com/gyhino@github/items/188d207d26f608269b3a
を引き続き使う。

要件

  • ログにSQL(DQL)が出力される
  • ログにクエリの実行時間が出力される

Doctrine2でSQLをログに出すためにはどうしたらいい?

Doctrine2にはSQLLoggerを設定することができ、それを使うことで簡単にSQLを出力する事ができる。
SQLLoggerはInterfaceとして提供されているだけなので、自分で好きに実装する。
https://github.com/doctrine/dbal/blob/master/lib/Doctrine/DBAL/Logging/SQLLogger.php

FuelPHPのログにSQLを出すために改修をする

今回Doctrine2を扱うのに利用しているライブラリにもSQLLoggerが用意されている。
https://github.com/aspendigital/fuel-doctrine2/blob/master/classes/Fuel/Doctrine/Logger.php

ライブラリ内でprofilingが有効になっている場合これを使う様に実装されている。
しかし、このSQLLoggerの実装はプロファイラにSQLと実行時間が表示されるようになるだけで、ログには書き出されない。

なので、これを拡張する形で進める。

Fuel\Doctrine\Loggerの拡張

SQLと処理時間をログに出すにはこんな感じで拡張をする。

fuel/app/classes/doctrine/SQLLogger.php
<?php

namespace Sample\Doctrine;

class SQLLogger extends \Fuel\Doctrine\Logger
{
    protected $startTime;
    protected $lastSql;

    public function startQuery($sql, array $params = null, array $types = null)
    {
        parent::startQuery($sql, $params, $types);

        $this->startTime = microtime(true);
        $this->lastSql = $sql;
    }

    public function stopQuery()
    {
        parent::stopQuery();

        \Log::info(json_encode(array(
            'sql' => $this->lastSql,
            'elapsedTime' => sprintf('%.10f', (microtime(true) - $this->startTime)), 
        )));
    }
}

namespaceをAutoloaderに設定して読み込まれるようにする

今後のことを考え、PSR-0準拠で読み込むようにする。

fuel/app/bootstrap.php
<?php

//...

// SQLLoggerが属するネームスペースをFuelPHPのAutoloaderに追加
Autoloader::add_namespace('Sample\Doctrine', APPPATH.'classes'.DIRECTORY_SEPARATOR.'doctrine'.DIRECTORY_SEPARATOR, true);

Autoloader::add_classes(array(
));

// Register the autoloader
Autoloader::register();

//...

拡張したSQLLoggerをDoctrine2に渡す設定をする

拡張したところで設定しないと使われないので、設定をする。

fuel/app/config/db.php
<?php

return array(
    'doctrine2' => array(
        'proxy_dir' => APPPATH.'classes'.DIRECTORY_SEPARATOR.'proxy',
        'proxy_namespace' => 'Proxy',
        'metadata_path' => APPPATH.'classes'.DIRECTORY_SEPARATOR.'entity',
        'init_callback' => function($manager, $connection)
        {
            // Doctrineセットアップ時の一番最後に呼ばれるコールバック
            $manager
                ->getConnection()
                ->getConfiguration()
                ->setSQLLogger(new Sample\Doctrine\SQLLogger($connection));
        },
    ),
    //...
);

profilingが無効の時は考慮できていないので、おそらく正しく動かない

おしまい

おしまい。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4