We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

SQL Profiler Not Printing Results

Hi all!

I've a problem with the SQL profiler for my setup. i've followed the documentation in order to get the profiler to work and I have the following code in my services file:

$di->set('db', function () use ($config, $di)
{

    $em = new EventsManager();

    /**
     * Enable special profiling in development environments
     */
    if ($config->environment == "development")
    {
        $logger = new FileLogger(ENGINE_PATH . "common/logs/debug_" . date("Y-m-d") . ".log");
        $profiler = $di->getProfiler();

        /**
         * Listen to all database events
         */
        $em->attach('db', function($event, $connection) use ($logger, $profiler)
        {
            if ($event->getType() == 'beforeQuery')
            {
                $sql = $connection->getSQLStatement();
                $logger->log($sql, Logger::INFO);
                $profiler->startProfile($sql);
            }

            if ($event->getType() == 'afterQuery')
            {
                $profiler->stopProfile();
            }
        });
    }

    /**
     * Start the database connection
     */
    $connection = new DbAdapter(array(
        'host'      => $config->db->host,
        'username'  => $config->db->username,
        'password'  => $config->db->password,
        'dbname'    => $config->db->dbname,
        'charset'   => $config->db->charset
    ));

    $connection->setEventsManager($em);

    return $connection;
});

As you can see I'm using both the logger and the profiler. The logger is generating a text file correctly and I'm happy this is working. However, the profiler doesn't seem to be working very well.

If I add print_r($this->profiler);die(); just before the last return I get the following output: Phalcon\Db\Profiler Object ( [_allProfiles:protected] => [_activeProfile:protected] => [_totalSeconds:protected] => 0 )

But, if I move the lines up to the end of the "beforeQuery" if section, I get something like: Phalcon\Db\Profiler Object ( [_allProfiles:protected] => [_activeProfile:protected] => Phalcon\Db\Profiler\Item Object ( [_sqlStatement:protected] => SELECT IF(COUNT(*) > 0, 1, 0) FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_NAME` = 'system_usergroups' AND `TABLE_SCHEMA` = DATABASE() [_sqlVariables:protected] => [_sqlBindTypes:protected] => [_initialTime:protected] => 1479760233.32 [_finalTime:protected] => ) [_totalSeconds:protected] => 0 )

So clearly it's doing something, but when I come to use it in the Volt template and use {{ profiler.getProfiles() }} I get an error that it's not defined.

Can anyone spot something I'm doing wrong here?

Thanks for looking and any help in advance.

edited Nov '16

Okay, so as is always the case: I write these questions and I come to a "solution".

After reviewing the code a little I reliased that the profiler was being set as follows:

$di->set('profiler', function ()
{
    return new Profiler();
});

But in another system that was working I was using:

$di['profiler'] = function () {
    return new Profiler();
};

So I copied it across and sure enough the printing started working. So that got me thinking why? So then I tried using

$di->setShared('profiler', function ()
{
    return new Profiler();
});

and that too worked.

I'm not exactly clear as to why, and someone may be able to provide a detailed reason for it, but I'm going to take a stab at it.

I assume that when you use the Array based method or the setShared method, these register the profiler into the DI in a way that the volt template engine can access it. Using the set method doesn't do this "name registration" and I would have to do another step to get it work.

Sorry if I've wasted anyone's time.