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 documentation is for Concrete 8.0 and higher. While custom attributes have been around for a long time, and much of this documentation applies to earlier versions, the differences are great enough that creating version 8-specific documentation has to be the priority. (Trust me, it'll be worth it.)
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 (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 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 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.
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.
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.
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.