Doctrine - วิธีการพิมพ์ sql จริงไม่ใช่แค่คำสั่งที่เตรียมไว้?


167

เรากำลังใช้ Doctrine, PHP ORM ฉันกำลังสร้างแบบสอบถามเช่นนี้:

$q = Doctrine_Query::create()->select('id')->from('MyTable');

และจากนั้นในฟังก์ชั่นที่ฉันเพิ่มเข้าไปในส่วนที่มีคำสั่งและสิ่งต่าง ๆ ตามความเหมาะสมเช่นนี้

$q->where('normalisedname = ? OR name = ?', array($string, $originalString));

ต่อมาก่อนที่จะexecute()สอบถามวัตถุนั้นฉันต้องการพิมพ์ raw SQL เพื่อตรวจสอบและทำสิ่งนี้:

$q->getSQLQuery();

อย่างไรก็ตามจะพิมพ์เฉพาะข้อความสั่งที่เตรียมไว้ไม่ใช่แบบสอบถามแบบเต็ม ฉันต้องการที่จะเห็นสิ่งที่มันถูกส่งไปยัง MySQL แต่แทนที่จะพิมพ์คำสั่งที่เตรียมไว้รวมถึง?ของ มีวิธีดูข้อความค้นหา "เต็ม" หรือไม่


วิธีที่ดีที่สุดที่ฉันได้พบเพื่อดูแบบสอบถามแบบเต็มมีคำอธิบายในคำตอบนี้: stackoverflow.com/a/678310/229077
Marek

คุณสามารถใช้ประโยชน์จากงานที่ทำโดย Doctrine (ผู้สร้างโปรไฟล์แสดงเคียวรีที่รันได้) ดูคำตอบของฉันด้านล่างสำหรับรายละเอียด
Vincent Pazeller

คำตอบ:


164

หลักคำสอนไม่ได้ส่ง "แบบสอบถาม SQL จริง" ไปยังเซิร์ฟเวอร์ฐานข้อมูล: มันเป็นจริงโดยใช้งบเตรียมซึ่งหมายความว่า:

  • ส่งคำสั่งเพื่อให้พร้อม (นี่คือสิ่งที่ส่งคืนโดย $query->getSql() )
  • และจากนั้นส่งพารามิเตอร์ (ส่งกลับโดย $query->getParameters() )
  • และดำเนินการคำสั่งที่เตรียมไว้

ซึ่งหมายความว่าจะไม่มีคิวรี SQL "ของจริง" ที่ด้าน PHP ดังนั้น Doctrine ไม่สามารถแสดงได้


14
ปาสคาล: คุณไม่ควรพูดว่ามันไม่ใช่ "แบบสอบถาม SQL จริง" เพราะคำสั่งที่เตรียมไว้เป็นแบบสอบถาม SQL จริงมันเป็นเพียงพารามิเตอร์ที่ส่งออกแยกต่างหาก ข้อความนี้อาจทำให้ผู้คนสับสน (เช่นolivierpons.fr/2014/03/22/symfony-2-avantages-et-inconvenients )
Matthieu Napoli

$query->getParameters();จะไม่ส่งคืนพารามิเตอร์ตามลำดับที่ถูกต้องเนื่องจากควรปรากฏในคำสั่งที่เตรียมไว้
gondo

4
ฉันคิดว่าที่นี่ผู้เขียนคำถามไม่สนใจว่าหลักคำสอนส่งหรือไม่ สิ่งที่ผู้ใช้และฉันต้องการทราบคือวิธีการรับแบบสอบถามซึ่งเราสามารถคัดลอกวางและเรียกใช้โดยไม่ต้องแทนที่เครื่องหมายคำถามด้วยพารามิเตอร์ เหมือนใน Codeigniter ฉันคิดว่าฉันพบสิ่งนี้ในดีบักเกอร์ symfony แต่ฉันยังไม่พบเมื่อฉันเรียกใช้สคริปต์จากบรรทัดคำสั่ง
Darius.V

104

ตัวอย่างการทำงาน:

$qb = $this->createQueryBuilder('a');
$query=$qb->getQuery();
// SHOW SQL: 
echo $query->getSQL(); 
// Show Parameters: 
echo $query->getParameters();

5
ในขณะที่มันทำงานเหมือนกับการกำหนดตัวแปรคุณอาจต้องการพิจารณาสิ่งนี้: พิมพ์ $ query-> getSQL (); foreach ($ query-> getParameters () เป็น $ param) {พิมพ์ "{$ param-> getName ()} -> {$ param-> getValue ()} \ n"; } เพราะคุณจะได้ผลลัพธ์ที่อ่านได้มากขึ้น
Justin Finkelstein

มันให้ผลประโยชน์น้อย เมื่อฉันคัดลอก sql ฉันยังคงมีพารามิเตอร์การค้นหา wichi ที่จะแทรกด้วยตนเองมันใช้เวลาตัน เราต้องการเคียวรีที่มีแทรก parameterrs ทำไมเราไม่สามารถค้นหาได้นานนัก แม้ในกรอบงาน codeigniter เท่าที่ฉันจำได้ใน profiler คุณสามารถคัดลอกแบบสอบถามและเรียกใช้ทันทีโดยไม่ต้องด้วยตนเอง เราต้องการเหมือนกันบน symfony
Darius.V

35

คุณสามารถตรวจสอบข้อความค้นหาที่ดำเนินการโดยแอปของคุณหากคุณบันทึกข้อความค้นหาทั้งหมดใน mysql:

http://dev.mysql.com/doc/refman/5.1/en/query-log.html

จะมีข้อความค้นหาเพิ่มเติมไม่เพียง แต่ข้อความค้นหาที่คุณต้องการ แต่คุณสามารถค้นหาได้

แต่มักจะ->getSql();ใช้งานได้

แก้ไข:

เพื่อดูแบบสอบถาม mysql ทั้งหมดที่ฉันใช้

sudo vim /etc/mysql/my.cnf 

และเพิ่ม 2 บรรทัดเหล่านั้น:

general_log = on
general_log_file = /tmp/mysql.log

และเริ่ม mysql ใหม่


17

ฉันได้สร้าง Doctrine2 Logger ที่ทำสิ่งนี้แล้ว มัน "hydrates" แบบสอบถาม sql parametrized กับค่าโดยใช้ตัวแปลงชนิดข้อมูลของ Doctrine 2

<?php


namespace Drsm\Doctrine\DBAL\Logging;
use Doctrine\DBAL\Logging\SQLLogger,
    Doctrine\DBAL\Types\Type,
    Doctrine\DBAL\Platforms\AbstractPlatform;
/**
 * A SQL logger that logs to the standard output and
 * subtitutes params to get a ready to execute SQL sentence

 * @author  dsamblas@gmail.com
 */
class EchoWriteSQLWithoutParamsLogger implements SQLLogger

{
    const QUERY_TYPE_SELECT="SELECT";
    const QUERY_TYPE_UPDATE="UPDATE";
    const QUERY_TYPE_INSERT="INSERT";
    const QUERY_TYPE_DELETE="DELETE";
    const QUERY_TYPE_CREATE="CREATE";
    const QUERY_TYPE_ALTER="ALTER";

    private $dbPlatform;
    private $loggedQueryTypes;
    public function __construct(AbstractPlatform $dbPlatform, array $loggedQueryTypes=array()){
        $this->dbPlatform=$dbPlatform;
        $this->loggedQueryTypes=$loggedQueryTypes;
    }
    /**
     * {@inheritdoc}
     */
    public function startQuery($sql, array $params = null, array $types = null)

    {
        if($this->isLoggable($sql)){
            if(!empty($params)){
                foreach ($params as $key=>$param) {
                    $type=Type::getType($types[$key]);
                    $value=$type->convertToDatabaseValue($param,$this->dbPlatform);
                    $sql = join(var_export($value, true), explode('?', $sql, 2));
                }

            }
            echo $sql . " ;".PHP_EOL;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function stopQuery()
    {

    }
    private function isLoggable($sql){
        if (empty($this->loggedQueryTypes)) return true;
        foreach($this->loggedQueryTypes as $validType){
            if (strpos($sql, $validType) === 0) return true;
        }
        return false;
    }
}

ตัวอย่างการใช้งาน:; ความสงบสุขของรหัสต่อไปนี้จะสะท้อนกับผลลัพธ์มาตรฐานใด ๆ INSERT, UPDATE, DELETE ประโยค SQL ที่สร้างด้วย $ em Entity Manager

/**@var  \Doctrine\ORM\EntityManager $em */
$em->getConnection()
                ->getConfiguration()
                ->setSQLLogger(
                    new EchoWriteSQLWithoutParamsLogger(
                        $em->getConnection()->getDatabasePlatform(),
                        array(
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_UPDATE,
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_INSERT,
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_DELETE
                        )
                    )
                );

1
ไม่ทำงานเมื่อพารามิเตอร์เป็นสตริงวันที่เช่น '2019-01-01'
Darius.V

14

getSqlQuery() ในทางเทคนิคแสดงคำสั่ง SQL ทั้งหมด แต่มีประโยชน์มากกว่าเมื่อคุณเห็นพารามิเตอร์เช่นกัน

echo $q->getSqlQuery();
foreach ($q->getFlattenedParams() as $index => $param)
  echo "$index => $param";

เพื่อให้รูปแบบนี้นำมาใช้ใหม่มากขึ้นมีวิธีการที่ดีที่อธิบายไว้ในความคิดเห็นที่วัตถุดิบ SQL จากวัตถุหลักคำสอนแบบสอบถาม


ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ลิงก์ทั้งสองของคุณนำไปสู่หน้า 404 คุณช่วยอัพเดทคำตอบของคุณได้ไหม? $qฉันถามเพราะผมไม่แน่ใจว่าสิ่งที่คุณหมายกับ ดูเหมือนจะไม่ใช่แบบสอบถามหรือเครื่องมือสร้างแบบสอบถาม
k00ni

1
ฉันเกรงว่าจะหารหัสที่ใช้ซ้ำไม่ได้อีก $qในกรณีนี้คือข้อความค้นหา Doctrine 1 คุณอาจใช้ Doctrine 2 ซึ่งในกรณีนี้คุณต้องการได้อย่าง$qb = $this->createQueryBuilder('a'); $q = $qb->getQuery(); $sql = $q->getSQL(); $params = $q->getParameters(); หวังว่าจะช่วยได้!
ภาระ

13

ไม่มีการสอบถามจริงอื่น ๆ นี่คือการทำงานของคำสั่งที่เตรียมไว้ ค่าถูกผูกไว้ในเซิร์ฟเวอร์ฐานข้อมูลไม่ใช่ในเลเยอร์แอปพลิเคชัน

ดูคำตอบของฉันสำหรับคำถามนี้: ใน PHP ด้วย PDO จะตรวจสอบคำถามสุดท้ายของ SQL แบบ parametrized ได้อย่างไร

(ซ้ำที่นี่เพื่อความสะดวก :)

การใช้คำสั่งที่เตรียมไว้พร้อมกับค่าที่แปรผันนั้นไม่ได้เป็นเพียงอีกวิธีในการสร้างสตริงของ SQL แบบไดนามิก คุณสร้างคำสั่งที่เตรียมไว้ที่ฐานข้อมูลแล้วส่งค่าพารามิเตอร์เพียงอย่างเดียว

ดังนั้นสิ่งที่อาจส่งไปยังฐานข้อมูลจะเป็นPREPARE ...แล้วSET ...และในที่สุดEXECUTE ....

คุณจะไม่สามารถรับสตริง SQL บางอย่างSELECT * FROM ...ได้แม้ว่ามันจะให้ผลลัพธ์ที่เทียบเท่าเพราะไม่มีการส่งแบบสอบถามแบบนี้ไปยังฐานข้อมูลเลย


9

ทางออกของฉัน:

 /**
 * Get SQL from query
 * 
 * @author Yosef Kaminskyi 
 * @param QueryBilderDql $query
 * @return int
 */
public function getFullSQL($query)
{
    $sql = $query->getSql();
    $paramsList = $this->getListParamsByDql($query->getDql());
    $paramsArr =$this->getParamsArray($query->getParameters());
    $fullSql='';
    for($i=0;$i<strlen($sql);$i++){
        if($sql[$i]=='?'){
            $nameParam=array_shift($paramsList);

            if(is_string ($paramsArr[$nameParam])){
                $fullSql.= '"'.addslashes($paramsArr[$nameParam]).'"';
             }
            elseif(is_array($paramsArr[$nameParam])){
                $sqlArr='';
                foreach ($paramsArr[$nameParam] as $var){
                    if(!empty($sqlArr))
                        $sqlArr.=',';

                    if(is_string($var)){
                        $sqlArr.='"'.addslashes($var).'"';
                    }else
                        $sqlArr.=$var;
                }
                $fullSql.=$sqlArr;
            }elseif(is_object($paramsArr[$nameParam])){
                switch(get_class($paramsArr[$nameParam])){
                    case 'DateTime':
                             $fullSql.= "'".$paramsArr[$nameParam]->format('Y-m-d H:i:s')."'";
                          break;
                    default:
                        $fullSql.= $paramsArr[$nameParam]->getId();
                }

            }
            else                     
                $fullSql.= $paramsArr[$nameParam];

        }  else {
            $fullSql.=$sql[$i];
        }
    }
    return $fullSql;
}

 /**
 * Get query params list
 * 
 * @author Yosef Kaminskyi <yosefk@spotoption.com>
 * @param  Doctrine\ORM\Query\Parameter $paramObj
 * @return int
 */
protected function getParamsArray($paramObj)
{
    $parameters=array();
    foreach ($paramObj as $val){
        /* @var $val Doctrine\ORM\Query\Parameter */
        $parameters[$val->getName()]=$val->getValue();
    }

    return $parameters;
}
 public function getListParamsByDql($dql)
{
    $parsedDql = preg_split("/:/", $dql);
    $length = count($parsedDql);
    $parmeters = array();
    for($i=1;$i<$length;$i++){
        if(ctype_alpha($parsedDql[$i][0])){
            $param = (preg_split("/[' ' )]/", $parsedDql[$i]));
            $parmeters[] = $param[0];
        }
    }

    return $parmeters;}

ตัวอย่างการใช้งาน:

$query = $this->_entityRepository->createQueryBuilder('item');
$query->leftJoin('item.receptionUser','users');
$query->where('item.customerid = :customer')->setParameter('customer',$customer)
->andWhere('item.paymentmethod = :paymethod')->setParameter('paymethod',"Bonus");
echo $this->getFullSQL($query->getQuery());

ขอบคุณสำหรับสิ่งนี้: D
Saad Achemlal

ดีมาก. ทำงานกับข้อความค้นหาปกติ แต่ฉันได้รับข้อความค้นหาด้วย regexp และดูเหมือนว่าไม่สนับสนุน $ qb = $ this-> createQueryBuilder ('r') -> innerJoin ('r.profile', 'p') -> addSelect (' p ') -> โดยที่ (' REGEXP (: fileNamePattern, r.fileNamePattern) = 1 ') -> andWhere (' p.incomingLocation =: ขาเข้าตำแหน่ง ') -> setParameters ([' fileNamePattern '=> $ fileName,' ขาเข้าตำแหน่ง ' => $ location]) -> getQuery ();
Fahim

ไม่สามารถใช้งานได้กับแบบสอบถามทั้งหมด เมื่อฉันมีสิ่งนี้ -> setParameters (อาร์เรย์ ('insuranceCarrier' => $ InsuranceCarrier, 'dateFrom' => $ dateFrom-> รูปแบบ ('Ym-d'), 'dateTo' => รูปแบบ $ dateTo-> ('Ym- d '),)) ที่เหลือเหล่านั้นด้วย? เครื่องหมายใน sql
Darius.V

9

คุณสามารถเข้าถึงพารามิเตอร์ SQL ได้อย่างง่ายดายโดยใช้วิธีการต่อไปนี้

   $result = $qb->getQuery()->getSQL();

   $param_values = '';  
   $col_names = '';   

   foreach ($result->getParameters() as $index => $param){              
            $param_values .= $param->getValue().',';
            $col_names .= $param->getName().',';
   } 

   //echo rtrim($param_values,',');
   //echo rtrim($col_names,',');    

ดังนั้นหากคุณพิมพ์$param_valuesและ$col_namesคุณจะได้รับค่าพารามิเตอร์ผ่านชื่อคอลัมน์ sql และตามลำดับ

หมายเหตุ: ถ้า $paramส่งคืนอาร์เรย์คุณจะต้องวนซ้ำเนื่องจากพารามิเตอร์ภายในIN (:?)มักจะมาเป็นอาร์เรย์ซ้อนกัน

ในขณะเดียวกันหากคุณพบวิธีการอื่นโปรดกรุณาแบ่งปันกับเรา :)

ขอบคุณ!


6

วิธีการแก้ปัญหาที่ชัดเจนมากขึ้น:

 /**
 * Get string query 
 * 
 * @param Doctrine_Query $query
 * @return string
 */
public function getDqlWithParams(Doctrine_Query $query){
    $vals = $query->getFlattenedParams();
    $sql = $query->getDql();
    $sql = str_replace('?', '%s', $sql);
    return vsprintf($sql, $vals);
}

$ query-> getFlattenedParams (); ไม่มีอยู่
นักพัฒนาซอฟต์แวร์

5
Solution:1
====================================================================================

function showQuery($query)
{
    return sprintf(str_replace('?', '%s', $query->getSql()), $query->getParams());
}

// call function  
echo showQuery($doctrineQuery);

Solution:2
====================================================================================

function showQuery($query)
{
    // define vars              
    $output    = NULL;
    $out_query = $query->getSql();
    $out_param = $query->getParams();

    // replace params
   for($i=0; $i<strlen($out_query); $i++) {
       $output .= ( strpos($out_query[$i], '?') !== FALSE ) ? "'" .str_replace('?', array_shift($out_param), $out_query[$i]). "'" : $out_query[$i];
   }

   // output
   return sprintf("%s", $output);
}

// call function  
echo showQuery($doctrineQueryObject);

5

คุณสามารถใช้ได้ :

$query->getSQL();

หากคุณใช้ MySQL คุณสามารถใช้ Workbench เพื่อดูคำสั่ง SQL ที่กำลังรันอยู่ คุณยังสามารถใช้ดูแบบสอบถามที่กำลังรันจาก mysql ได้โดยใช้คำสั่งต่อไปนี้:

 SHOW FULL PROCESSLIST \G

4

อาจเป็นประโยชน์กับบางคน:

// Printing the SQL with real values
$vals = $query->getFlattenedParams();
foreach(explode('?', $query->getSqlQuery()) as $i => $part) {
    $sql = (isset($sql) ? $sql : null) . $part;
    if (isset($vals[$i])) $sql .= $vals[$i];
}

echo $sql;

2

TL; DR

$qb = ... // your query builder
$query = $qb->getQuery();
// temporarily enable logging for your query (will also work in prod env)
$conf = $query->getEntityManager()->getConnection()->getConfiguration();
$backupLogger = $conf->getSQLLogger();
$logger = new \Doctrine\DBAL\Logging\DebugStack();
$conf->setSQLLogger($logger);
// execute query
$res = $query->getResult();
$conf->setSQLLogger($backupLogger); //restore logger for other queries
$params = [
  'query' => array_pop($logger->queries) //extract query log details
  //your other twig params here...
]
return $params; //send this to your twig template...

ในไฟล์ทวิกของคุณใช้ฟิลเตอร์ทวิกผู้ช่วย Doctrine:

// show raw query:
{{ (query.sql ~ ';')|doctrine_replace_query_parameters(query.params)
// highlighted
{{ (query.sql ~ ';')|doctrine_replace_query_parameters(query.params)|doctrine_pretty_query(highlight_only = true) }}
// highlighted and formatted (i.e. with tabs and newlines)
{{ (query.sql ~ ';')|doctrine_replace_query_parameters(query.params)|doctrine_pretty_query }}

คำอธิบาย:

คำตอบอื่น ๆ ที่กล่าวถึงว่าคำสั่งที่เตรียมไว้นั้นเป็นจริง "คำค้นหาจริง" นั้นถูกต้อง แต่พวกเขาไม่ตอบสนองต่อความคาดหวังของผู้ถามที่ชัดเจน ... นักพัฒนาทุกคนต้องการแสดง "แบบสอบถามที่เรียกใช้" สำหรับการดีบัก .

ดังนั้นฉันจึงดูแหล่งที่มาของผู้สร้างโปรไฟล์ของ Symfony เพื่อดูว่าพวกเขาทำได้อย่างไร ส่วนหลักคำสอนเป็นความรับผิดชอบของหลักคำสอนดังนั้นพวกเขาจึงสร้างกลุ่มคำสอนเพื่อรวมเข้ากับ Symfony ต้องดูที่doctrine-bundle/Resources/views/Collector/db.html.twigไฟล์คุณจะพบวิธีการใช้งานไฟล์ (สิ่งนี้อาจเปลี่ยนแปลงในทุกเวอร์ชัน) ที่น่าสนใจพวกเขาสร้างตัวกรองกิ่งไม้ที่เราสามารถนำมาใช้ใหม่ (ดูด้านบน)

เพื่อให้ทุกอย่างใช้งานได้เราจำเป็นต้องเปิดใช้งานการบันทึกสำหรับการสืบค้นของเรา มีหลายวิธีในการทำสิ่งนี้และที่นี่ฉันใช้ DebugStack ซึ่งอนุญาตให้บันทึกการสืบค้นโดยไม่ต้องพิมพ์จริง สิ่งนี้จะช่วยให้แน่ใจว่าสิ่งนี้จะทำงานในโหมดการผลิตหากนี่คือสิ่งที่คุณต้องการ ...

หากคุณต้องการการจัดรูปแบบเพิ่มเติมคุณจะเห็นว่าพวกเขามี CSS บางอย่างในแท็กสไตล์ดังนั้นเพียง "ขโมย" มัน ^^:

.highlight pre { margin: 0; white-space: pre-wrap; }
.highlight .keyword   { color: #8959A8; font-weight: bold; }
.highlight .word      { color: #222222; }
.highlight .variable  { color: #916319; }
.highlight .symbol    { color: #222222; }
.highlight .comment   { color: #999999; }
.highlight .backtick  { color: #718C00; }
.highlight .string    { color: #718C00; }
.highlight .number    { color: #F5871F; font-weight: bold; }
.highlight .error     { color: #C82829; }

หวังว่านี่จะช่วย ;-)


1

ฉันเขียนคนตัดไม้ธรรมดาซึ่งสามารถบันทึกแบบสอบถามด้วยพารามิเตอร์ที่แทรก การติดตั้ง:

composer require cmyker/doctrine-sql-logger:dev-master

การใช้งาน:

$connection = $this->getEntityManager()->getConnection(); 
$logger = new \Cmyker\DoctrineSqlLogger\Logger($connection);
$connection->getConfiguration()->setSQLLogger($logger);
//some query here
echo $logger->lastQuery;

1
$sql = $query->getSQL();

$parameters = [];
    foreach ($query->getParameters() as $parameter) {
        $parameters[] = $parameter->getValue();
    }

$result = $connection->executeQuery($sql, $parameters)
        ->fetchAll();

คุณควรเพิ่มข้อความในคำตอบเพื่ออธิบายว่าโค้ดทำอะไร
DarkMukke

0

ฟังก์ชัน @dsamblas ที่ปรับเปลี่ยนเพื่อทำงานเมื่อพารามิเตอร์เป็นสตริงวันที่เช่นนี้ '2019-01-01' และเมื่อมีอาร์เรย์ที่ส่งผ่านโดยใช้ IN like

$qb->expr()->in('ps.code', ':activeCodes'),

. ดังนั้นทำทุกสิ่งที่ dsamblas เขียน แต่แทนที่ startQuery ด้วยอันนี้หรือดูความแตกต่างและเพิ่มรหัสของฉัน (ในกรณีที่เขาแก้ไขบางอย่างในฟังก์ชั่นของเขาและเวอร์ชั่นของฉันไม่มีการดัดแปลง)

public function startQuery($sql, array $params = null, array $types = null)

{
    if($this->isLoggable($sql)){
        if(!empty($params)){
            foreach ($params as $key=>$param) {

                try {
                    $type=Type::getType($types[$key]);
                    $value=$type->convertToDatabaseValue($param,$this->dbPlatform);
                } catch (Exception $e) {
                    if (is_array($param)) {
                        // connect arrays like ("A", "R", "C") for SQL IN
                        $value = '"' . implode('","', $param) . '"';
                    } else {
                        $value = $param; // case when there are date strings
                    }
                }

                $sql = join(var_export($value, true), explode('?', $sql, 2));
            }

        }
        echo $sql . " ;".PHP_EOL;
    }
}

ทดสอบไม่มาก


0

ฉันทำการวิจัยบางอย่างสำหรับหัวข้อนี้เนื่องจากฉันต้องการดีบักเคียวรี SQL ที่สร้างขึ้นและเรียกใช้งานในเอดิเตอร์ sql เท่าที่เห็นในคำตอบทั้งหมดมันเป็นหัวข้อทางเทคนิคอย่างมาก

เมื่อฉันคิดว่าคำถามเริ่มต้นอยู่ที่ฐานของ dev-env คำตอบที่ง่ายมากหายไปในขณะนี้ คุณสามารถใช้บิลด์ใน Symfony profiler ได้ เพียงคลิกที่แท็บ Doctrine เลื่อนไปที่แบบสอบถามที่คุณต้องการตรวจสอบ จากนั้นคลิกที่ "ดูแบบสอบถามที่รันได้" และคุณสามารถวางแบบสอบถามของคุณโดยตรงในตัวแก้ไข SQL ของคุณ

วิธีการพื้นฐาน UI เพิ่มเติม แต่เร็วมากและไม่มีการดีบั๊กโค้ด

ป้อนคำอธิบายรูปภาพที่นี่


0
$sql = $query->getSQL();
$obj->mapDQLParametersNamesToSQL($query->getDQL(), $sql);
echo $sql;//to see parameters names in sql
$obj->mapDQLParametersValuesToSQL($query->getParameters(), $sql);
echo $sql;//to see parameters values in sql

public function mapDQLParametersNamesToSQL($dql, &$sql)
{
    $matches = [];
    $parameterNamePattern = '/:\w+/';
    /** Found parameter names in DQL */
    preg_match_all($parameterNamePattern, $dql, $matches);
    if (empty($matches[0])) {
        return;
    }
    $needle = '?';
    foreach ($matches[0] as $match) {
        $strPos = strpos($sql, $needle);
        if ($strPos !== false) {
            /** Paste parameter names in SQL */
            $sql = substr_replace($sql, $match, $strPos, strlen($needle));
        }
    }
}

public function mapDQLParametersValuesToSQL($parameters, &$sql)
{
    $matches = [];
    $parameterNamePattern = '/:\w+/';
    /** Found parameter names in SQL */
    preg_match_all($parameterNamePattern, $sql, $matches);
    if (empty($matches[0])) {
        return;
    }
    foreach ($matches[0] as $parameterName) {
        $strPos = strpos($sql, $parameterName);
        if ($strPos !== false) {
            foreach ($parameters as $parameter) {
                /** @var \Doctrine\ORM\Query\Parameter $parameter */
                if ($parameterName !== ':' . $parameter->getName()) {
                    continue;
                }
                $parameterValue = $parameter->getValue();
                if (is_string($parameterValue)) {
                    $parameterValue = "'$parameterValue'";
                }
                if (is_array($parameterValue)) {
                    foreach ($parameterValue as $key => $value) {
                        if (is_string($value)) {
                            $parameterValue[$key] = "'$value'";
                        }
                    }
                    $parameterValue = implode(', ', $parameterValue);
                }
                /** Paste parameter values in SQL */
                $sql = substr_replace($sql, $parameterValue, $strPos, strlen($parameterName));
            }
        }
    }
}

-1

หากต้องการพิมพ์แบบสอบถาม SQL ใน Doctrine ให้ใช้:

$query->getResult()->getSql();

อย่าลืมเพิ่มคำอธิบายด้วยคำตอบของคุณ? เพียงหนึ่งซับโดยไม่มีคำอธิบายไม่เป็นที่ยอมรับ
HaveNoDisplayName

1
หากต้องการพิมพ์ข้อความค้นหา sql ใน Doctrine ให้ใช้ $ query-> getResult () -> getSql (); ขอบคุณ
Jaydeep Patel

2
แทนการเพิ่ม commnet แก้ไขคำตอบของคุณ
HaveNoDisplayName
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.