Nova
WordPress Integration
Component Models

Component Models

️⚠️

Dedicated page forthcoming. This'll get into specifics about structure, code expectations, etc. Probably also the schema validation. And nesting model data.

Introduction

Components' Model classes are, arguably, the most important piece of the Style Guide's integration with WordPress. It's here that the data required by a given component's template is populated from its many sources, based on explicitly-defined inputs.

Sample Model

The following is a significantly-simplified copy of the model for the <TemplateArticle /> component.

<?php
/**
 * Model for the `template-article` component.
 *
 * @package pmc-nova
 */
 
declare( strict_types = 1 );
 
namespace PMC\Nova\Style_Guide\Components\Template_Article;
 
use PMC\Nova\Components\Model as Base;
use PMC\Nova\Style_Guide\Components;
 
/**
 * Class Model.
 */
final class Model extends Base {
	/**
	 * Post ID to populate data from.
	 *
	 * @var int
	 */
	public int $post_id;
 
	/**
	 * Populate data structure.
	 */
	protected function _populate_data(): void {
		$this->_add_nested_model_data(
			'featuredMedia',
			Components\Featured_Media\Model::class,
			[
				'post_id' => $this->post_id,
			]
		);
	}
}

Code Style

All PHP written for Nova, including models, includes declare( strict_types = 1 );. This prevents PHP from performing type coercion, which can lead to unexpected behaviour. As a result, if a property is typed as an int, a string that passes the is_numeric() check will trigger a TypeError rather than PHP converting it to an integer.

All model classes (and most other Nova classes) are marked as final to prevent them from being extended. This avoids the nightmare of components being dependent on each other and ensures that components' behaviour is predictable and easily understood.

With the exception of abstract methods defined in the base class, all methods are marked as private to limit their use to that which is intended within the model.

Inputs (properties)

All external information that a model requires to populate its data is defined as strictly-typed properties on the model class.

If required, no default value is set, ensuring that PHP will throw an error if omitted. If optional, a default value of null is typically used (though in some cases, an empty string or empty array may be used instead).

Models do not accept extra properties (those not defined by the model itself). Passing an extra property to, or attempting to use a property not defined in, the model will trigger a LogicException.

These strictures ensure that data is predictable and clearly defined without the need for additional documentation.

Base model inputs

There are a few special properties set directly on the model abstract. These allow all components to easily share baseline functionality.

For example,

  • (Working with class names)[/core-tech/nova/style-guide/component-library/classes/].
  • (Working with inline styles)[/core-tech/nova/style-guide/component-library/inline-styles/].

Refer to the abstract Model class (opens in a new tab) for additional information.

Working with _populate_data()

The majority of a component's model will be in the _populate_data() method or in methods called therein. This abstract method is called in the base class and is one of the few ways that a developer will interact with the base class.

The base class provides a _data property (an instance of stdClass) that the _populate_data() method will add properties to. These properties match what is defined in the component's schema.json, in both name and permissible data type.