With custom add-ons you can add new fieldtypes, features, template tags, and much more to ExpressionEngine. Here we are going to look at different parts of an add-on, and how to define just what our add-on is going to do.
In this section, we’re explaining the parts of an add-on. No need to memorize everything though, the CLI will generate all the pieces we need based on what functions we want our add-on to have.
While ExpressionEngine offers a lot of functionality right out of the box, sometimes you want more power or to do things that ExpressionEngine doesn’t natively do.
Here are some ideas of what you can accomplish with a custom add-on:
- Add custom template tags like
- Run functions or return data when someone reaches a specific URL using URL endpoints (called Actions).
- Add custom fieldtypes for content editors when creating channel entries.
- Add custom CLI commands like
$ eecli.php amazing_add_on:do_something_amazing
- Add custom Publish Form tabs to help organize entry fields for content editors.
- Hook into ExpressionEngine and run custom functions (called Extensions) when ExpressionEngine does certain actions, like emailing your team whenever a post is created or manipulating text when a template is rendered.
- Display information from your add-on to content editors on the front-end by adding a Prolet to the ExpressionEngine Dock.
- Display information in the Control Panel Dashboard using a custom Dashboard Widget.
These are just a few ideas of what you can do with custom add-ons. The possibilities are almost endless.
Getting started making an add-on is incredibly easy with the CLI. To begin making an add-on, simply use the
make:addon command from the CLI.
If you are working with an existing add-on, we recommend you start with Modernizing add-ons
$ php system/ee/eecli.php make:addon Let's build your add-on! What is the name of your add-on? Amazing Add-On Add-on description? [Amazing Add-on description] This add-on does amazing things! Add-on version? [1.0.0]1.0.0 Add-on author? ExpressionEngine Developer Add-on author URL? www.expressionengine.com Let's build! Your add-on has been created successfully!
This will create an add-on named Amazing Add-On in your
system/user/addons folder with a skeleton file structure like below:
amazing_add_on/ ┣ language/ ┃ ┣ english/ ┃ ┃ ┣ amazing_add_on_lang.php ┣ addon.setup.php ┣ mod.amazing_add_on.php ┗ upd.amazing_add_on.php
At this point, your add-on can’t really do anything other than be installed. However, from here, you can add more functionality to your add-on via the CLI depending on your needs.
Here’s a list of functionality that can be added to your add-on and the corresponding CLI command if applicable:
- Extension hooks (
- Control Panel Pages (
- Actions (
- Fieldtypes (
- CLI Commands (
- Template Tags (
- Language Files
- Publish Form Tabs
- Prolets (
- Dashboard Widgets (
Continue reading below to understand all the files and folders found in the structure of an add-on.
Below is the complete structure of an add-on that we’ll call “Amazing Add-on”. There’s a lot in this structure because this add-on can do many things (it’s amazing 😀)! Don’t worry though; your add-on can be as simple or complex as you want to make it. This example just shows all the possibilities. Continue reading as we break down the parts of this add-on.
amazing_add_on ┣ Commands ┃ ┗ CommandAnAmazingCommand.php ┣ database ┃ ┣ migrations ┃ ┃ ┗ 2022_11_14_170449_amazing_migration.php ┣ Extensions ┃ ┣ TemplatePostParse.php ┃ ┗ TypographyParseTypeEnd.php ┣ ControlPanel ┃ ┣ Routes ┃ ┃ ┣ Index.php ┃ ┃ ┗ Page2.php ┃ ┣ Sidebar.php ┣ Actions ┃ ┗ ExampleAction.php ┣ Tags ┃ ┗ ExampleTag.php ┣ Model ┃ ┗ AmazingModel.php ┣ language ┃ ┣ english ┃ ┃ ┣ amazing_add_on_lang.php ┃ ┃ ┗ index.html ┃ ┗ index.html ┣ widgets ┃ ┗ AnAmazingWidget.php ┣ views ┃ ┣ Index.php ┃ ┗ Page2.php ┣ addon.setup.php ┣ ext.amazing_add_on.php ┣ ft.amazing_add_on.php ┣ icon.svg ┣ mcp.amazing_add_on.php ┣ tab.amazing_add_on.php ┣ mod.amazing_add_on.php ┣ pro.amazing_add_on.php ┗ upd.amazing_add_on.php
Note: Pay attention to how these filenames are structured. For filenames, hyphens and special characters are removed, and spaces are replaced with underscores.
Starting with version 3.0 each add-on in ExpressionEngine must have an
addon.setup.php file in its package directory. This file provides descriptive data about a specific add-on, such as author, name, and version.
Reference The Add-on Setup File for more information on the contents of this file.
Add_on_name_upd extends Installer
The Update file for an add-on includes a class with a name that is a combination of the add-on’s name with a
_upd suffix. Here you define functionality that should be executed on installation, update, and uninstallation of your add-on.
Reference The Add-on Update File for more information on this file.
Add_on_name_upd extends Extension
The extension file is used to route ExpressionEngine to our
Reference Extending The Core for more information on how to use core hooks to extend what ExpressionEngine can do.
Add_on_name_ft extends EE_Fieldtype
The fieldtype file is used to create new fieldtypes in ExpressionEngine when your add-on is installed.
Reference Adding Fieldtypes for more information on adding fieldtypes with your add-on.
Add_on_name_upd extends Mcp
The Mcp file is used to route ExpressionEngine to our
ControlPanel Folder, which contains logic for your Control Panel pages (settings or other pages you might want to add to the Control Panel for your users to interact with).
Reference Adding Control Panel Pages for more information on adding Control Panel pages with your add-on.
Add_on_name_upd extends Module
The module file is used to route ExpressionEngine to our
Modules Folder, which contains any actions or template tags you are adding with your add-on.
Reference Adding Template Tags for more information on adding template tags with your add-on or Adding Actions for more information on creating URL endpoints (actions) with your add-on.
The tab file is used to create tabs that are visible in Publish Layouts. Respectively, these tabs would also be visible on the Entry Publish/Edit page if selected in the publish layout.
Reference Adding Publish Form Tabs for more information on adding Publish Form Tabs with your add-on.
Add_on_name_upd extends AbstractProlet implements ProletInterface
The Prolet file is used to create new Prolets with our add-on.
Reference Adding Prolets for more information on adding prolets to your add-on.
The add-on icon folder is used both in the Add-on Manager and in the Dock on the front-end to distinguish your add-on from others.
When we tell the CLI that we want to create an extension, classes are automatically created in the
Extensions folder along with the above mentioned
ext.[addon_name].php file. Interacting with hooks allows us to extend ExpressionEngine’s functionality, thus we refer to these as “extensions”.
Reference the Extensions section of the docs for more information on using extensions in your add-on.
/Actions folder stores all the business logic for any actions that we are adding to ExpressionEngine with our add-on. Each action will have a separate file and corresponding class created based on information provided in the
$actions array in the
Reference Adding Actions for more information on creating URL endpoints (actions) with your add-on.
ControlPanel folder contains all the Control Panel routes and we create for our add-on as well as our sidebar.
Reference Adding Control Panel Pages for more information on adding Control Panel routes and pages with your add-on.
/Tags folder stores all the business logic for any template tags we create with our add-on.
Reference Adding Template Tags for more information on adding template tags with your add-on.
views folder contains all of our Control Panel views which will be used to render our add-on’s control panel pages.
language folder contains all of our language files that will be used to display text on a page in whatever language is selected in the user’s account settings.
Reference Using Language Files for more information on using language files with your add-on.
/database/migrations folder holds all migrations that will be ran on installation or updating of our add-on. Using the CLI, migrations can also be ran independently.
Model folder holds all models that we are creating with our add-on.
Reference Building Your Own Models for more information on creating your own models with your add-on.
widgets folder holds all dashboard widgets we create with our add-on.
Reference Developing Dashboard Widgets for more information on creating widgets with your add-on.
When creating an add-on via the CLI you will be asked for author and the author’s URL. If you’d like to skip these questions when creating an add-on, you can set default values in your config file like so:
... $config['cli_default_addon_author'] = 'ExpressionEngine Developer'; $config['cli_default_addon_author_url'] = 'https://expressionengine.com'; ...
In the past, add-ons were often categorized based on their functionality. We identified our add-on to ExpressionEngine as a fieldtype, extension, module, or plug-in. Thus there was never a straightforward process on structuring one add-on that contained all these categories in one.
With the release of 6.4.x and 7.2.x this paradigm has been updated to reflect the idea that we are just creating add-ons, and those add-ons can have multiple types of functionality. The CLI has also been updated to make creating add-ons and adding functionality incredibly easy. We have also updated the docs to reflect the ideal workflow of creating an add-on.
While the latest changes shift our view of add-ons and how developers will create add-ons, you may still come across add-ons using the old methodology. We have left much of the old methods and structure in place in the core so that older add-ons will continue to work. However, we are choosing to not actively update the documentation for the old methods because we feel it’s no longer in the best interest of the community to develop add-ons in this way. If you need to access how the docs once were regarding add-ons, you can reference the legacy docs in GitHub (note that v7 and v6 were the same in these regards).