+++ Introduction

DQL (Doctrine Query Language) is a object query language which allows you to find objects. DQL understands things like object relationships, polymorphism and inheritance (including column aggregation inheritance). For more info about DQL see the actual DQL chapter.

{{Doctrine_Query}} along with {{Doctrine_Expression}} provide an easy-to-use wrapper for writing DQL queries. Creating a new query object can be done by either using the new operator or by calling create method. The create method exists for allowing easy method call chaining.

<code type="php">
// initalizing a new Doctrine_Query (using the current connection)
$q = new Doctrine_Query();

// initalizing a new Doctrine_Query (using custom connection parameter)
// here $conn is an instance of Doctrine_Connection
$q = new Doctrine_Query($conn);

// an example using the create method
// here we simple fetch all users
$users = new Doctrine_Query::create()->from('User')->execute();
</code>


+++ Selecting tables

The {{FROM}} clause indicates the component or components from which to retrieve records. If you name more than one component, you are performing a join. For each table specified, you can optionally specify an alias. {{Doctrine_Query}} offers easy to use methods such as {{from()}}, {{addFrom()}}, {{leftJoin()}} and {{innerJoin()}} for managing the {{FROM}} part of your DQL query.

<code type="php">
// find all users
$q = new Doctrine_Query();

$coll = $q->from('User')->execute();

// find all users with only their names (and primary keys) fetched

$coll = $q->select('u.name')->('User u');
</code>

The following example shows how to use leftJoin and innerJoin methods:  

<code type="php">
// find all groups

$coll = $q->from("FROM Group");

// find all users and user emails

$coll = $q->from("FROM User u LEFT JOIN u.Email e");

// find all users and user emails with only user name and
// age + email address loaded

$coll = $q->select('u.name, u.age, e.address')
          ->from('FROM User u')
          ->leftJoin('u.Email e')
          ->execute();

// find all users, user email and user phonenumbers

$coll = $q->from('FROM User u')
          ->innerJoin('u.Email e')
          ->innerJoin('u.Phonenumber p')
          ->execute();
</code>


+++ Limiting the query results

<code type="php">
// find the first ten users and associated emails

$q = new Doctrine_Query();

$coll = $q->from('User u LEFT JOIN u.Email e')->limit(10);

// find the first ten users starting from the user number 5

$coll = $q->from('User u')->limit(10)->offset(5);
</code>


+++ Setting query conditions

The {{WHERE}} clause, if given, indicates the condition or conditions that the records must satisfy to be selected.

{{Doctrine_Query}} provides easy to use {{WHERE}} -part management methods {{where}} and {{addWhere}}. The {{where}} methods always overrides the query {{WHERE}} -part whereas {{addWhere}} adds new condition to the {{WHERE}} -part stack.

<code type="php">
// find all groups where the group primary key is bigger than 10

$coll = $q->from('Group')->where('Group.id > 10');

// the same query using Doctrine_Expression component
$e    = $q->expr;
$coll = $q->from('Group')->where($e->gt('Group.id', 10));
</code>

Using regular expression operator: 

<code type="php">
// find all users where users where user name matches
// a regular expression, regular expressions must be 
// supported by the underlying database

$coll = $conn->query("FROM User WHERE User.name REGEXP '[ad]'");
</code>              

DQL has support for portable {{LIKE}} operator:   

<code type="php">
// find all users and their associated emails 
// where SOME of the users phonenumbers
// (the association between user and phonenumber 
// tables is One-To-Many) starts with 123

$coll = $q->select('u.*, e.*')
          ->from('User u LEFT JOIN u.Email e LEFT JOIN u.Phonenumber p')
          ->where(\"p.phonenumber LIKE '123%'");
</code>
 
Using multiple conditions and condition nesting are also possible:  

<code type="php">
// multiple conditions

$coll = $q->select('u.*')
          ->from('User u LEFT JOIN u.Email e')
          ->where(\"u.name LIKE '%Jack%' AND e.address LIKE '%@drinkmore.info'\");

// nesting conditions

$coll = $q->select('u.*')
          ->from('User u LEFT JOIN u.Email e')
          ->where(\"u.name LIKE '%Jack%' OR u.name LIKE '%John%') AND e.address LIKE '%@drinkmore.info'");
</code>


+++ HAVING conditions

{{Doctrine_Query}} provides {{having()}} method for adding {{HAVING}} conditions to the DQL query. This method is identical in function to the {{Doctrine_Query::where()}} method.

If you call {{having()}} multiple times, the conditions are ANDed together; if you want to OR a condition, use {{orHaving()}}.   

<code type="php">
$q = new Doctrine_Query();

$users = $q->select('u.name')
           ->from('User u')
           ->leftJoin('u.Phonenumber p');
           ->having('COUNT(p.id) > 3');
</code>


+++ Sorting query results

{{ORDER BY}} - part works in much same way as SQL {{ORDER BY}}. 

<code type="php">
$q = new Doctrine_Query();

// find all users, sort by name descending

$users = $q->from('User u')->orderby('u.name DESC');

// find all users sort by name ascending

$users = $q->from('User u')->orderby('u.name ASC');

// find all users and their emails, sort by email address in ascending order

$users = $q->from('User u')->leftJoin('u.Email e')->orderby('e.address');

// find all users and their emails, sort by user name and email address

$users = $q->from('User u')->leftJoin('u.Email e')
           ->addOrderby('u.name')->addOrderby('e.address');

// grab randomly 10 users
$users = $q->select('u.*, RAND() rand')->from('User u')->limit(10)->orderby('rand DESC');
</code>

