DoctrineDataCollector.php 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bridge\Doctrine\DataCollector;
  11. use Doctrine\Common\Persistence\ManagerRegistry;
  12. use Doctrine\DBAL\Logging\DebugStack;
  13. use Doctrine\DBAL\Types\Type;
  14. use Symfony\Component\HttpKernel\DataCollector\DataCollector;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. /**
  18. * DoctrineDataCollector.
  19. *
  20. * @author Fabien Potencier <fabien@symfony.com>
  21. */
  22. class DoctrineDataCollector extends DataCollector
  23. {
  24. private $registry;
  25. private $connections;
  26. private $managers;
  27. private $loggers = array();
  28. public function __construct(ManagerRegistry $registry)
  29. {
  30. $this->registry = $registry;
  31. $this->connections = $registry->getConnectionNames();
  32. $this->managers = $registry->getManagerNames();
  33. }
  34. /**
  35. * Adds the stack logger for a connection.
  36. *
  37. * @param string $name
  38. * @param DebugStack $logger
  39. */
  40. public function addLogger($name, DebugStack $logger)
  41. {
  42. $this->loggers[$name] = $logger;
  43. }
  44. /**
  45. * {@inheritdoc}
  46. */
  47. public function collect(Request $request, Response $response, \Exception $exception = null)
  48. {
  49. $queries = array();
  50. foreach ($this->loggers as $name => $logger) {
  51. $queries[$name] = $this->sanitizeQueries($name, $logger->queries);
  52. }
  53. $this->data = array(
  54. 'queries' => $queries,
  55. 'connections' => $this->connections,
  56. 'managers' => $this->managers,
  57. );
  58. }
  59. public function getManagers()
  60. {
  61. return $this->data['managers'];
  62. }
  63. public function getConnections()
  64. {
  65. return $this->data['connections'];
  66. }
  67. public function getQueryCount()
  68. {
  69. return array_sum(array_map('count', $this->data['queries']));
  70. }
  71. public function getQueries()
  72. {
  73. return $this->data['queries'];
  74. }
  75. public function getTime()
  76. {
  77. $time = 0;
  78. foreach ($this->data['queries'] as $queries) {
  79. foreach ($queries as $query) {
  80. $time += $query['executionMS'];
  81. }
  82. }
  83. return $time;
  84. }
  85. /**
  86. * {@inheritdoc}
  87. */
  88. public function getName()
  89. {
  90. return 'db';
  91. }
  92. private function sanitizeQueries($connectionName, $queries)
  93. {
  94. foreach ($queries as $i => $query) {
  95. $queries[$i] = $this->sanitizeQuery($connectionName, $query);
  96. }
  97. return $queries;
  98. }
  99. private function sanitizeQuery($connectionName, $query)
  100. {
  101. $query['explainable'] = true;
  102. $query['params'] = (array) $query['params'];
  103. foreach ($query['params'] as $j => &$param) {
  104. if (isset($query['types'][$j])) {
  105. // Transform the param according to the type
  106. $type = $query['types'][$j];
  107. if (is_string($type)) {
  108. $type = Type::getType($type);
  109. }
  110. if ($type instanceof Type) {
  111. $query['types'][$j] = $type->getBindingType();
  112. $param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
  113. }
  114. }
  115. list($param, $explainable) = $this->sanitizeParam($param);
  116. if (!$explainable) {
  117. $query['explainable'] = false;
  118. }
  119. }
  120. return $query;
  121. }
  122. /**
  123. * Sanitizes a param.
  124. *
  125. * The return value is an array with the sanitized value and a boolean
  126. * indicating if the original value was kept (allowing to use the sanitized
  127. * value to explain the query).
  128. *
  129. * @param mixed $var
  130. * @return array
  131. */
  132. private function sanitizeParam($var)
  133. {
  134. if (is_object($var)) {
  135. return array(sprintf('Object(%s)', get_class($var)), false);
  136. }
  137. if (is_array($var)) {
  138. $a = array();
  139. $original = true;
  140. foreach ($var as $k => $v) {
  141. list($value, $orig) = $this->sanitizeParam($v);
  142. $original = $original && $orig;
  143. $a[$k] = $value;
  144. }
  145. return array($a, $original);
  146. }
  147. if (is_resource($var)) {
  148. return array(sprintf('Resource(%s)', get_resource_type($var)), false);
  149. }
  150. return array($var, true);
  151. }
  152. }