Profile picture for user admin
Daniel Sipos
09 Nov 2015

Have you ever needed to override a Queue in Drupal 7? For example, the reliable database SystemQueue? It's actually quite easy and very flexible as well. Let me first tell you the use case we are going to work with in this article.

Let's say that we want to make sure that when adding items to a queue, those items don't already exist in the queue table. That's actually a fair request in my opinion. An option would be to make a query and see if the item already exists before delegating its creation to the responsible Queue class. However, we'd have to deal with querying for serialised data and is just not performant.

A better way is to use our own DrupalQueueInterface implementation:

/**
 * Custom implementation of the DrupalQueueInterface
 */
class MyCustomQueue extends SystemQueue {

  /**
   * Overriding the method to make sure no duplicate queue items get created
   * but that the items are updated if the exist.
   */
  public function createItem($data) {

    $serialized = serialize($data);

    $query = db_merge('queue')
      ->key(array('name' => $this->name, 'data' => $serialized))
      ->fields(array(
        'name' => $this->name,
        'data' => $serialized,
        'created' => time(),
      ));
    return (bool) $query->execute();
  }
}

As you can see, we are extending from the good ol' SystemQueue but overriding it's createItem() method. Instead of the db_insert() statement with which items were persisted, we are using a db_merge() statement to UPSERT the items. This means that if the items already exit, they get updated. If not, they get created. Which is exactly what we want.

Lastly, we need to make sure this class is being used for our queue. Again the solution is simple. Let's say our queue name is my_custom_queue. When requesting it like so:

DrupalQueue::get('my_custom_queue');

... Drupal looks in the variables table for a variable called queue_class_my_custom_queue. If it finds it, it will try to instantiate a class that has the name specified as the variable value (if it also implements DrupalQueueInterface). If there is no such variable, it falls back to the default one which is SystemQueue.

So this means that our module needs to create that variable so that when we are requesting this particular queue, we get an instance of our own class. We can do this inside install and uninstall hooks:

/**
 * Implements hook_install().
 */
function my_module_install() {
  variable_set('queue_class_my_custom_queue', 'MyCustomQueue');
}

/**
 * Implements hook_uninstall().
 */
function my_module_uninstall() {
  variable_del('queue_class_my_custom_queue');
}

And that is pretty much it. Now our queue will use the custom class we wrote and we can make sure no items are duplicated.

Hope this helps.

Profile picture for user admin

Daniel Sipos

CEO @ Web Omelette

Danny founded WEBOMELETTE in 2012 as a passion project, mostly writing about Drupal problems he faced day to day, as well as about new technologies and things that he thought other developers would find useful. Now he now manages a team of developers and designers, delivering quality products that make businesses successful.

Contact us

Comments

Roger Nyman 09 Nov 2015 23:28

Sorry, just can't spot the

Sorry, just can't spot the interface impelementation. What am I missing?
Thanks.

anou 24 Jul 2017 12:21

including custom queue class

Hello,
how do you include your custom queue class?
Did you just put it in your .module file?

or is it "better" to put it in a mymodule.queue.inc file and include it somehow?

Erik 05 Dec 2018 22:20

In reply to by anou (not verified)

I believe the "best practice"

I believe the "best practice" to add the file to you custom module's .info file, such as:

files[] = my_queue_class.queue.inc

When Drupal scans files and rebuilds its registry, the file will be picked up and its classes registered. I don't know if simply creating a mymodule.queue.inc file will have the same result.

Add new comment