wordpress-plugin-fundamentals
Modern WordPress plugin development with PHP 8.3+, OOP architecture, hooks system, database interactions, and Settings API
What this skill does
# WordPress Plugin Fundamentals
## Overview
WordPress plugin development using modern PHP 8.3+ practices, OOP architecture, Composer autoloading, and WordPress 6.7+ APIs. Build secure, maintainable plugins with proper hooks integration, database management, and settings pages.
**Current Standards**:
- **WordPress**: 6.7+ (Full Site Editing stable)
- **PHP**: 8.3 recommended (7.4 minimum)
- **Architecture**: OOP with PSR-4 autoloading
- **Security**: Three-layer model (sanitize, validate, escape)
- **Testing**: PHPUnit + WPCS compliance
**Installation**:
```bash
composer require --dev wp-coding-standards/wpcs:"^3.0"
composer require --dev phpunit/phpunit:"^9.6"
```
## Plugin Architecture
### Directory Structure
Modern plugin organization with Composer autoloading:
```
my-plugin/
├── my-plugin.php # Main plugin file (metadata header)
├── composer.json # Dependency management (REQUIRED)
├── includes/ # Core business logic (PSR-4 autoloaded)
│ ├── Core.php # Plugin bootstrap/loader class
│ ├── Admin/ # Admin-specific functionality
│ │ ├── Settings.php
│ │ └── MetaBoxes.php
│ ├── Frontend/ # Public-facing functionality
│ │ └── Shortcodes.php
│ └── API/ # REST API endpoints
│ └── CustomEndpoint.php
├── assets/ # CSS, JS, images
│ ├── css/
│ ├── js/
│ └── images/
├── languages/ # Translation files
├── tests/ # PHPUnit tests
│ ├── unit/
│ ├── integration/
│ └── bootstrap.php
├── .phpcs.xml.dist # PHP_CodeSniffer config (WPCS)
└── README.md
```
### Main Plugin File
**my-plugin.php**:
```php
<?php
/**
* Plugin Name: Modern WordPress Plugin
* Plugin URI: https://example.com/my-plugin
* Description: Modern plugin following WordPress 6.x best practices
* Version: 1.0.0
* Requires at least: 6.4
* Requires PHP: 8.1
* Author: Your Name
* Author URI: https://example.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-plugin
* Domain Path: /languages
*/
// Security: Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
// Define plugin constants
define( 'MY_PLUGIN_VERSION', '1.0.0' );
define( 'MY_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
define( 'MY_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'MY_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
// Composer autoloader
if ( file_exists( MY_PLUGIN_PATH . 'vendor/autoload.php' ) ) {
require_once MY_PLUGIN_PATH . 'vendor/autoload.php';
}
/**
* Initialize plugin on plugins_loaded hook
* Runs after all plugins are loaded
*/
add_action( 'plugins_loaded', 'my_plugin_init' );
function my_plugin_init() {
// Initialize core plugin class
if ( class_exists( 'MyPlugin\\Core' ) ) {
$plugin = MyPlugin\Core::get_instance();
$plugin->run();
}
}
/**
* Activation hook
* Runs once when plugin is activated
*/
register_activation_hook( __FILE__, 'my_plugin_activate' );
function my_plugin_activate() {
// Run activation tasks
if ( class_exists( 'MyPlugin\\Activation' ) ) {
MyPlugin\Activation::activate();
}
// Flush rewrite rules after plugin activation
flush_rewrite_rules();
}
/**
* Deactivation hook
* Runs when plugin is deactivated
*/
register_deactivation_hook( __FILE__, 'my_plugin_deactivate' );
function my_plugin_deactivate() {
// Cleanup tasks
if ( class_exists( 'MyPlugin\\Deactivation' ) ) {
MyPlugin\Deactivation::deactivate();
}
// Flush rewrite rules
flush_rewrite_rules();
}
```
### Core Plugin Class (Singleton Pattern)
**includes/Core.php**:
```php
<?php
namespace MyPlugin;
/**
* Main plugin class using Singleton pattern
*
* Design Decision: Singleton ensures single plugin instance
* Trade-off: Testability vs. simplicity (use DI for complex plugins)
* Extension Point: Hook system allows third-party extensions
*/
class Core {
/**
* Single instance of the plugin
* @var Core|null
*/
private static $instance = null;
/**
* Get plugin instance (Singleton)
*
* @return Core
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Private constructor prevents direct instantiation
*/
private function __construct() {
$this->load_dependencies();
$this->define_hooks();
$this->load_textdomain();
}
/**
* Load required classes and dependencies
*/
private function load_dependencies() {
// Dependencies auto-loaded via Composer PSR-4
// Additional manual includes if needed
}
/**
* Register WordPress hooks
*/
private function define_hooks() {
// Core hooks
add_action( 'init', [ $this, 'on_init' ] );
add_action( 'admin_menu', [ $this, 'register_admin_menu' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_frontend_assets' ] );
add_action( 'rest_api_init', [ $this, 'register_rest_routes' ] );
}
/**
* Load plugin text domain for translations
*/
private function load_textdomain() {
load_plugin_textdomain(
'my-plugin',
false,
dirname( MY_PLUGIN_BASENAME ) . '/languages'
);
}
/**
* Start plugin execution
*/
public function run() {
// Plugin is now running
do_action( 'my_plugin_loaded' );
}
/**
* Init hook callback
* Register post types, taxonomies, etc.
*/
public function on_init() {
// Register custom post types
$this->register_post_types();
// Register taxonomies
$this->register_taxonomies();
}
/**
* Register custom post types
*/
private function register_post_types() {
register_post_type( 'book', [
'labels' => [
'name' => __( 'Books', 'my-plugin' ),
'singular_name' => __( 'Book', 'my-plugin' ),
],
'public' => true,
'has_archive' => true,
'supports' => [ 'title', 'editor', 'thumbnail' ],
'show_in_rest' => true, // Enable block editor
'menu_icon' => 'dashicons-book',
]);
}
/**
* Register custom taxonomies
*/
private function register_taxonomies() {
register_taxonomy( 'genre', 'book', [
'labels' => [
'name' => __( 'Genres', 'my-plugin' ),
'singular_name' => __( 'Genre', 'my-plugin' ),
],
'hierarchical' => true,
'show_in_rest' => true,
]);
}
/**
* Register admin menu pages
*/
public function register_admin_menu() {
add_menu_page(
__( 'My Plugin Settings', 'my-plugin' ),
__( 'My Plugin', 'my-plugin' ),
'manage_options',
'my-plugin-settings',
[ $this, 'render_settings_page' ],
'dashicons-admin-generic',
80
);
}
/**
* Render settings page
*/
public function render_settings_page() {
require_once MY_PLUGIN_PATH . 'includes/Admin/views/settings.php';
}
/**
* Enqueue admin assets
*/
public function enqueue_admin_assets( $hook ) {
// Only load on our plugin pages
if ( 'toplevel_page_my-plugin-settings' !== $hook ) {
return;
}
wp_enqueue_style(
'my-plugin-admin',
MY_PLUGIN_URL . 'assets/css/admin.css',
[],
MY_PLUGIN_VERSION
);
wp_enqueue_script(
'my-plugin-admin',
MY_PLURelated in development
cc-plugin-expert
IncludedComprehensive Claude Code plugin development expert providing guidance for creation, maintenance, installation, configuration, and troubleshooting of plugins and skills
flexlayout-react
IncludedFlexLayout for React - Advanced docking layout manager with drag-and-drop, tabs, splitters, and complex window management
react-state-machines
IncludedBuilding reusable React state machine skills with XState v5 and the actor model
espocrm-development
IncludedComprehensive guide for developing on EspoCRM - metadata-driven CRM with service layer architecture
rust-desktop-applications
IncludedBuild cross-platform desktop applications with Rust using Tauri framework and native GUI alternatives
sparc-methodology
IncludedSPARC (Specification, Pseudocode, Architecture, Refinement, Completion) comprehensive development methodology with multi-agent orchestration