Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Working with a Database in Drupal 7 - Lesson 5 - Extenders

17/04/2025, by Ivan

Select queries in Drupal support extenders. An extender allows you to add functionality to a SELECT query at runtime. This functionality can either be a new method or can override the behavior of an existing one.

This is achieved using object-oriented programming design patterns. Extenders implement the Decorator Pattern, attaching additional responsibilities to a dynamic object by providing a flexible subclass-like extension of query methods.

Using Extenders

To use an extender, you must start with a query object. Calling the extend() method on a query returns a new object with added functionality. For example:

extend('PagerDefault');
?>

In this example, a new PagerDefault object wraps the original query object, adding pagination functionality. The $query variable is replaced with the returned extended object—important for using the extended methods. If you forget to assign the result of extend(), you'll lose access to the extended features:

fields('n', array('nid', 'title'))
  ->extend('PagerDefault')  // returns a new object
  ->limit(5);               // works on the PagerDefault object

// But this refers to the original SelectQuery object again!
$query->orderBy('title');

// So the execute() below won't use the PagerDefault features.
$result = $query->execute();
?>

To avoid such issues, always assign the result of extend() back to the query variable:

extend('PagerDefault')->extend('TableSort');
$query->fields(...);
// ...
?>

This ensures that $query is fully extended before calling any methods. You can chain multiple extenders, but note that the order can matter. For instance, TableSort should come after PagerDefault.

Creating Custom Extenders

An extender is simply a class that implements SelectQueryInterface and accepts two parameters in its constructor: the base select query and the database connection. Typically, you’ll subclass SelectQueryExtender, which handles most of the interface for you.

You can define any extender by subclassing SelectQueryExtender. The name of the class is what you pass to extend(). You may override existing methods or define your own, as needed.

The extender must return what the interface expects—usually the query object or another extender object. You can chain methods or decorate the query however you like.

Example Extender

query->orderBy($field, $direction);
    return $this;
  }
}
?>

In this example, orderBy() is overridden with a no-op, and a new method orderByForReal() is introduced to perform the actual sorting. Both methods return $this to preserve the query object for chaining.

Any module can define its own extenders. Drupal core provides two useful built-in extenders: PagerDefault and TableSort.

Supporting Multiple Databases

Just like db_select(), extenders support database-specific versions. Drupal will automatically look for a database-specific suffix for your extender class. For example:

  • ExampleExtender_pgsql
  • ExampleExtender_mysql

If available, Drupal will use the DBMS-specific class automatically. This helps ensure compatibility with different database backends while maintaining consistent logic in your query handling.