contentbox-cfml-content-types
Use this skill when implementing ContentBox content models and rendering flows, including entries/pages/content stores, custom fields, entity relationships, lifecycle callbacks, and content-type specific behaviors.
ContentBox Content Types & Custom Fields (CFML)
Extend ContentBox content types and add custom fields using CFML. ContentBox supports entries, pages, and ContentStore items with extensible custom field capabilities.
Content Types
ContentBox has three primary content types:
| Type | Entity | Service | Description |
|---|---|---|---|
| Entries | Entry | entryService@contentbox | Blog posts with dates, categories, comments |
| Pages | Page | pageService@contentbox | Static pages with hierarchical structure |
| ContentStore | ContentStore | contentStoreService@contentbox | Key-value content blocks |
Entry Entity
property name="entryService" inject="entryService@contentbox";
// Entry properties
entry.getEntryID()
entry.getTitle()
entry.getSlug()
entry.getHTMLContent()
entry.getPlainTextContent()
entry.getPublishedDate()
entry.getCreatedDate()
entry.getModifiedDate()
entry.getIsActive()
entry.getIsPublished()
entry.getHits()
entry.getNumberOfComments()
// Relationships
entry.getAuthor() // Author entity
entry.getCategories() // Query of categories
entry.getComments() // Query of comments
entry.getSite() // Site entity
entry.getFeaturedImage() // Media entity
// Status
entry.getStatus() // "published", "draft", "pending"
entry.isPublished()
entry.isDraft()
Page Entity
property name="pageService" inject="pageService@contentbox";
// Page properties
page.getPageID()
page.getTitle()
page.getSlug()
page.getHTMLContent()
page.getPlainTextContent()
page.getCreatedDate()
page.getModifiedDate()
page.getIsActive()
page.getIsPublished()
page.getMenuOrder() // For ordering in menus
page.getParent() // Parent page (hierarchical)
page.getChildren() // Child pages
// Relationships
page.getAuthor()
page.getSite()
page.getFeaturedImage()
ContentStore Entity
property name="contentStoreService" inject="contentStoreService@contentbox";
// ContentStore is a key-value store
contentStoreService.getValue( "key" )
contentStoreService.setValue( "key", "value" )
contentStoreService.deleteValue( "key" )
contentStoreService.getAll()
// ContentStore entity
item.getContentStoreID()
item.getSlug() // The key
item.getContent() // The value
item.getCreatedDate()
item.getModifiedDate()
Custom Fields
ContentBox supports custom fields through the cbCustomField entity and service:
property name="customFieldService" inject="customFieldService@contentbox";
// Create custom field
var field = customFieldService.new( {
name : "subtitle",
label : "Subtitle",
type : "text", // text, textarea, boolean, select, date, number
required : false,
defaultValue: "",
contentType : "entry", // "entry", "page", or "all"
order : 1
} );
customFieldService.save( field );
// Get custom fields for content type
var fields = customFieldService.findByContentType( "entry" );
Custom Field Types
| Type | Description |
|---|---|
text | Single-line text input |
textarea | Multi-line text area |
boolean | Checkbox toggle |
select | Dropdown select |
date | Date picker |
number | Numeric input |
media | Media picker |
html | HTML editor |
Accessing Custom Field Values
// Get custom field value from entry
var subtitle = entry.getCustomFieldValue( "subtitle" );
// Get all custom field values
var fields = entry.getCustomFields();
Content Helpers (Mixins)
Inject mixins into all content objects via settings:
// In ModuleConfig.cfc configure()
settings.contentHelpers = [
"mymodule.models.mixins.MyContentMixin"
];
Creating a Content Mixin
<!--- models/mixins/MyContentMixin.cfc --->
<cfcomponent>
<cffunction name="getExcerpt" access="public" returntype="string">
<cfargument name="maxLength" type="numeric" default="200">
<cfreturn left( this.getPlainTextContent(), arguments.maxLength ) & "...">
</cffunction>
<cffunction name="getReadingTime" access="public" returntype="numeric">
<cfset var wordCount = arrayLen( listToArray( this.getPlainTextContent(), " " ) )>
<cfreturn ceiling( wordCount / 200 )>
</cffunction>
</cfcomponent>
Using Content Mixins
// After injecting, methods are available on all content objects
var excerpt = entry.getExcerpt( 150 );
var readTime = entry.getReadingTime();
Content Rendering
Content Renderers
ContentBox uses interceptors to process content before rendering:
| Renderer | Class | Purpose |
|---|---|---|
| Link Renderer | LinkRenderer@contentbox | Process internal links |
| Widget Renderer | WidgetRenderer@contentbox | Process {widget:...} shortcodes |
| Setting Renderer | SettingRenderer@contentbox | Process {setting:...} shortcodes |
| Markdown Renderer | MarkdownRenderer@contentbox | Process Markdown content |
Widget Shortcode
{widget:WidgetName arg1="value" arg2="value"}
Setting Shortcode
{setting:cb_site_title}
Content Lifecycle
Entry Lifecycle
// Interception points
cbadmin_preEntrySave // Before entry saved
cbadmin_postEntrySave // After entry saved
cbadmin_preEntryRemove // Before entry deleted
cbadmin_postEntryRemove // After entry deleted
cbadmin_onEntryStatusUpdate // When status changes
cb_onContentRendering // Before content rendered
Page Lifecycle
// Interception points
cbadmin_prePageSave
cbadmin_postPageSave
cbadmin_prePageRemove
cbadmin_postPageRemove
cbadmin_onPageStatusUpdate
cb_onContentRendering
Content Queries
EntryService Queries
property name="entryService" inject="entryService@contentbox";
// Find published entries
var entries = entryService.findPublishedContent(
max : 10,
category : "news",
searchTerm: "search term",
sortOrder : "publishedDate DESC",
siteID : siteId
);
// Find by slug
var entry = entryService.findBySlug( "my-entry-slug" );
// Find by category
var entries = entryService.findByCategory( "news" );
// Find by author
var entries = entryService.findByAuthor( authorId );
// Count entries
var count = entryService.countPublishedContent( siteID : siteId );
PageService Queries
property name="pageService" inject="pageService@contentbox";
// Find all pages
var pages = pageService.findAllWhere( { siteID : siteId, isPublished : true } );
// Find by slug
var page = pageService.findBySlug( "about" );
// Find children
var children = pageService.findChildren( parentId );
// Find hierarchical
var tree = pageService.getHierarchicalPages( siteId );
Best Practices
- Use services โ
entryService,pageService,contentStoreService - Use
findBySlug()โ for human-readable URL lookups - Always filter by
siteIDโ in multi-site installations - Use content helpers โ for reusable content methods
- Use interception points โ for content lifecycle hooks
- Validate custom fields โ ensure data integrity
- Use
getPlainTextContent()โ for excerpts and search - Use
getHTMLContent()โ for rendering - Handle soft deletes โ check
isDeletedflag - Cache expensive queries โ use CacheBox for performance
Engine Compatibility
This skill targets CFML engines (Lucee 5+, Adobe ColdFusion 2018+). For BoxLang-specific syntax and features, see the BoxLang variant of this skill.