fabfuel / prophiler

PHP Profiler & Developer Toolbar (built for Phalcon)
http://prophiler.fabfuel.de
Other
443 stars 54 forks source link

PDO Profiling #35

Closed PBXg33k closed 8 years ago

PBXg33k commented 9 years ago

Hi,

First of all great tool you wrote and thanks. I've recently updated prophiler on my existing codebase from 1.1 to 2.0 and tried to apply PDO profiling. Since i heavily use prepared statements in my project i noticed the PDO profiling breaking pretty fast since it was relying on PHP::PDO and not on Phalcon\Db\Adapter\Pdo (ie: tableExists is implicitly called).

Is there a reason PHP::PDO is required instead of Phalcon's extension?

I've modified the code locally (which i can fork and PR) to work with prepared statements.

Here's an excerpt from my code which causes the following exception:

PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'PDO' does not have a method 'tableexists' in ~\libraries\fabfuel\prophiler\src\Fabfuel\Prophiler\Decorator\PDO\PDO.php on line 45

# services.php
...
$di['db'] = function () use ($di) {
    $mode = require __DIR__.'/mode.php';
    $dbFilePath = __DIR__."/database-{$mode}.php";

    if (is_file($dbFilePath)) {
        $dbconfig = require_once $dbFilePath;
        // Slightly altered to get PDO statement with existing config
        $db = new DbAdapter($dbconfig->database->toArray());
        $dbhandler = $db->getInternalHandler();

        return new \Fabfuel\Prophiler\Decorator\PDO\PDO(
            // new DbAdapter($dbconfig->database->toArray()),
            $dbhandler, // object(PDO)
            $di->get('profiler')
        );
    } else {
        throw new Exception("Unable to find database configuration.");
    }
};
...
# router.php
...
            // Split URI into parts for quering the database
            preg_match('~/*([\w\d-_]+)~iu', $router->getRewriteUri(), $matches);

            if (!empty($matches[1])) {
                @list($uri, $uriIndex) = explode('-', $matches[1]);

                // Lookup route in the databse
                $route = self::findFirst([
                    'conditions' => 'uri = ?1 AND uri_index = ?2',
                    'bind' => [1 => $uri, 2 => (int) (!empty($uriIndex)) ? $uriIndex : 0],
                ]);

                if ($route) {
                    // Match! Add route to router
                    $router->add(
                        $router->getRewriteUri(),
                        [
                            'module' => $route->module,
                            'controller' => $route->controller,
                            'action' => $route->action,
                            'params' => unserialize($route->params)
                        ]
                    );
                }
            }
...
PBXg33k commented 9 years ago

After modifying src\Fabfurl\Profiler\Decorator\PDO\PDO.php with the following changes

public function __construct(\Phalcon\Db\Adapter\Pdo $pdo, ProfilerInterface $profiler)
public function setPdo(\Phalcon\Db\Adapter\Pdo $pdo)

i kept receiving the following exception:

PDOException: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound

Applying the change below in the same file fixed it for me

    public function query($statement, $bindParams = null, $bindTypes = null)
    {
        $metadata = ['statement' => $statement, 'bind parameters', $bindParams, 'bind types' => $bindTypes];
        $benchmark = $this->getProfiler()->start('PDO::query', [], 'Database');
        $result = $this->getPdo()->query($statement, $bindParams, $bindTypes);
        if ($result instanceof \PDOStatement) {
            $metadata['rows'] = $result->rowCount();
            $metadata['columns'] = $result->columnCount();
        }
        $this->getProfiler()->stop($benchmark, $metadata);
        return $result;
    }
...
mzf commented 8 years ago

How profile queries? I have this issue too. Need wiki for it

fabfuel commented 8 years ago

Hi!

Sorry for the late answer.

Prophiler itself is a framework independent implementation. It was initially built for Phalcon, but it also works with any other or no framework.

Due to that, the PDO decorator has to decorate \PDO\PDO.

In addition you could create a second adapter for \Phalcon\Db\Adapter\Pdo. A pull request would be highly appreciated.

Best Fabian