has a real parser for the DQL language, which transforms the DQL statement
into an [Abstract Syntax Tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree)
and generates the appropriate SQL statement for it. Since this process is
deterministic Doctrine heavily caches the SQL that is generated from any given DQL query,
which reduces the performance overhead of the parsing process to zero.
You can modify the Abstract syntax tree by hooking into DQL parsing process
by adding a Custom Tree Walker. A walker is an interface that walks each
node of the Abstract syntax tree, thereby generating the SQL statement.
There are two types of custom tree walkers that you can hook into the DQL parser:
- An output walker. This one actually generates the SQL, and there is only ever one of them. We implemented the default SqlWalker implementation for it.
- A tree walker. There can be many tree walkers, they cannot generate the sql, however they can modify the AST before its rendered to sql.
Now this is all awfully technical, so let me come to some use-cases fast
to keep you motivated. Using walker implementation you can for example:
* Modify the AST to generate a Count Query to be used with a paginator for any given DQL query.
* Modify the Output Walker to generate vendor-specific SQL (instead of ANSI).
* Modify the AST to add additional where clauses for specific entities (example ACL, country-specific content...)
* Modify the Output walker to pretty print the SQL for debugging purposes.
In this cookbook-entry I will show examples on the first two points. There
are probably much more use-cases.
## Generic count query for pagination
Say you have a blog and posts all with one category and one author. A query
for the front-page or any archive page might look something like:
[sql]
SELECT p, c, a FROM BlogPost p JOIN p.category c JOIN p.author a WHERE ...
Now in this query the blog post is the root entity, meaning its the one that
is hydrated directly from the query and returned as an array of blog posts.
In contrast the comment and author are loaded for deeper use in the object tree.
A pagination for this query would want to approximate the number of posts that
match the WHERE clause of this query to be able to predict the number of pages
to show to the user. A draft of the DQL query for pagination would look like:
[sql]
SELECT count(DISTINCT p.id) FROM BlogPost p JOIN p.category c JOIN p.author a WHERE ...
Now you could go and write each of these queries by hand, or you can use a tree
walker to modify the AST for you. Lets see how the API would look for this use-case: