Drupal provides a user-friendly way for site creators or software developers to generate queries for Drupal content using the Drupal user interface. In the UI, the user can configure the fields, filters, sorting, and relationship in the generated query using basic and common conditions. Most of the cases, this is already enough. Yet, there are situations where you need to dynamically alter the constructed query using the hook_query_alter() function prior to its execution.

/**

 * Implementation of hook_query_alter().

 */

function example_query_alter(QueryAlterableInterface $query) {

  // ...

}

One of the most important features of dynamic queries is the ability of other modules to alter them on the fly. That allows other modules to inject their own restrictions and conditions into the query, either to alter the module’s behavior or to apply runtime restrictions on the query, such as node access restrictions.

In Query alteration, there is a tag-specific alter hook, hook_query_TAG_NAME_alter(), that is called for every tag on a given Select query, after the generic one has been called. The following example is called for queries that have the tag ‘sort_by_weight’:

/**

 * implements hook query alter to allow ordering by weight

 * @param QueryAlterableInterface $query

 */

function MYMODULE_query_sort_by_weight_alter(QueryAlterableInterface $query) {

  $query->join('weight_weights', 'w', 'node.nid = w.entity_id');

  $query->fields('w', array('weight'));

  $query->orderBy('w.weight', 'ASC');

}

As stated in the query alteration documentation, there are two important observations to be made regarding hook_query_alter().

  1. The $query parameter is not passed by reference. Because it is an object, the object will not be duplicated anyway due to the way PHP 5 and later handles objects. Passing by reference is therefore unnecessary. The alter hook also has no return value.
  2. The parameter is explicitly specified as QueryAlterableInterface. While not strictly necessary, explicitly specifying the parameter against passing in the wrong type of variable. The type is also specified as QueryAlterableInterface  rather than simply SelectQuery to better provide forward compatibility.

The alter hook may take any action on the query object it wishes, except executing the query again as that would reslt in an infinite loop loop. Module developers may either call additional methods on the query object as listed above to add additional fields, joins, conditionals, etc. to the query, or may request access to the query object's internal data structures to manipulate them directly. The former is preferred for adding new information to a query while the latter allows the alter hook to remove information from a query or manipulate instructions already queued up.

References: