diff --git a/.travis.yml b/.travis.yml index 6ed63cdf..81dc7dae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ before_script: - rm config/application.config.php && cp ../DoctrineORMModule/.travis/application.config.php config/ - cp ../DoctrineORMModule/.travis/composer.json ./ - curl -s http://getcomposer.org/installer | php - - php composer.phar install + - php composer.phar install --dev - rm -rf vendor/doctrine/doctrine-orm-module - cp -r ../DoctrineORMModule vendor/doctrine/doctrine-orm-module - cp ../DoctrineORMModule/.travis/travis.local.php config/autoload/ diff --git a/composer.json b/composer.json index e697f0fc..bab21527 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,12 @@ "doctrine/migrations": "dev-master", "zendframework/zendframework": "dev-master" }, + "require-dev": { + "zendframework/zend-developer-tools": "dev-master" + }, + "suggest": { + "zendframework/zend-developer-tools": "zend-developer-tools if you want to profile operations executed by the ORM during development" + }, "minimum-stability": "dev", "autoload": { "psr-0": { diff --git a/config/module.config.php b/config/module.config.php index 36bbf8b3..0910ea0c 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -50,4 +50,21 @@ 'orm_default' => array() ), ), + + 'view_manager' => array( + 'template_map' => array( + 'zend-developer-tools/toolbar/doctrine-orm' => __DIR__ . '/../view/zend-developer-tools/toolbar/doctrine-orm.phtml', + ), + ), + + 'zdt' => array( + 'collectors' => array( + 'orm_default' => 'doctrine.collector.orm_default', + ), + 'toolbar' => array( + 'entries' => array( + 'orm_default' => 'zend-developer-tools/toolbar/doctrine-orm', + ), + ), + ), ); diff --git a/src/DoctrineORMModule/Collector/SQLLoggerCollector.php b/src/DoctrineORMModule/Collector/SQLLoggerCollector.php new file mode 100644 index 00000000..df488124 --- /dev/null +++ b/src/DoctrineORMModule/Collector/SQLLoggerCollector.php @@ -0,0 +1,115 @@ +. + */ + +namespace DoctrineORMModule\Collector; + +use ZendDeveloperTools\Collector\CollectorInterface; +use ZendDeveloperTools\Collector\AutoHideInterface; + +use Zend\Mvc\MvcEvent; + +use Doctrine\DBAL\Logging\DebugStack; + +/** + * Collector to be used in ZendDeveloperTools to record and display SQL queries + * + * @license MIT + * @link www.doctrine-project.org + * @author Marco Pivetta + */ +class SQLLoggerCollector implements CollectorInterface, AutoHideInterface +{ + /** + * Collector priority + */ + const PRIORITY = 10; + + /** + * @var DebugStack + */ + protected $sqlLogger; + + /** + * @var string + */ + protected $name; + + /** + * @param DebugStack $logger + * @param string $name + */ + public function __construct(DebugStack $sqlLogger, $name) + { + $this->sqlLogger = $sqlLogger; + $this->name = (string) $name; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function getPriority() + { + return static::PRIORITY; + } + + /** + * {@inheritDoc} + */ + public function collect(MvcEvent $mvcEvent) + { + } + + /** + * {@inheritDoc} + */ + public function canHide() + { + return empty($this->sqlLogger->queries); + } + + /** + * @return int + */ + public function getQueryCount() + { + return count($this->sqlLogger->queries); + } + + /** + * @return float + */ + public function getQueryTime() + { + $time = 0.0; + + foreach ($this->sqlLogger->queries as $query) { + $time += $query['executionMS']; + } + + return $time; + } +} diff --git a/src/DoctrineORMModule/Module.php b/src/DoctrineORMModule/Module.php index d3732fc9..993c93a7 100644 --- a/src/DoctrineORMModule/Module.php +++ b/src/DoctrineORMModule/Module.php @@ -21,11 +21,19 @@ use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\ORM\Tools\Console\ConsoleRunner; + use DoctrineModule\Service\DriverFactory; use DoctrineModule\Service\EventManagerFactory; + use DoctrineORMModule\Service\ConfigurationFactory as ORMConfigurationFactory; use DoctrineORMModule\Service\EntityManagerFactory; use DoctrineORMModule\Service\DBALConnectionFactory; +use DoctrineORMModule\Form\Annotation\AnnotationBuilder; + +// @todo move to own factory to allow wrapping of controllers +use DoctrineORMModule\Collector\SQLLoggerCollector; +use Doctrine\DBAL\Logging\DebugStack; +use Doctrine\DBAL\Logging\LoggerChain; use Zend\ModuleManager\ModuleManagerInterface; use Zend\ModuleManager\Feature\ServiceProviderInterface; @@ -117,9 +125,7 @@ public function getServiceConfig() ), 'factories' => array( 'DoctrineORMModule\Form\Annotation\AnnotationBuilder' => function(ServiceLocatorInterface $sl) { - return new \DoctrineORMModule\Form\Annotation\AnnotationBuilder( - $sl->get('doctrine.entitymanager.orm_default') - ); + return new AnnotationBuilder($sl->get('doctrine.entitymanager.orm_default')); }, 'doctrine.connection.orm_default' => new DBALConnectionFactory('orm_default'), @@ -128,7 +134,23 @@ public function getServiceConfig() 'doctrine.driver.orm_default' => new DriverFactory('orm_default'), 'doctrine.eventmanager.orm_default' => new EventManagerFactory('orm_default'), - ) + 'doctrine.collector.orm_default' => function(ServiceLocatorInterface $sl) { + $debugStackLogger = new DebugStack(); + /* @var $configuration \Doctrine\ORM\Configuration */ + $configuration = $sl->get('doctrine.configuration.orm_default'); + + if (null !== $configuration->getSQLLogger()) { + $logger = new LoggerChain(); + $logger->addLogger($debugStackLogger); + $logger->addLogger($configuration->getSQLLogger()); + $configuration->setSQLLogger($logger); + } else { + $configuration->setSQLLogger($debugStackLogger); + } + + return new SQLLoggerCollector($debugStackLogger, 'orm_default'); + }, + ), ); } } \ No newline at end of file diff --git a/tests/DoctrineORMModuleTest/Collector/SQLLoggerCollectorTest.php b/tests/DoctrineORMModuleTest/Collector/SQLLoggerCollectorTest.php new file mode 100644 index 00000000..f0f3b54e --- /dev/null +++ b/tests/DoctrineORMModuleTest/Collector/SQLLoggerCollectorTest.php @@ -0,0 +1,102 @@ +. + */ + +namespace DoctrineORMModuleTest\Paginator; + +use PHPUnit_Framework_TestCase as TestCase; +use DoctrineORMModule\Collector\SQLLoggerCollector; +use Doctrine\DBAL\Logging\DebugStack; +use Zend\Mvc\MvcEvent; + + +class SQLLoggerCollectorTest extends TestCase +{ + /** + * @var DebugStack + */ + protected $logger; + + /** + * @var string + */ + protected $name = 'test-collector-name'; + + /** + * @var SQLLoggerCollector + */ + protected $collector; + + public function setUp() + { + parent::setUp(); + $this->logger = new DebugStack(); + $this->collector = new SQLLoggerCollector($this->logger, $this->name); + } + + public function testHasCorrectName() + { + $this->assertSame($this->name, $this->collector->getName()); + } + + public function testGetPriority() + { + $this->assertInternalType('int', $this->collector->getPriority()); + } + + public function testCollect() + { + $this->collector->collect(new MvcEvent()); + } + + public function testCanHide() + { + $this->assertTrue($this->collector->canHide()); + $this->logger->startQuery('some sql'); + $this->assertFalse($this->collector->canHide()); + } + + public function testGetQueryCount() + { + $this->assertSame(0, $this->collector->getQueryCount()); + $this->logger->startQuery('some sql'); + $this->assertSame(1, $this->collector->getQueryCount()); + $this->logger->startQuery('some more sql'); + $this->assertSame(2, $this->collector->getQueryCount()); + } + + public function testGetQueryTime() + { + $start = microtime(true); + $this->assertEquals(0, $this->collector->getQueryTime()); + + $this->logger->startQuery('some sql'); + $this->logger->stopQuery(); + $time = microtime(true) - $start; + $time1 = $this->collector->getQueryTime(); + $this->assertGreaterThan(0, $time1); + $this->assertLessThan($time, $time1); + + $this->logger->startQuery('some more sql'); + $this->logger->stopQuery(); + $time = microtime(true) - $start; + $time2 = $this->collector->getQueryTime(); + $this->assertGreaterThan($time1, $time2); + $this->assertLessThan($time, $time1); + } +} \ No newline at end of file diff --git a/view/zend-developer-tools/toolbar/doctrine-orm.phtml b/view/zend-developer-tools/toolbar/doctrine-orm.phtml new file mode 100644 index 00000000..3eb7c055 --- /dev/null +++ b/view/zend-developer-tools/toolbar/doctrine-orm.phtml @@ -0,0 +1,27 @@ +
+
+ Database (Zend\Db) + + collector->getQueryCount(); ?> + queries in + ZDT_Time($this->collector->getQueryTime()); ?> s + +
+
+ Details + + Help us! + + Please help us improve +
+ profiling by forking and +
+ contributing to +
+ + DoctrineORMModule + +
+
+
+
\ No newline at end of file