Programatically working with Panels in Drupal is a bit of a nightmare. Trying to figure out how to obtain the right panel display and discover the right load and save tasks can be an utter disaster as you try trace code through ctools, page manager and panels itself while trying to understand what a ctools task or handler is or how to load them.

"But you don't need to programatically work with Panels. It has an export/import UI to work with and integration with the Features module." - While this is true in many cases, there are still reason to work with Panels in a programatic manor, for instance, when changes to panels are not always administer through code changes but through the admin UI on production. In this case, you can't risk revert your administrators changes when you want to only enforce your delta changes.

A Simple Example - Updating pane configuration on all node view template variants.

There doesn't seem to be a documented example of working with Panels programatically so I thought I'd give you a simple example of updating a cache setting on all panes of a certain type within the node_view "handler".

// The node template is managed by Page Manager as is known as a 'task';
$task = page_manager_get_task('node_view');
ctools_get_plugins('page_manager', 'task_handlers', 'panel_context');

// Tasks have arrays of handlers which we refer to in Panels as 'variants';
$handlers = page_manager_load_sorted_handlers($task, '', TRUE);

foreach ($handlers as $handler) {
  // Each handler/variant has an associate display in Panels which
  // is the object we actually want to load and save.
  $display = panels_panel_context_get_display($handler);
  $save = FALSE;

  // The panes are stored in a property called 'content'.
  foreach ($display->content as &$pane) {
    // Add country code as a value to vary by.
    if ($pane->type == 'block' && $pane->subtype == 'service_links-service_links') {
      $save = TRUE;
      $pane->cache['settings']['granularity']['lifetime'] = 180;  
  // Only save the display if changes were actually made.
  if ($save) {


  • Followed Drupal coding standards and added an if conditional statement around panels_save_display.
  • Use ctools_get_plugins() instead of ctools_include() will prevent plugins from being included twice.