When it comes to WordPress plugins and development, plugins play a crucial role in extending the functionality of a client’s site. While normal plugins can be installed and activated, there is another, often underutilized type of plugin called a MU-plugin, or a must-use plugin.
MU-plugins are unique because they are loaded automatically by WordPress, so there is no need for an activation or deactivation process. This makes mu-plugins particularly useful for essential functionality that must be enabled for a particular site.
This tutorial will explore MU-Plugins, explaining what they are, why you might want to use them, and how to create your own. Whether you’re a seasoned WordPress developer or just getting started, understanding MU-Plugins can open up new possibilities for managing and customizing your WordPress site.
What are MU-plugins, and how do they differ from regular plugins?
MU-Plugins differ from regular plugins in several areas, notably their location and activation mechanisms.
The folder structure differs
Regular plugins live inside your plugins
folder inside wp-content
.
.
├── wp-admin
├── wp-includes
└── wp-content/
├── plugins
└── themes
Code language: AsciiDoc (asciidoc)
Unlike plugins, MU-Plugins reside in an mu-plugins
folder inside wp-content
. If this folder doesn’t exist, you can create it.
.
├── wp-admin
├── wp-includes
└── wp-content/
├── plugins
├── themes
└── mu-plugins
Code language: AsciiDoc (asciidoc)
MU-Plugins are just files for the most part, so they can be placed directly inside the mu-plugins
folder and are automatically executed.
.
├── wp-admin
├── wp-includes
└── wp-content/
├── plugins
├── themes
└── mu-plugins/
└── register-post-types.php
Code language: AsciiDoc (asciidoc)
They can not be deactivated
By nature, MU-Plugins cannot be deactivated. They are designed to be dropped into the mu-plugins
folder and immediately executed.
This poses some risk if someone introduces an MU-Plugin that causes an error, as there is no fallback mechanism.
Extra care should be taken if the installation is multisite. An error in a MU plugin can take down an entire network.
MU-Plugins can’t be edited via the admin
A benefit and drawback of MU-Plugins is they aren’t editable via the admin. The benefit is that once installed, you can be assured that it won’t be modified by another admin. The drawback is that you’ll have to either manually upload the mu-plugin, or add it via SSH.
MU-Plugins can’t be upgraded or automatically upgraded
Most MU-Plugins are just regular PHP files that often have no structure. As a result, upgrading the plugin within the admin or having it automatically upgraded is not possible. These files must be updated manually.
As a result, mu-plugins
should typically be reserved for critical functionality.
Creating an MU-Plugin
Unlike plugins, MU-Plugins don’t require a plugin header. You can place any PHP inside a file, and it’ll be automatically executed.
That being said, it’s still important to use plugin headers as these will display when the mu-plugins
are listed in the admin.
The supported plugin headers are as follows:
<?php
/*
* Plugin Name: Add Adobe Fonts/Post Types to GeneratePress
* Plugin URI: https://okcmediator.com
* Description: Adds Adobe Fonts and compatible post types to GeneratePress.
* Version: 1.0.0
* Author: Ronald Huereca
* Author URI: https://mediaron.com
*/
Code language: PHP (php)
Here’s how it would look on the plugins screen.
From there, you can insert any PHP after the headers.
Here’s a sample MU-Plugin that adds font support for a WordPress plugin.
<?php
/*
* Plugin Name: Add Adobe Fonts/Post Types to GeneratePress
* Plugin URI: https://okcmediator.com
* Description: Adds Adobe Fonts and compatible post types to GeneratePress.
* Version: 1.0.0
* Author: Ronald Huereca
* Author URI: https://mediaron.com
*/
/**
* Compatibility with: https://wordpress.org/plugins/custom-typekit-fonts/
* Would be nice to be able to categorize fonts: https://docs.generatepress.com/article/generate_typography_default_fonts/
*/
add_filter( 'generate_typography_default_fonts', 'mr_custom_add_typekit_fonts' );
function mr_custom_add_typekit_fonts( $fonts ) {
// Add Typekit Fonts.
if ( defined( 'CUSTOM_TYPEKIT_FONTS_FILE' ) ) {
$adobe_fonts = get_option( 'custom-typekit-fonts', array() );
if ( isset( $adobe_fonts['custom-typekit-font-details'] ) ) {
foreach ( $adobe_fonts['custom-typekit-font-details'] as $font_name => $font_details ) {
$fonts[] = $font_name;
}
}
}
return $fonts;
}
Code language: PHP (php)
As you can see, you can execute actions and filters like you do with plugins, albeit in just one file.
Adding structure to your mu-plugins
As mentioned earlier, mu-plugins are just a single file.
However, nothing stops you from referencing a file in a folder for more complicated mu-plugins.
In this next example, I’m placing a plugin folder inside mu-plugins
and referencing it from the main PHP file.
.
└── wp-content/
├── plugins
├── themes
└── mu-plugins/
├── my-plugin-file.php
└── my-plugin/
├── my-plugin.php
├── js
├── css
└── includes
In the file my-plugin-file.php
, you’d use this code to include the main plugin file:
<?php
/*
* Plugin Name: Sample MU-Plugin
* Plugin URI: https://mediaron.com
* Description: Sample mu-plugin for including a plugin in a folder.
* Version: 1.0.0
* Author: Ronald Huereca
* Author URI: https://mediaron.com
*/
require_once plugin_dir_path( __FILE__ ) . 'my-plugin/my-plugin.php';
Code language: PHP (php)
Developing with mu-plugins
There are a few considerations when developing with mu-plugins. Let’s go over them below.
MU-Plugins are loaded before regular plugins
One thing to keep in mind when developing an mu-plugin
is that they are loaded before plugins.
This allows you to control regular plugins or any plugins executing after yours (plugins are loaded alphabetically).
One handy hook for your mu-plugin
is muplugins_loaded
. The muplugins_loaded hook allows you to execute code immediately after all mu-plugins
have loaded, but before regular plugins have loaded.
<?php
add_action( 'muplugins_loaded', 'dlx_sample_muplugins_loaded' );
function dlx_sample_muplugins_loaded() {
// Execute code here.
}
Code language: PHP (php)
Referencing styles and scripts from an mu-plugin
As mentioned earlier, mu-plugins
typically don’t come in directories. However, for scripts and styles, this is almost a requirement.
You’d use function plugins_url to reference any scripts and styles in your mu-plugin
.
Here’s an example:
<?php
/*
* Plugin Name: Sample MU-Plugin
* Plugin URI: https://mediaron.com
* Description: Sample mu-plugin for including a plugin in a folder.
* Version: 1.0.0
* Author: Ronald Huereca
* Author URI: https://mediaron.com
*/
add_action( 'wp_enqueue_scripts', 'dlx_sample_enqueue_scripts' );
function dlx_sample_enqueue_scripts() {
wp_enqueue_script(
'dlx-sample-script',
plugins_url( '/my-plugin/js/sample.js', __FILE__ ),
array( 'jquery' ),
'1.0.0',
true
);
}
Code language: PHP (php)
Conclusion
MU-Plugins are designed to be executed automatically, cannot be edited, and cannot be automatically upgraded. They are typically used to host critical functionality and great care should be taken to ensure that an mu-plugin
doesn’t cause an error.
If you have any questions, please leave a comment below or @ me on Twitter.
Like this tutorial? There's more like it. Subscribe today!
Ronald Huereca founded DLX Plugins in 2022 with the goal of providing deluxe plugins available for download. Find out more about DLX Plugins, check out some tutorials, and check out our plugins.