$query = $this->createQuery(); return $query->matching($query->like('linker', "$linkerKey=$linkerValue")) ->setOrderings(array('crdate' => $ordering)) ->execute(); How can i debug such a generated query in extbase? When creating the same query again (but without the execute() ) and trying to display it with var_dump or the internal t3lib_div::debug i just receive a blank page.
20 Réponses :
$query = $this->createQuery(); $result = $query->matching($query->like('linker', "$linkerKey=$linkerValue")) ->setOrderings(array('crdate' => $ordering)) ->execute(); $GLOBALS['TYPO3_DB']->debugOutput = true; return $result;
Cela ne fonctionne pas pour moi du tout. Qu'est-ce que $ globals ['typo3_db'] -> debugoutoutputt = vrai; censé faire? Je n'ai aucun résultat. J'utilise typo3 4.6.6 ici et je ne peux pas obtenir le SQL généré par ExtBase. Pourquoi est-ce aussi difficile?
@Martin: Voir API.TYPO3.ORG/TTTYPO3CMS/47/HTML/ ...
Pour prolonger: Vous pouvez également attribuer 1 code> (identique que
true code>, pour
affichage des requêtes avec des erreurs code>) ou
2 code> ( Pour
Afficher toutes les requêtes code>).
$ Globals ['typo3_db'] -> debugoutputtput = 2; code> ne fonctionne pas ... Je ne comprends pas pourquoi il est un tel problème de simplement activer la production de requêtes SQL ...
Ce hack à exttasse est sale, mais utile:
dans typo3 / systext / extbase / classes / persistance / stockage / typo3dbbackend.php
Modifier la méthode BuildQuery (Array $ SQL)
Avant la déclaration de retour, ajoutez: p> Supprimer après utilisation, et n'oubliez pas que cela affectera tout ce qui fonctionne sur ExtBase, utilisez donc dans l'environnement DEV uniquement P> Source: http://sancer-media.net/2011/EXTBASE-SCHNE-MYSQL -debug.html p> p>
Merci d'avoir posté votre réponse! Veuillez noter que vous devriez poster les parties essentielles de la réponse ici, sur ce site ou vos risques posts supprimés voir la FAQ où il mentionne les réponses que sont à peine plus qu'un lien ". , vous pouvez toujours inclure le lien si vous le souhaitez, mais seulement comme une" référence ". La réponse devrait se tenir seul sans avoir besoin du lien.
Remarque, dans TYPO3 6.1 Ceci est à TYPO3 / SYSTEXT / ExtBase / Classes / Persistence / Générique / Stockage / Typ o3dbbackend.php - mais le hack ne fonctionne plus
Voir la réponse de @ Biesior à Stackoverflow.com/Questions / 13084863 / ... pour 6.1 - Travaux
Un moyen simple sans changer de code de base de TYPO3 et non mentionné dans aucun forum à ce jour utilise jusqu'à présent l'utilisation de la méthode PHP "Serialize ()": dans l'objet de résultat que vous trouvez le SQL Requête (rechercher "déclaration" ...) p> p>
extbase a maintenant un queryParser pour cela. Dans votre méthode de référentiel, juste avant de retourner la requête exécutée, insert: p> Le résultat est une vue de table des pièces de requête, divisée par des mots-clés SQL, par exemple: P > garder à l'esprit que le queryResult que votre référentiel retourne peut toujours être différent du résultat de la requête SQL. ExtBase utilise la propertyMapper pour essayer de convertir chaque ligne de résultat en extculaseObject. Si la propriété est mal configurée ou que la ligne contient des données qui ne peuvent pas être converties en types de données en fonction de la configuration, ces objets seront ignorés. Em> p> p> P> p>
Sur la version 8.7, cela donne mon erreur: Appel à la méthode non définie Typo3 \ cms \ extbase \ persistence \ generic \ Storage \ Typo3DBQuerypa RSER :: Parerery () Code>
Comme @pgampe a souligné, cette méthode est obsolète. Voir sa réponse pour une mise à jour.
O.k désormais maintenant déboguer une requête générée dans l'un des fichiers principaux tels que ceci: $ this-> xyrepository-> ajouter ($ xyObject);
en v6.2x ou plus tard, vous pouvez déboguer l'objet de résultat dans ExtBase comme: P>
dans le référentiel: p>
retour $ $ Query-> exécuter (vrai); // "vrai" retournera le résultat de la matrice p> blockQuote>
ou aussi vous pouvez déboguer l'objet de résultat dans le contrôleur: p>
$ résultantObject = ceci-> YourRepository-> résultats ();
\ Typo3 \ cms \ extbase \ utilitaire \ déboggerutilité :: var_dump ($ résultant); p> blockQuote>
dans la version $queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL());
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters());
Excellent!, Qui aide effectivement à trouver ce qui se passe en arrière.
Pourquoi cela n'est-il pas directement intégré dans la débogueur ?!
Merci. Ces lignes seront sobres pour moi.
Je pense que l'instruction SQL exécutable est nécessaire. $ QueryParser = $ this-> ObjectManager-> Obtenez (\ TYPO3 \ CMS \ ExtBase \ persistence \ Gen \ Storage \ Typo3DB QueryParser :: Classe); $ sql = $ QueryParser-> ConvertQuéryTodOctrineQueryBuilder ($ requis) -> GE TSQL (); $ paramters = $ QueryParser-> ConvertQuéryTodoctrineQueryBuilder ($ requis) -> GE TPARAMETTERS (); $ Search = Array (); $ remplaçable = tableau (); foreach ($ paramters comme $ k => $ v) {$ Search [] = ':'. $ k; $ Remplacer [] = '\' '. $ v. '\' '; } $ sql = str_replace ($ recherche, $ Remplacer, $ SQL); \ Typo3 \ cms \ extbase \ utilitaire \ déboggerutilité :: var_dump ($ SQL); code>
pgampe, @franzholzinger, basing sur vos réponses J'ai créé un référentiel abstrait comme indiqué dans une autre réponse , je suis intéressé par votre opinion et peut-être corriger et tester dans les précédentes versions TYPO3.
Cela fonctionne aussi longtemps que $ globals ['typo3_db'] est pris en charge.
Il vous montrera la requête complète de la construction SQL. Ainsi, avec cette fonction, vous pouvez faire quelque chose comme celui-ci dans votre contrôleur: p> $all = $this->repository->findAll();
$this->repository->debugQuery($all);
Ici, je pose une méthode que vous pouvez entrer pour le débogage de n'importe quelle classe, ce qui en fait un trait serait sûrement possible. La paternité et la source sont mentionnées dans le commentaire, l'utilisation également:
/** * Render the generated SQL of a query in TYPO3 8 * * @author wp_bube https://www.typo3.net/forum/user-profil/benutzer/zeige/benutzer/wp-bube/ * @src https://www.typo3.net/forum/thematik/zeige/thema/125747/ * * Usage: $this->debugQuery($query); * * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query * @param bool $format * @param bool $exit */ private function debugQuery($query, $format = true, $exit = true) { function getFormattedSQL($sql_raw) { if (empty($sql_raw) || !is_string($sql_raw)) { return false; } $sql_reserved_all = array( 'ACCESSIBLE', 'ACTION', 'ADD', 'AFTER', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AND', 'AS', 'ASC', 'AUTOCOMMIT', 'AUTO_INCREMENT', 'AVG_ROW_LENGTH', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'BY', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED', 'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT', 'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE', 'DAY_SECOND', 'DEFINER', 'DELAYED', 'DELAY_KEY_WRITE', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DO', 'DROP', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXECUTE', 'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FROM', 'FULL', 'FULLTEXT', 'FUNCTION', 'GEMINI', 'GEMINI_SPIN_RETRIES', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP', 'HAVING', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE', 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INNER', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL', 'INTO', 'INVOKER', 'IS', 'ISOLATION', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEFT', 'LEVEL', 'LIKE', 'LIMIT', 'LINEAR', 'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE', 'MASTER_LOG_POS', 'MASTER_PASSWORD', 'MASTER_PORT', 'MASTER_USER', 'MATCH', 'MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY', 'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUTER', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', 'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE', 'RAID_TYPE', 'RANGE', 'READ', 'READ_ONLY', 'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT', 'RETURN', 'RETURNS', 'REVOKE', 'RIGHT', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SELECT', 'SEPARATOR', 'SERIALIZABLE', 'SESSION', 'SET', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT', 'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CACHE', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF', 'SQL_LOG_UPDATE', 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_NO_CACHE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES', 'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER', 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE', 'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL', 'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNION', 'UNIQUE', 'UNLOCK', 'UPDATE', 'USAGE', 'USE', 'USING', 'VALUES', 'VARIABLES', 'VIEW', 'WHEN', 'WHERE', 'WITH', 'WORK', 'WRITE', 'XOR', 'YEAR_MONTH' ); $sql_skip_reserved_words = array('AS', 'ON', 'USING'); $sql_special_reserved_words = array('(', ')'); $sql_raw = str_replace("\n", " ", $sql_raw); $sql_formatted = ""; $prev_word = ""; $word = ""; for ($i = 0, $j = strlen($sql_raw); $i < $j; $i++) { $word .= $sql_raw[$i]; $word_trimmed = trim($word); if ($sql_raw[$i] == " " || in_array($sql_raw[$i], $sql_special_reserved_words)) { $word_trimmed = trim($word); $trimmed_special = false; if (in_array($sql_raw[$i], $sql_special_reserved_words)) { $word_trimmed = substr($word_trimmed, 0, -1); $trimmed_special = true; } $word_trimmed = strtoupper($word_trimmed); if (in_array($word_trimmed, $sql_reserved_all) && !in_array($word_trimmed, $sql_skip_reserved_words)) { if (in_array($prev_word, $sql_reserved_all)) { $sql_formatted .= '<b>' . strtoupper(trim($word)) . '</b>' . ' '; } else { $sql_formatted .= '<br/> '; $sql_formatted .= '<b>' . strtoupper(trim($word)) . '</b>' . ' '; } $prev_word = $word_trimmed; $word = ""; } else { $sql_formatted .= trim($word) . ' '; $prev_word = $word_trimmed; $word = ""; } } } $sql_formatted .= trim($word); return $sql_formatted; } $queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class); $doctrineQueryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query); $preparedStatement = $doctrineQueryBuilder->getSQL(); $parameters = $doctrineQueryBuilder->getParameters(); $stringParams = []; foreach ($parameters as $key => $parameter) { $stringParams[':' . $key] = $parameter; } $statement = strtr($preparedStatement, $stringParams); if ($format) { echo '<code>' . getFormattedSQL($statement) . '</code>'; } else { echo $statement; } if ($exit) { exit; } }
Selon @pgampe de la réponse et @franzholzinger S: J'ai créé abstractonrepository dans mon ext Wit Certaines méthodes extraites, pouvant être étendues dans votre propre référentiel Pour amener la possibilité de débogage un peu plus confortable.
note strong> c'est testé et fonctionne pour TYPO3 VER 10.x code>, la plupart fonctionnera probablement depuis
8.7 + Code> également, nécessite des tests. P>
<?php
namespace VENDOR\Extkey\Domain\Repository;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
class FooRepository extends \VENDOR\Extkey\Domain\Repository\AbstractRepository
{
public function findByName($name)
{
$query = $this->createQuery();
$query->matching(
$query->equals('name', $name)
);
$this->debugQuery($query, 'Debug SQL in repository with QueryInterface');
return $query->execute();
}
public function queryByName($name)
{
/** @var ConnectionPool $pool */
$pool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $pool->getConnectionForTable('tx_extkey_domain_model_yourmodel');
$queryBuilder = $connection->createQueryBuilder();
$query = $queryBuilder
->select('*')
->from('tx_extkey_domain_model_yourmodel')
->where("name like :name")
->setParameter('name', "%{$name}%");
$this->debugQuery($query, 'Debug SQL in my repository with QueryBuilder');
return $query->execute()->fetchAll();
}
Le seul inconvénient est que toutes les classes de référentiel sont obligées de dériver de l'abstractroptère. Il serait préférable d'avoir une classe d'API externe à la place.
Dans rendudebug () code> Les deux tableaux doivent être inversés. Sinon, un ": dcvalue12" remplacera en partie en recherchant et en remplaçant ': dcvalue1'. Dans l'ordre inverse, vous pouvez éviter cela.
Je construit une fonction statique d'une classe utilitie pour l'utilisation dans TYPO3 9.5.
Cela devrait fonctionner dans TYPO3 10.4. et typo3 11 Utilisation dans le référentiel p>
$query = $this->createQuery(); $result = $query->matching($query->like('linker', "$linkerKey=$linkerValue")) ->setOrderings(array('crdate' => $ordering)) ->execute(); $GLOBALS['TYPO3_DB']->debugOutput = true; return $result;
Cela ne fonctionne pas pour moi du tout. Qu'est-ce que $ globals ['typo3_db'] -> debugoutoutputt = vrai; censé faire? Je n'ai aucun résultat. J'utilise typo3 4.6.6 ici et je ne peux pas obtenir le SQL généré par ExtBase. Pourquoi est-ce aussi difficile?
@Martin: Voir API.TYPO3.ORG/TTTYPO3CMS/47/HTML/ ...
Pour prolonger: Vous pouvez également attribuer 1 code> (identique que
true code>, pour
affichage des requêtes avec des erreurs code>) ou
2 code> ( Pour
Afficher toutes les requêtes code>).
$ Globals ['typo3_db'] -> debugoutputtput = 2; code> ne fonctionne pas ... Je ne comprends pas pourquoi il est un tel problème de simplement activer la production de requêtes SQL ...
Ce hack à exttasse est sale, mais utile:
dans typo3 / systext / extbase / classes / persistance / stockage / typo3dbbackend.php
Modifier la méthode BuildQuery (Array $ SQL)
Avant la déclaration de retour, ajoutez: p> Supprimer après utilisation, et n'oubliez pas que cela affectera tout ce qui fonctionne sur ExtBase, utilisez donc dans l'environnement DEV uniquement P> Source: http://sancer-media.net/2011/EXTBASE-SCHNE-MYSQL -debug.html p> p>
Merci d'avoir posté votre réponse! Veuillez noter que vous devriez poster les parties essentielles de la réponse ici, sur ce site ou vos risques posts supprimés voir la FAQ où il mentionne les réponses que sont à peine plus qu'un lien ". , vous pouvez toujours inclure le lien si vous le souhaitez, mais seulement comme une" référence ". La réponse devrait se tenir seul sans avoir besoin du lien.
Remarque, dans TYPO3 6.1 Ceci est à TYPO3 / SYSTEXT / ExtBase / Classes / Persistence / Générique / Stockage / Typ o3dbbackend.php - mais le hack ne fonctionne plus
Voir la réponse de @ Biesior à Stackoverflow.com/Questions / 13084863 / ... pour 6.1 - Travaux
Un moyen simple sans changer de code de base de TYPO3 et non mentionné dans aucun forum à ce jour utilise jusqu'à présent l'utilisation de la méthode PHP "Serialize ()": dans l'objet de résultat que vous trouvez le SQL Requête (rechercher "déclaration" ...) p> p>
extbase a maintenant un queryParser pour cela. Dans votre méthode de référentiel, juste avant de retourner la requête exécutée, insert: p> Le résultat est une vue de table des pièces de requête, divisée par des mots-clés SQL, par exemple: P > garder à l'esprit que le queryResult que votre référentiel retourne peut toujours être différent du résultat de la requête SQL. ExtBase utilise la propertyMapper pour essayer de convertir chaque ligne de résultat en extculaseObject. Si la propriété est mal configurée ou que la ligne contient des données qui ne peuvent pas être converties en types de données en fonction de la configuration, ces objets seront ignorés. Em> p> p> P> p>
Sur la version 8.7, cela donne mon erreur: Appel à la méthode non définie Typo3 \ cms \ extbase \ persistence \ generic \ Storage \ Typo3DBQuerypa RSER :: Parerery () Code>
Comme @pgampe a souligné, cette méthode est obsolète. Voir sa réponse pour une mise à jour.
O.k désormais maintenant déboguer une requête générée dans l'un des fichiers principaux tels que ceci: $ this-> xyrepository-> ajouter ($ xyObject);
en v6.2x ou plus tard, vous pouvez déboguer l'objet de résultat dans ExtBase comme: P>
dans le référentiel: p>
retour $ $ Query-> exécuter (vrai); // "vrai" retournera le résultat de la matrice p> blockQuote>
ou aussi vous pouvez déboguer l'objet de résultat dans le contrôleur: p>
$ résultantObject = ceci-> YourRepository-> résultats ();
\ Typo3 \ cms \ extbase \ utilitaire \ déboggerutilité :: var_dump ($ résultant); p> blockQuote>
dans la version $queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getSQL());
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->convertQueryToDoctrineQueryBuilder($query)->getParameters());
Excellent!, Qui aide effectivement à trouver ce qui se passe en arrière.
Pourquoi cela n'est-il pas directement intégré dans la débogueur ?!
Merci. Ces lignes seront sobres pour moi.
Je pense que l'instruction SQL exécutable est nécessaire. $ QueryParser = $ this-> ObjectManager-> Obtenez (\ TYPO3 \ CMS \ ExtBase \ persistence \ Gen \ Storage \ Typo3DB QueryParser :: Classe); $ sql = $ QueryParser-> ConvertQuéryTodOctrineQueryBuilder ($ requis) -> GE TSQL (); $ paramters = $ QueryParser-> ConvertQuéryTodoctrineQueryBuilder ($ requis) -> GE TPARAMETTERS (); $ Search = Array (); $ remplaçable = tableau (); foreach ($ paramters comme $ k => $ v) {$ Search [] = ':'. $ k; $ Remplacer [] = '\' '. $ v. '\' '; } $ sql = str_replace ($ recherche, $ Remplacer, $ SQL); \ Typo3 \ cms \ extbase \ utilitaire \ déboggerutilité :: var_dump ($ SQL); code>
pgampe, @franzholzinger, basing sur vos réponses J'ai créé un référentiel abstrait comme indiqué dans une autre réponse , je suis intéressé par votre opinion et peut-être corriger et tester dans les précédentes versions TYPO3.
Cela fonctionne aussi longtemps que $ globals ['typo3_db'] est pris en charge.
Il vous montrera la requête complète de la construction SQL. Ainsi, avec cette fonction, vous pouvez faire quelque chose comme celui-ci dans votre contrôleur: p> $all = $this->repository->findAll();
$this->repository->debugQuery($all);
Ici, je pose une méthode que vous pouvez entrer pour le débogage de n'importe quelle classe, ce qui en fait un trait serait sûrement possible. La paternité et la source sont mentionnées dans le commentaire, l'utilisation également:
/** * Render the generated SQL of a query in TYPO3 8 * * @author wp_bube https://www.typo3.net/forum/user-profil/benutzer/zeige/benutzer/wp-bube/ * @src https://www.typo3.net/forum/thematik/zeige/thema/125747/ * * Usage: $this->debugQuery($query); * * @param \TYPO3\CMS\Extbase\Persistence\QueryInterface $query * @param bool $format * @param bool $exit */ private function debugQuery($query, $format = true, $exit = true) { function getFormattedSQL($sql_raw) { if (empty($sql_raw) || !is_string($sql_raw)) { return false; } $sql_reserved_all = array( 'ACCESSIBLE', 'ACTION', 'ADD', 'AFTER', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AND', 'AS', 'ASC', 'AUTOCOMMIT', 'AUTO_INCREMENT', 'AVG_ROW_LENGTH', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'BY', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED', 'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT', 'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE', 'DAY_SECOND', 'DEFINER', 'DELAYED', 'DELAY_KEY_WRITE', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DO', 'DROP', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXECUTE', 'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FROM', 'FULL', 'FULLTEXT', 'FUNCTION', 'GEMINI', 'GEMINI_SPIN_RETRIES', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP', 'HAVING', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE', 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INNER', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL', 'INTO', 'INVOKER', 'IS', 'ISOLATION', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEFT', 'LEVEL', 'LIKE', 'LIMIT', 'LINEAR', 'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE', 'MASTER_LOG_POS', 'MASTER_PASSWORD', 'MASTER_PORT', 'MASTER_USER', 'MATCH', 'MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY', 'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUTER', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', 'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE', 'RAID_TYPE', 'RANGE', 'READ', 'READ_ONLY', 'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT', 'RETURN', 'RETURNS', 'REVOKE', 'RIGHT', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SELECT', 'SEPARATOR', 'SERIALIZABLE', 'SESSION', 'SET', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT', 'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CACHE', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF', 'SQL_LOG_UPDATE', 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_NO_CACHE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES', 'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER', 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE', 'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL', 'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNION', 'UNIQUE', 'UNLOCK', 'UPDATE', 'USAGE', 'USE', 'USING', 'VALUES', 'VARIABLES', 'VIEW', 'WHEN', 'WHERE', 'WITH', 'WORK', 'WRITE', 'XOR', 'YEAR_MONTH' ); $sql_skip_reserved_words = array('AS', 'ON', 'USING'); $sql_special_reserved_words = array('(', ')'); $sql_raw = str_replace("\n", " ", $sql_raw); $sql_formatted = ""; $prev_word = ""; $word = ""; for ($i = 0, $j = strlen($sql_raw); $i < $j; $i++) { $word .= $sql_raw[$i]; $word_trimmed = trim($word); if ($sql_raw[$i] == " " || in_array($sql_raw[$i], $sql_special_reserved_words)) { $word_trimmed = trim($word); $trimmed_special = false; if (in_array($sql_raw[$i], $sql_special_reserved_words)) { $word_trimmed = substr($word_trimmed, 0, -1); $trimmed_special = true; } $word_trimmed = strtoupper($word_trimmed); if (in_array($word_trimmed, $sql_reserved_all) && !in_array($word_trimmed, $sql_skip_reserved_words)) { if (in_array($prev_word, $sql_reserved_all)) { $sql_formatted .= '<b>' . strtoupper(trim($word)) . '</b>' . ' '; } else { $sql_formatted .= '<br/> '; $sql_formatted .= '<b>' . strtoupper(trim($word)) . '</b>' . ' '; } $prev_word = $word_trimmed; $word = ""; } else { $sql_formatted .= trim($word) . ' '; $prev_word = $word_trimmed; $word = ""; } } } $sql_formatted .= trim($word); return $sql_formatted; } $queryParser = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class); $doctrineQueryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query); $preparedStatement = $doctrineQueryBuilder->getSQL(); $parameters = $doctrineQueryBuilder->getParameters(); $stringParams = []; foreach ($parameters as $key => $parameter) { $stringParams[':' . $key] = $parameter; } $statement = strtr($preparedStatement, $stringParams); if ($format) { echo '<code>' . getFormattedSQL($statement) . '</code>'; } else { echo $statement; } if ($exit) { exit; } }
Selon @pgampe de la réponse et @franzholzinger S: J'ai créé abstractonrepository dans mon ext Wit Certaines méthodes extraites, pouvant être étendues dans votre propre référentiel Pour amener la possibilité de débogage un peu plus confortable.
note strong> c'est testé et fonctionne pour TYPO3 VER 10.x code>, la plupart fonctionnera probablement depuis
8.7 + Code> également, nécessite des tests. P>
<?php
namespace VENDOR\Extkey\Domain\Repository;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
class FooRepository extends \VENDOR\Extkey\Domain\Repository\AbstractRepository
{
public function findByName($name)
{
$query = $this->createQuery();
$query->matching(
$query->equals('name', $name)
);
$this->debugQuery($query, 'Debug SQL in repository with QueryInterface');
return $query->execute();
}
public function queryByName($name)
{
/** @var ConnectionPool $pool */
$pool = GeneralUtility::makeInstance(ConnectionPool::class);
$connection = $pool->getConnectionForTable('tx_extkey_domain_model_yourmodel');
$queryBuilder = $connection->createQueryBuilder();
$query = $queryBuilder
->select('*')
->from('tx_extkey_domain_model_yourmodel')
->where("name like :name")
->setParameter('name', "%{$name}%");
$this->debugQuery($query, 'Debug SQL in my repository with QueryBuilder');
return $query->execute()->fetchAll();
}
Le seul inconvénient est que toutes les classes de référentiel sont obligées de dériver de l'abstractroptère. Il serait préférable d'avoir une classe d'API externe à la place.
Dans rendudebug () code> Les deux tableaux doivent être inversés. Sinon, un ": dcvalue12" remplacera en partie en recherchant et en remplaçant ': dcvalue1'. Dans l'ordre inverse, vous pouvez éviter cela.
Je construit une fonction statique d'une classe utilitie pour l'utilisation dans TYPO3 9.5.
Cela devrait fonctionner dans TYPO3 10.4. et typo3 11 Utilisation dans le référentiel p>