Using OOPS WP
What is OOPS-WP?
OOPS-WP is a lightly-opinionated collection of abstract classes, traits, and interfaces designed to promote object-oriented design thinking in WordPress development. Its primary goal is to give engineers the tools they need to quickly and consistently scaffold common WordPress data structures, such as custom post types, taxonomies, settings pages, REST API routes, Gutenberg blocks, widgets, shortcodes, and more, by using a composition and SOLID-based approach to plugin and theme architecture.
What is SOLID, and how does OOPS-WP follow it?
SOLID comprises the first 5 principles of object-oriented design:
- Single responsibility principle
- Open-closed principle
- Liskov substitution principle
- Interface segregation principle
- Dependency Inversion principle
You can read a really great article about SOLID at scotch.io. OOPS-WP promotes object-oriented programming and SOLID principles by defining a structure for how common structural elements should be initialized in WordPress plugins and themes. Specifically, OOPS-WP:
- Promotes single-responsibility by making objects focus on a particular task: registering a post type, setting up the objects needed for a feature, registering an API route, etc.
- Provides a set of objects which can be easily extended but not modified.
- Allows changing of objects so long as they abide by the same contracts, meaning we can replace code more easily down the line.
- Separates interfaces by defining contracts for particular structures (less so in 0.1.0, but moreso in future releases)
- Leads to dependency inversion by promoting composition over inheritance.
OOPS-WP Structures and Utilities
Structures introduced in 0.1.0
Structures are abstract classes that can be extended during plugin and theme development, the result of which will become some kind of "thing" in WordPress - a post type, a shortcode, a widget, etc.
A Service in OOPS-WP represents a functional component in WordPress.
For instance, as a developer who is building a custom plugin for a client, you might be tasked with extending WordPress to provide some additional post types and taxonomies. You could create a ContentRegistrationService object that contains references to each individual post type and taxonomy, each of which would be represented by their own class file. The job of the service is to create each of those objects and to fire its hooks at runtime.
A ServiceRegistrar is an object that registers a collection of Services.
Continuing with the ContentRegistrationService example above, let's say that your client's plugin also required some custom REST API routes, some WP-CLI commands, and a few custom settings pages.
Instead of putting all of the logic for those different pieces of functionality into a single class or functions file, you could split the responsibility of each feature set into its own Service class: an ApiService, a CliService, and a SettingsService. The role of the ServiceRegistrar is to contain references to those individual services, creating their objects and triggering their WordPress hooks at runtime.
The PostType class is an object that can be extended to quickly register a new custom post type. It provides a small set of arguments needed to hook the post type with WordPress, and requires that you define a slug and an array of labels that WordPress will need to load it.
The EditorBlock class can be used when registering a new Gutenberg block with WordPress. It defines a set of abstract methods that your child class will define in order to give your blocks a type and paths to its assets.
Utilities introduced in 0.1.0
Utilities are interfaces and traits that your own classes can implement and use, ensuring that your objects define the methods that are needed at runtime. Generally, these interfaces are small, and importantly, they promote the L in SOLID - letting you switch out one kind of object for another in the future, so long as that new object still abides by the same interface.
The Hookable interface requires a single method,
should be implemented by objects that need to hook into WordPress.
register_hooks method helps keep all of those hooks in one place
within a class file.
The Registerable interface can be used by classes that require some kind
of "registration" with WordPress. Generally, these are objects that
subsequently call some type of WordPress registration function, such as
The Runnable interface requires a single method,
run, which can be
implemented by objects that need to trigger some kind of process after
instantiation. This might be something like a plugin or
which first gets initialized, then subsequently needs to be run.
run method helps support unit testing by classes that implement
it, because boot-up logic that requires interaction with the WordPress
APIs can be stored in here, allowing us to create new objects without
tons of additional setup when writing tests.
The FilePathDependent trait can be used by objects that require some
kind of reference to a file path. One such example is the
class, which leverage this trait to indicate where the class is relative
The AssetsLocator interface can be implemented by objects that require some kind of URL reference to a file path. It differs from the FilePathDependent trait because the location of assets required by an object may not be within the file server and thus, is required by an object to define its method body.