9.7 KiB
PSR-4 WordPress Plugin Template
This is a modern PSR-4 autoloading pattern for WordPress plugins using Composer. Best for large, complex plugins that need professional architecture with namespaces and autoloading.
Features
✅ PSR-4 autoloading with Composer ✅ Namespace organization (MyPSR4Plugin*) ✅ Singleton pattern ✅ Modular class structure by domain ✅ Custom post type with meta boxes ✅ Custom taxonomy ✅ Admin settings using Settings API ✅ REST API endpoints (GET, POST) ✅ Asset management (admin + frontend) ✅ Proper activation/deactivation hooks ✅ Uninstall script for cleanup ✅ Internationalization ready ✅ WordPress Coding Standards ready (PHPCS) ✅ Security best practices
Installation
- Copy this folder to
wp-content/plugins/ - Rename folder and files to match your plugin name
- Find and replace the following:
MyPSR4Plugin→ YourPluginNamespaceMy PSR-4 Plugin→ Your plugin namemy-psr4-plugin→ your-plugin-slugmypp_→ yourprefix_MYPP_→ YOURPREFIX_yourname/my-psr4-plugin→ your-composer/package-namehttps://example.com→ Your websiteYour Name→ Your name
- Run
composer installin the plugin directory - Activate in WordPress admin
Structure
my-psr4-plugin/
├── my-psr4-plugin.php # Main plugin file (bootstrapper)
├── composer.json # Composer dependencies and autoloading
├── uninstall.php # Cleanup on uninstall
├── README.md # This file
├── src/ # Source code (PSR-4 autoloaded)
│ ├── Plugin.php # Main plugin class
│ ├── PostTypes/ # Custom post types
│ │ └── Book.php
│ ├── Taxonomies/ # Taxonomies
│ │ └── Genre.php
│ ├── Admin/ # Admin functionality
│ │ └── Settings.php
│ ├── Frontend/ # Frontend functionality
│ │ └── Assets.php
│ └── API/ # REST API endpoints
│ └── BookEndpoints.php
├── assets/ # CSS/JS files (create as needed)
│ ├── css/
│ │ ├── admin-style.css
│ │ └── style.css
│ └── js/
│ ├── admin-script.js
│ └── script.js
├── languages/ # Translation files (create as needed)
└── vendor/ # Composer dependencies (auto-generated)
Composer Setup
Install Dependencies
cd wp-content/plugins/my-psr4-plugin
composer install
Development Dependencies
The template includes WordPress Coding Standards (WPCS) for code quality:
# Check code standards
composer phpcs
# Fix code standards automatically
composer phpcbf
Update Dependencies
composer update
Namespaces
The plugin uses the following namespace structure:
MyPSR4Plugin\- Root namespaceMyPSR4Plugin\PostTypes\- Custom post typesMyPSR4Plugin\Taxonomies\- TaxonomiesMyPSR4Plugin\Admin\- Admin functionalityMyPSR4Plugin\Frontend\- Frontend functionalityMyPSR4Plugin\API\- REST API endpoints
Included Examples
Custom Post Type (src/PostTypes/Book.php)
- "Books" post type with Gutenberg support
- Meta boxes for ISBN, Author, Publication Year
- Nonce verification and sanitization
Taxonomy (src/Taxonomies/Genre.php)
- "Genres" hierarchical taxonomy
- Linked to Books post type
Admin Settings (src/Admin/Settings.php)
- Located in Settings → PSR-4 Plugin
- Uses WordPress Settings API
- Multiple field types with validation
REST API (src/API/BookEndpoints.php)
GET /wp-json/mypp/v1/books- List all booksGET /wp-json/mypp/v1/books/{id}- Get single bookPOST /wp-json/mypp/v1/books- Create book- Permission callbacks and validation
Assets (src/Frontend/Assets.php)
- Conditional loading (admin + frontend)
- Localized script data
Adding New Classes
1. Create Class File
Create src/YourNamespace/YourClass.php:
<?php
namespace MyPSR4Plugin\YourNamespace;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class YourClass {
private static $instance = null;
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
// Initialize
}
}
2. Initialize in Plugin.php
Add to src/Plugin.php in the init() method:
YourNamespace\YourClass::get_instance();
3. Composer Will Auto-Load
No need to manually require files! Composer's PSR-4 autoloader handles it.
Security Checklist
- ABSPATH check in every file
- Namespaces prevent naming conflicts
- Private constructors (singletons)
- Nonces for all forms
- Capability checks (current_user_can)
- Input sanitization (sanitize_text_field, absint)
- Output escaping (esc_html, esc_attr)
- REST API permission callbacks
- REST API argument validation
- Conditional asset loading
- Composer autoloader check
Advantages of PSR-4 Pattern
✅ Professional - Industry-standard autoloading ✅ No manual requires - Composer handles class loading ✅ Organized - Classes grouped by domain/functionality ✅ Scalable - Easy to add new features ✅ Testable - Each class is independently testable ✅ Standards - Compatible with modern PHP tooling ✅ Namespaces - Prevents naming conflicts ✅ Version control - Clean git diffs (no huge files)
When to Use PSR-4
Use PSR-4 when:
- Plugin has 20+ classes
- Multiple developers
- Need professional architecture
- Plan to add many features over time
- Want to use Composer packages
- Need unit testing
- Building a commercial plugin
Use OOP when:
- Plugin has 10-20 classes
- Single developer
- Don't need Composer dependencies
Use Simple when:
- Plugin has <10 classes
- Quick, focused functionality
Development Workflow
1. Create New Feature Class
# Example: Create a new AJAX handler
touch src/AJAX/BookActions.php
2. Write Class with Namespace
<?php
namespace MyPSR4Plugin\AJAX;
class BookActions {
// Your code
}
3. Initialize in Plugin.php
AJAX\BookActions::get_instance();
4. Test
No need to run composer dump-autoload - PSR-4 discovers classes automatically!
Code Quality
Check Code Standards
composer phpcs
Fix Code Standards
composer phpcbf
Add Custom Rules
Edit composer.json scripts:
"scripts": {
"phpcs": "phpcs --standard=WordPress --extensions=php src/",
"phpcbf": "phpcbf --standard=WordPress --extensions=php src/"
}
Distribution & Auto-Updates
Enabling GitHub Auto-Updates
You can provide automatic updates from GitHub without submitting to WordPress.org:
1. Install Plugin Update Checker via Composer:
composer require yahnis-elsts/plugin-update-checker
Or as git submodule:
git submodule add https://github.com/YahnisElsts/plugin-update-checker.git
2. Create Updater class:
Create src/Updater.php:
<?php
namespace MyPSR4Plugin;
use YahnisElsts\PluginUpdateChecker\v5\PucFactory;
class Updater {
private static $instance = null;
private $updateChecker;
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init_updater();
}
private function init_updater() {
$updater_path = plugin_dir_path( __DIR__ ) . 'vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php';
if ( ! file_exists( $updater_path ) ) {
return;
}
require $updater_path;
$this->updateChecker = PucFactory::buildUpdateChecker(
'https://github.com/yourusername/your-plugin/',
plugin_dir_path( __DIR__ ) . 'my-psr4-plugin.php',
'your-plugin-slug'
);
$this->updateChecker->setBranch( 'main' );
$this->updateChecker->getVcsApi()->enableReleaseAssets();
// Private repo authentication
if ( defined( 'MYPP_GITHUB_TOKEN' ) ) {
$this->updateChecker->setAuthentication( MYPP_GITHUB_TOKEN );
}
}
}
3. Initialize in Plugin.php:
Add to src/Plugin.php init() method:
Updater::get_instance();
4. For private repos, add token to wp-config.php:
define( 'MYPP_GITHUB_TOKEN', 'ghp_xxxxxxxxxxxxx' );
5. Create releases:
# Update version in plugin header
git add my-psr4-plugin.php
git commit -m "Bump version to 1.0.1"
git tag 1.0.1
git push origin main
git push origin 1.0.1
# Create GitHub Release with pre-built ZIP
6. Build release ZIP:
#!/bin/bash
# build-release.sh
VERSION="1.0.1"
PLUGIN_SLUG="my-psr4-plugin"
# Install dependencies (no dev packages)
composer install --no-dev --optimize-autoloader
# Create ZIP
zip -r "${PLUGIN_SLUG}-${VERSION}.zip" \
"${PLUGIN_SLUG}/" \
-x "*.git*" "*.github/*" "tests/*" "node_modules/*"
echo "Built: ${PLUGIN_SLUG}-${VERSION}.zip"
Resources
- Complete Guide: See
references/github-auto-updates.md - Implementation Examples: See
examples/github-updater.php - Plugin Update Checker: https://github.com/YahnisElsts/plugin-update-checker
Resources
License
GPL v2 or later