Concrete CMS features a robust and powerful system for associating custom data with different types of objects like pages, users and files. If you've ever set the 'Exclude from Nav' checkbox to true on a page, or looked at a file's width or height, or added some custom preferences for a user account, you've interacted with custom attributes.

Creating a custom attribute for tracking data against a page, user or file object is something that any Concrete editor can easily do using the tools in the Dashboard; this is all documented in the editor's guide. However, as a Concrete developer there are a number of ways attributes can be used and extended. Developers can add completely new types of attributes to Concrete, and can also use attributes in their own custom objects. And since attributes are the bedrock of all the data behind Express that just makes learning about them more important than ever.

Note: This is just an overview - read through the other pages in this section for some helpful code examples and more in-depth details about the different ways of working with attributes.


Before we talk about how we can extend the Concrete custom attribute system, let's explain some of the concepts behind it so we know everyone understands the terminology.

Attribute Keys

Attribute keys (or simply "custom attributes" if you're describing Concrete for an editor audience) are the custom attributes you add through the Dashboard user interface. Examples of attribute keys include "Exclude from Nav", "Meta Keywords", "Blog Topics", "Width", "Height", etc... When adding an attribute through the user interface of Concrete, you're adding an attribute key.

Attribute Types

Attribute types are the types of data that a custom attribute can store, when creating an attribute key. Attribute types include "Text", "Textarea", "Boolean", "Select", "Image/File", and more. Creating custom attribute types are one of the most common ways that developers extend the Concrete custom attribute system. Custom attribute types can be included in packages easily, and make it so that developers can create bespoke, targeted interfaces for custom problems, and store specific data in an easily reusable way.

Attribute Key Settings

New in version 8, attribute key settings objects are just a simple way to store settings about a particular attribute key, rather than just having to create custom database queries to store type-specific settings. For example, when you create a textarea attribute, you'll also be storing whether the textarea attribute uses plain text or rich text. This type-specific settings data will be stored within a custom object found at Concrete\Core\Entity\Attribute\Key\Settings\TextareaSettings. This is all handled within the attribute controller in an easy to understand manner, without a lot of custom coding.

Attribute Categories

Attribute categories are the types of objects in Concrete that can join to custom attribute values. Attribute categories that ship with the core include Pages, Files and Users.

Attribute Values

Any time you assign a value to a page, file or user through the Concrete user interface or through custom code, you're creating an attribute value behind the scenes. Attribute values join the identifier of an attribute category (e.g. a page ID + a page version ID) with an attribute key and an data value object.

Attribute Data Values

Attribute data value objects store type-specific data in the database. For example, if you're setting a numerical value against a custom attribute, you're creating a data value of object of the type Concrete\Core\Entity\Attribute\Value\Value\NumberValue, with the specific details of the data value object set.

Attribute Controllers

Every attribute type has a controller; this is a Concrete class responsible for setting data in various views, and providing the output for the data value objects in different situations. When you create a custom attribute type, you'll definitely be creating a controller to go with it.

Attribute Types

Now that we understand the terminology behind attributes, let's work on one of the most common things a developer might do with custom attributes – create a new one.