Change record status: 
Project: 
Introduced in branch: 
8.x
Introduced in version: 
8.x
Description: 

The inconsistent 'attribute_array', 'attribute' string, 'classes_array', 'classes' string have been combined together into an Attribute object. The object can be printed as a string, and accessed and added to like an array. drupal_attributes() has now been removed in favour of this new class.

Make sure to include the correct Attribute class

use Drupal\Core\Template\Attribute;

To create an Attribute object:

$variables['item_attribute'] = new Attribute();

By default, Drupal will initialize three Attribute objects in template_preprocess() that are accessible in pre/process functions as $variables['attributes'], $variables['title_attributes'], $variables['content_attributes']. For all of these, the 'class' attribute is pre-initialized to the empty array. If more are needed, initialize a new one via

$attributes = array('class' => array('class-1', 'class-2'));
$variables['item_attribute'] = new Attribute($attributes);

Attributes can be added to the object either when passed in initially (like above) and as needed using array syntax.

For example, to add an ID:

$variables['item_attribute'] = new Attribute();
$variables['item_attribute']['id'] = 'my-id';

There are three types of attributes: array, string, and boolean.

string is the most common type, and can be seen above in the ID example.

Classes are an example to use array for. When using array, you must initialize the array first before adding items.

  $variables['item_attribute'] = new Attribute();
  $variables['item_attribute']['class'] = array();
  $variables['item_attribute']['class'][] = 'class-1';

Use this so different classes can easily be removed/added as needed.

It will print out as a string with each item separated by a space, e.g.:

<div class="class-1 class-2"></div>

Boolean is for HTML boolean attributes that are either on or off (not ones that can contain the value TRUE/FALSE, as those can also contain other values). For example, the disabled attribute. When seen in a tag, it looks like:

  <checkbox disabled>
  $variables['item_attribute'] = new Attribute();
  // This will print just "disabled", not disabled="disabled"
  $variables['item_attribute']['disabled'] = TRUE;
  // To remove it, so it prints no output.
  $variables['item_attribute']['disabled'] = FALSE;

Please use lowercase for key names and always use array syntax for classes.

When upgrading themes, change:

PHPTemplate (7.x):

<div class="<?php print $classes; ?>"<?php print $attributes; ?>>

to Twig (8.x):

<div class="{{ attributes.class }}"{{ attributes|without('class') }}>

However, this:

<div{{ attributes }}>

will print out the same. When printing out individual attributes to customize them within a template, use the Twig "without" filter to prevent attributes that have already been printed from being printed again.

You can also instantiate and print an Attribute inline. This is functionality equivalent to calling the old drupal_attributes() with the same arguments.

$output = '<span' . new Attribute(array('class' => array('first', 'last')) . '>some text</span>';
Impacts: 
Module developers
Themers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

KarenS’s picture

Note that when you switch from drupal_attributes() to new Attribute() you may have to add the following to the top of every file that creates a new Attribute. You'll know that it is needed if you see a message that the Attribute class doesn't exist.

use Drupal\Core\Template\Attribute;
mparker17’s picture

Beware when reading attributes: by design, this class doesn't output an HTML attribute if it's already been accessed.

See http://api.drupal.org/comment/49228#comment-49228 for more information.

rooby’s picture

I have replied to that comment you posted with an explanation of why it happens.

Hopefully that helps people better understand how the Attribute object works.

mikeker’s picture

Not sure when the underlying fix went in, but the documentation was changed on 14 Aug 2014 to reflect the new functionality. You can call __toPrint() on an Attribute instance and get the same result each time. There is no longer a need to use __clone().

- Mike