10

Given the following code, how can I print the SQL that is generated?

$bundle='my_bundle_type';
$query = \Drupal::entityQuery('node');
$query->condition('status', 1);
$query->condition('type', $bundle);
$entity_ids = $query->execute();

What I have tried:

  • __toString() doesn't work
  • dpq($query) throws an error

7 Answers 7

13

With debug tag (devel module is mandatory) we can print the raw sql.

$query = \Drupal::entityQuery('foo')->condition('bar', 'xyz')->addTag('debug');
$ids = $query->execute();
1
  • 5
    This isnt working for me. I have Devel enabled.
    – Jeff
    Commented Dec 5, 2018 at 2:43
12

UPDATE

My original answer is not valid anymore, now there's a good solution for this, see Sukhjinder Singh answer. In short: use Devel module and add tag 'debug', execute it and query will be printed.

$entityQueryObject->addTag('debug')->execute();

ORIGINAL ANSWER

As @kiamlaluno says, the problem is \Drupal::entityQuery() implements QueryInterface, not SelectInterface. dpq needs its first argument to implements that SelectInterface.

The object returned by \Drupal::entityQuery() is a Drupal\Core\Entity\Query\Sql\Query. This object has a protected property that implements the SelectInterface:

  /**
   * The build sql select query.
   *
   * @var \Drupal\Core\Database\Query\SelectInterface
   */
  protected $sqlQuery;

Unfortunately, the Query objects don't allow to access the $sqlQuery or print the SQL string.

As a very quick and dirty hack you can edit the Query class file in core/lib/Drupal/Core/Entity/Query/Sql/Query.php, change the $sqlQuery property to be public, and access it directly.

In Query.php, protected $sqlQuery should be public $sqlQuery;.

Then you can use the dpq function from devel module with the internal property. Make sure the devel module is installed (so it's enabled).

Prints a SQL string from a DBTNG Select object. Includes quoted arguments.

So in your case:

$sql_string = dpq($query->sqlQuery, TRUE));

Or just:

kint(dpq($query->sqlQuery, TRUE));

dpq() Parameters

  • object $query: An object that implements the SelectInterface interface.

  • boolean $return: Whether to return the string. Default is FALSE, meaning to print it and return $query instead.

  • string $name: Optional name for identifying the output.

IMPORTANT!!

This is a dirty trick, you should revert the Query.php file when you are done. Hacking Drupal core is a very bad practice and kittens, ponies and other puppies are suffering when you do that. Maybe even some unicorns are - better think twice about it.

Final thoughts

This a dirty workaround. Another better approach may exist but I'm not aware of it. If there is not a better way Drupal core may add some functionality to get the SQL string as sometimes is needed when debugging, and frankly, this hack is not a good way to do it.

10
  • Unfortunately, as I stated in the question the dpq throws error, I think it doesn't work with \Drupal::entityQuery Commented Mar 14, 2017 at 10:40
  • The OP said that function throws an error. He didn't say which error, exactly, so it could be the Devel module has not been installed.
    – avpaderno
    Commented Mar 14, 2017 at 10:40
  • 1
    I think the problem is the first argument dpq() is expecting: The object returned from \Drupal::entityQuery() implements QueryInterface, not SelectInterface. The first doesn't require the classes implementing it to have an addExpression() method, for example.
    – avpaderno
    Commented Mar 14, 2017 at 10:51
  • 1
    @downvoter, please explain the down vote. If you know a proper way to get the SQL string please share with us, I'm very interested in do it without this multiple-times-said dirt and quick hack.
    – sanzante
    Commented Mar 14, 2017 at 18:33
  • 2
    Tweaking core is always a hack, the API should allow this. Seems like the Query class itself needs a _toString() if it wants to keep $sqlQuery protected.
    – Grayside
    Commented Aug 30, 2017 at 21:56
2

With installed Devel module you can get the string with raw SQL query from EntityQuery class via:

$rawSqlQuery = (string) dpq($entityQuery);
echo $rawSqlQuery;
1

Here's another approach:

How can I debug entity queries in Drupal 8?

See the question in this link. This is a solution that has worked for me, if you add those two functions to a custom module, all you have to do is tag an entity query with "debug" to output the string version of the sql query.

0
1

You can simply use the __toString() option as below and look at the SQL in the $query variable.

 $query = \Drupal::entityQuery('node')
->condition('status', 1)
->condition('type', 'basic_page')
->condition('changed', $utc_start, '>=')
->__toString();
1
  • I tried this solution and it works, I am using Drupal 9.3. I just dumped like this : dump($query->__toString());
    – Hanane
    Commented Feb 20 at 15:24
0

You can use ReflectionClass in this case.

$reflection = new ReflectionClass(get_class($query));
$property = $reflection->getProperty('sqlQuery');
$entity_ids = $query->execute(); // this is required
$sql = (string)$property->getValue($query);
echo $sql;
-2

Enable Devel and Devel Kint modules then just try

 kint ($query);
5
  • 1
    This outputs the query object in a readable fashion, not the pure sql that would be generated by the query.
    – oknate
    Commented Mar 14, 2017 at 20:44
  • @oknate you can find raw query in kint output
    – Yuseferi
    Commented Mar 14, 2017 at 20:47
  • Awesome, can you add instructions to your answer on how to do that?
    – oknate
    Commented Mar 14, 2017 at 20:56
  • 1
    I tried using kint, unfortunately this eats my memory on a simple query. Commented Mar 15, 2017 at 18:15
  • @OlegVidenov yes, it's good debugging tool but memory hungry.
    – Yuseferi
    Commented Mar 15, 2017 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.