Architecture concepts
Project structure
Eightshift Development Kit follows a strict project structure to support autoloading, dependency injection and wp boilerplate
commands, as well as conventions to increase codebase understanding between developers. As an added benefit, following this structure and conventions makes your codebase more consistent and organized.
While Eightshift Development Kit provides required theme files and common theme files such as style.css
and functions.php
, they're used differently to what you might expect if you've worked with WordPress themes previously. For instance, style.css
is used only to register theme metadata, and doesn't contain any actual styles, as they're built using Webpack and use cache busting. functions.php
simply bootstraps the execution lifecycle. We also provide very basic template partials, such as single.php
, which you can accommodate to your needs. An idea to consider is replacing some of them with pages that are editable in Gutenberg.
While you'll find some additional configuration files such as webpack.config.js
in the project root, the majority of your projects codebase should live in the src
directory, which is autoloaded via Composer following PSR-4 conventions. This implies that every directory under src
is a namespace under your base namespace (which is your project name), and PHP files inside of those directories are classes in that namespace, with exceptions for filenames that aren't in StudlyCase
.
An Eightshift Development Kit convention is to structure namespaces around features and functionality, so for instance, all custom post types would be part of the ProjectName\CustomPostType
namespace.
Object-oriented paradigms
Eightshift Libs is entirely object-oriented, providing abstract classes for internal library functionality, interfaces you can use to implement certain classes to make use of Eightshift Development Kit features, as well as concrete class implementations for use in projects.
Our use of OOP allows you to extend, modify or even replace Eightshift Development Kit functionality safely, without breaking compatibility or harming your project.
One of the most important interfaces in Eightshift Libs is the ServiceInterface
. Classes that implement it are called service classes. This isn't a common pattern in PHP OOP. In Eightshift Development Kit, a service class represents a part of the project's functionality and has a register
method that sets up the action and filter hooks for the service. If you need to add an action or a filter, you should do that in a service class. All your service classes are automatically loaded and can have dependencies injected using dependency injection.
To ensure there are no naming collisions caused by Composer dependencies, we use the Imposter Composer plugin to contain them in the {ProjectName}Vendor
namespace. This comes with a few caveats which you should be aware of, and about which you can read more in the namespaces chapter.
Read more about namespaces and Imposter, extending classes and service classes, and dependency injection and autowiring.
Blocks and Components
While Blocks and Components will be covered in much more detail in the Blocks chapter, it's worth getting acquainted with the concepts from the start.
In Gutenberg, Blocks are an abstract unit for structuring content. The same applies in Eightshift, with an additional concept of Components, which are abstract units for structuring blocks and layouts.
Components are mostly similar to Blocks, with a few key differences:
- Components can not be inserted by users in Gutenberg, and are not registered as block types
- Components can be rendered in any context using the
Components::render
method, with arbitrary attribute values passed to them - Blocks are usually only rendered using the render callback provided when registering the block
- Note that in the Eightshift Development Kit, the render callback is provided for you by Eightshift Libs. It automatically adds the wrapper if necessary and sets up your block view.
- Components don't implement the
{blockName}-block.js
file
Blocks and Components have the same structure, which makes extracting components from existing blocks trivially easy.
Components can be composed into a block. In other words, blocks can consist out of zero or more components. Component composition is handled in the block manifest, allows you to avoid using InnerBlocks to include functionality shared with other blocks, and serializes component attributes to the block using prefixed attributes for each component instance depending on your manifest definitions.
To learn more about the differences between blocks and components, read Igor's blog post on Components and blocks. To learn how to use blocks and components to build your projects, read the Blocks chapter.
The Manifest
manifest.json
files contain metadata, configurations and variables.
Every Eightshift project has one global manifest.json
file stored in src/Blocks/manifest.json
, which contains global settings, properties, and variables.
Furthermore, every Eightshift block, component, and variation has its own manifest file which is used to provide data required for block registration, such as a list of attributes, the block name, and the template for the inserter example. These local manifest files allow you to define arrays of options for attribute values that your blocks or components can consume. Manifest files also allow you to define relationships between attribute values and CSS variable values, which allows you a great deal of power when styling your blocks and components, as well as saves time as you don't have to provide conditional CSS classes.
To learn more about the global manifest, block manifest, component manifest and using the manifest to provide CSS variables for use in block styling, read the respective articles in the Blocks chapter. For information about manifest structure, refer to the manifest schemas available in Eightshift Frontend Libs and linked to in the manifest files.
The directory structure in detail
Your project might contain a different set of namespaces and classes in the src
folder, depending on what you've included using wp boilerplate commands.
By default, your project will include the Blocks
, Config
, Enqueue
, Main
, Manifest
and Menu
namespaces. You can include classes from Eightshift Libs to provide additional functionality manually or using wp boilerplate.
This chapter also doesn't cover all the namespaces and classes in Eightshift Libs, or their use. Check out the source code documentation for all available namespaces and classes.
- src
- Blocks
- assets
- components
- custom
- variations
- wrapper
- Columns
- Config
- CustomMeta
- CustomPostType
- CustomTaxonomy
- Enqueue
- Admin
- Blocks
- Theme
- Exception
- Helpers
- I18n
- Main
- Manifest
- Media
- Menu
- ModifyAdminAppearance
- Plugin
- Rest
- ThemeOptions
- View
- .storybook
- .gitignore
- .eslintignore
- .eslintrc
- .stylelintrc
- babel.config.js
- composer.json
- composer.lock
- package-lock.json
- package.json
- phpcs.xml.dist
- postcss.config.js
- README.md
- webpack.config.js
Blocks
The Blocks namespace contains the Blocks class used for block registration. This directory also contains shared assets, components, blocks, variations, and the wrapper.
Read about blocks in detail in the Blocks chapter.
Columns
This namespace contains all the custom admin listing columns hooks in your project. These include listing column hooks for post types, taxonomy, and user lists, such as manage_{$post_type}_posts_columns
.