While theme development controls the visual presentation, Plugin Development is where real full-stack software engineering happens in WordPress. Plugins allow you to encapsulate business logic — such as an automated course enrollment system, an algorithmic calculator, or a third-party CRM integration — into a portable, standalone package that can be distributed to clients or published on the official WordPress.org repository. In this class, we build a production plugin called Veewom Quick Notice.
Navigate to /wp-content/plugins/ and create a directory named after your plugin slug:
/wp-content/plugins/veewom-quick-notice/
Inside this folder, create your primary PHP file with the same name: veewom-quick-notice.php.
WordPress identifies a plugin strictly by parsing the comment header at the top of the main PHP file:
<?php
/**
* Plugin Name: Veewom Quick Notice
* Plugin URI: https://veewom.com/wordpress/
* Description: Displays customizable alert notices and banner shortcodes across your site.
* Version: 1.0.0
* Requires at least: 6.0
* Requires PHP: 8.0
* Author: Veewom Engineering Team
* Author URI: https://veewom.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: veewom-quick-notice
*/
// Block direct execution outside WordPress
if ( ! defined('ABSPATH') ) {
exit;
}
WordPress provides specialized lifecycle hooks to execute setup routines (like creating custom database tables or seeding options) when a user clicks "Activate", and cleanup routines on "Deactivate":
// 1. Activation Hook
register_activation_hook(__FILE__, 'veewom_notice_activate');
function veewom_notice_activate() {
// Add default options if not already present
if ( ! get_option('veewom_notice_text') ) {
add_option('veewom_notice_text', 'Welcome to Veewom Tutorials!');
}
}
// 2. Deactivation Hook
register_deactivation_hook(__FILE__, 'veewom_notice_deactivate');
function veewom_notice_deactivate() {
// Clean up temporary caches or transients
delete_transient('veewom_notice_cache');
}
To give administrators a dedicated control panel in the left sidebar, use add_menu_page() hooked into admin_menu:
add_action('admin_menu', 'veewom_notice_add_admin_menu');
function veewom_notice_add_admin_menu() {
add_menu_page(
__('Quick Notice Settings', 'veewom-quick-notice'), // Page Title
__('Quick Notice', 'veewom-quick-notice'), // Menu Label
'manage_options', // Required Capability
'veewom-quick-notice', // Menu Slug
'veewom_notice_render_settings_page', // Callback Function
'dashicons-megaphone', // Dashicon
25 // Menu Position
);
}
function veewom_notice_render_settings_page() {
// Save settings if form submitted
if ( isset($_POST['veewom_save_notice']) && check_admin_referer('veewom_notice_nonce') ) {
$notice = sanitize_text_field($_POST['notice_message']);
update_option('veewom_notice_text', $notice);
echo '<div class="updated"><p>Settings successfully saved!</p></div>';
}
$current_text = get_option('veewom_notice_text', '');
?>
<div class="wrap">
<h1>Veewom Quick Notice Settings</h1>
<form method="post" action="">
<?php wp_nonce_field('veewom_notice_nonce'); ?>
<table class="form-table">
<tr>
<th><label for="notice_message">Banner Message:</label></th>
<td>
<input type="text" name="notice_message" id="notice_message" value="<?php echo esc_attr($current_text); ?>" class="regular-text" />
</td>
</tr>
</table>
<input type="submit" name="veewom_save_notice" class="button button-primary" value="Save Changes" />
</form>
</div>
<?php
}
Shortcodes allow content creators to embed your plugin's dynamic output anywhere inside a Gutenberg block or page by typing [quick_notice type="warning"]:
// Register [quick_notice] Shortcode
add_shortcode('quick_notice', 'veewom_render_notice_shortcode');
function veewom_render_notice_shortcode($atts, $content = null) {
// Parse user attributes with default fallbacks
$args = shortcode_atts(array(
'type' => 'info', // default type
), $atts, 'quick_notice');
$border_color = ($args['type'] === 'warning') ? '#ef4444' : '#ff6600';
$message = $content ? $content : get_option('veewom_notice_text');
return '<div style="border-left: 5px solid ' . esc_attr($border_color) . '; background: #fffaf6; padding: 14px 18px; margin: 15px 0;">'
. esc_html($message) .
'</div>';
}
In professional code audits, any plugin failing the Sanitize Early, Escape Late rule is rejected. Always clean incoming input using sanitize_text_field() or intval() before saving to the database, and always escape output using esc_html(), esc_attr(), or esc_url() before echoing to HTML.
Expand your CMS mastery by studying these tightly integrated WordPress development topics:
The foundational building blocks for every WordPress plugin.
Implement nonces, capability checks, and data sanitization in plugins.
Register custom post types inside plugins rather than themes.
Register custom REST API routes using register_rest_route().