Getting Started
This guide will walk you through creating your first AvelPress plugin using the AvelPress CLI.
Installing the AvelPress CLI
To install the AvelPress CLI, follow the official installation instructions in the Installation Guide. The recommended method is using Composer:
composer global require avelpress/avelpress-cliAvailable CLI Commands
The AvelPress CLI provides the following commands:
avel new- Create a new AvelPress pluginavel make:controller- Generate a new controlleravel make:model- Generate a new modelavel make:migration- Generate a new database migrationavel build- Build a distribution package of your plugin
Creating Your First Plugin
1. Create a New Plugin
avel new acme/task-managerThis will prompt you for:
- Display name: The name shown in WordPress admin (max 80 characters)
- Short description: Brief description of your plugin (max 150 characters)
After creation, navigate to your project and install dependencies:
cd acme-task-manager
composer install2. Project Structure
This will generate the following structure:
acme-task-manager/
├── acme-task-manager.php # Main plugin file
├── avelpress.config.php # Build configuration
├── composer.json
├── readme.txt
├── .gitignore
├── assets/
├── src/
│ ├── app/
│ │ ├── Http/Controllers/
│ │ ├── Models/
│ │ ├── Providers/
│ │ │ └── AppServiceProvider.php
│ │ ├── Admin/
│ │ │ ├── Setup.php
│ │ │ └── Menu.php
│ │ ├── Modules/
│ │ └── Services/
│ ├── bootstrap/
│ │ └── providers.php
│ ├── config/
│ │ └── app.php
│ ├── database/
│ │ └── migrations/
│ ├── resources/
│ │ └── views/
│ └── routes/
│ ├── api.php
│ └── admin.php
└── vendor/ # Composer dependencies3. Understanding Key Files
Build Configuration (avelpress.config.php)
<?php
return [
'plugin_id' => 'acme-task-manager',
'build' => [
'output_dir' => 'dist',
'prefixer' => [
'enabled' => true,
'namespace_prefix' => 'Acme\TaskManager',
]
]
];This configuration controls the build process:
plugin_id: Identifies your plugin for buildsprefixer.enabled: Whether to add namespace prefixes (prevents conflicts)namespace_prefix: The prefix to add to all namespaces when building
Main Plugin File (acme-task-manager.php)
<?php
/**
* Plugin Name: Task Manager
* Description: A new AvelPress plugin.
* Version: 1.0.0
* Requires at least: 6.0
* Requires PHP: 7.4
* Author: Your Name
* Text Domain: acme-task-manager
* License: GPLv2 or later
*/
use AvelPress\Avelpress;
defined( 'ABSPATH' ) || exit;
define( 'ACME_TASK_MANAGER_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
require ACME_TASK_MANAGER_PLUGIN_PATH . 'vendor/autoload.php';
Avelpress::init( 'acme-task-manager', [
'base_path' => ACME_TASK_MANAGER_PLUGIN_PATH . 'src',
] );2. Understanding the Generated Files
The CLI has created the basic structure with several important files:
Configuration (avelpress.config.php)
<?php
return [
'plugin_id' => 'acme-task-manager',
'build' => [
'output_dir' => 'dist',
'composer_cleanup' => true,
'prefixer' => [
'namespace_prefix' => 'Acme\\TaskManager\\'
]
]
];This configuration file is used by the avel build command to:
- Add namespace prefixes to vendor packages to prevent conflicts
- Specify which vendor packages to include in the build
- Configure the build process for distribution
Main Plugin File (acme-task-manager.php)
<?php
/**
* Plugin Name: Task Manager Pro
* Description: A comprehensive task management system for WordPress with advanced features.
* Version: 1.0.0
* Requires at least: 6.0
* Requires PHP: 7.4
* Author: Your Name
* Text Domain: acme-task-manager
* License: GPLv2 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
*/
use AvelPress\AvelPress;
defined( 'ABSPATH' ) || exit;
define( 'ACME_TASK_MANAGER_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
require ACME_TASK_MANAGER_PLUGIN_PATH . 'vendor/autoload.php';
AvelPress::init( 'acme-task-manager', [
'base_path' => ACME_TASK_MANAGER_PLUGIN_PATH . 'src',
] );Notice how the CLI uses the display name and description you provided during project creation.
Configuration (src/config/app.php)
<?php
defined( 'ABSPATH' ) || exit;
return [
'name' => 'Acme-task-manager',
'version' => '1.0.0',
'debug' => defined('WP_DEBUG') ? WP_DEBUG : false,
];Service Providers (src/bootstrap/providers.php)
<?php
defined( 'ABSPATH' ) || exit;
return [
Acme\TaskManager\App\Providers\AppServiceProvider::class,
];AppServiceProvider (src/app/Providers/AppServiceProvider.php)
<?php
namespace Acme\TaskManager\App\Providers;
use AvelPress\Support\ServiceProvider;
defined( 'ABSPATH' ) || exit;
class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*/
public function register(): void {
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void {
//
}
}3. Building the Task Manager
Now let's add the functionality to create a task management system using the CLI generators.
Building Your Plugin
Use the AvelPress CLI to create controllers, models, and migrations:
# Create a migration
avel make:migration create_tasks_table
# Create a model
avel make:model Task --timestamps
# Create a controller
avel make:controller TaskController --resourceAfter creating your components, you can build a production-ready distribution:
avel buildThis creates a dist/ directory with a production-ready version of your plugin, including namespace prefixing to prevent conflicts.
Testing Your Plugin
- Upload your plugin to
/wp-content/plugins/ - Activate it in the WordPress admin
- Test your API endpoints at
/wp-json/your-plugin/v1/endpoint
What's Next?
- Application Structure - Understand how AvelPress organizes code
- Service Providers - Learn about dependency injection
- Database Models - Work with database models
- Routing - Define API and admin routes
The generated file will look like this:
<?php
use AvelPress\Database\Migrations\Migration;
use AvelPress\Database\Schema\Blueprint;
use AvelPress\Database\Schema\Schema;
defined( 'ABSPATH' ) || exit;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void {
Schema::create( 'tasks', function (Blueprint $table) {
// Add columns to the table
} );
}
/**
* Reverse the migrations.
*/
public function down(): void {
Schema::drop( 'tasks' );
}
};Now update the up() method to define your table structure:
public function up(): void {
Schema::create( 'tasks', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description')->nullable();
$table->boolean('completed')->default(false);
$table->timestamps();
} );
}Tip: The CLI automatically detects table names from migration names. Use patterns like:
create_tasks_table- Creates a new tableadd_column_to_tasks_table- Modifies existing table- Use
--app-id=your-appto prefix table names automatically
Note: When using the
timestamps()method, the columnscreated_atandupdated_atwill be automatically created in the table to record the creation and update dates of each record.
Model
Use the AvelPress CLI to create a model:
avel make:model Task --timestampsAdvanced Model Options:
# Create model with fillable attributes
avel make:model Task --fillable=title,description,completed --timestamps
# Create model in a specific module
avel make:model Task --module=TaskManager --timestamps
# Create model with custom table name
avel make:model Task --table=custom_tasks --timestamps
# Create model with table prefix
avel make:model Task --prefix=tm_ --timestamps
# Create model in custom path
avel make:model Task --path=src/app/Custom/Models --timestampsThis will create src/app/Models/Task.php:
<?php
namespace Acme\TaskManager\App\Models;
use AvelPress\Database\Eloquent\Model;
defined( 'ABSPATH' ) || exit;
class Task extends Model {
/**
* The attributes that are mass assignable.
*/
protected $fillable = [
'title',
'description',
'completed'
];
/**
* Indicates if the model should be timestamped.
*/
public $timestamps = true;
}The CLI automatically:
- Creates the model with proper namespace based on your project structure
- Sets up fillable attributes if provided via
--fillableoption - Enables timestamps if
--timestampsflag is used - Uses proper WordPress coding standards
- Detects and applies the correct namespace from your project configuration
Note: By default, AvelPress (like Laravel) expects the table name to follow naming conventions. In this example, our
Taskmodel expects a table namedtasks. The difference is that AvelPress automatically detects and applies the WordPress table prefix (e.g.,wp_tasksif your prefix iswp_), so you don't need to make any manual adjustments regardless of what prefix your WordPress installation uses.
Controller
Use the AvelPress CLI to create a controller:
avel make:controller TaskController --resourceAdvanced Controller Options:
# Create controller in a specific module
avel make:controller TaskController --module=TaskManager --resource
# Create controller in custom path
avel make:controller TaskController --path=src/app/Custom/Controllers --resource
# Create simple controller without resource methods
avel make:controller TaskController
# Create API controller in a module
avel make:controller Api/TaskController --module=TaskManager --resourceThis will create src/app/Http/Controllers/TaskController.php with all CRUD methods:
<?php
namespace Acme\TaskManager\App\Http\Controllers;
use AvelPress\Routing\Controller;
defined( 'ABSPATH' ) || exit;
class TaskController extends Controller {
/**
* Display a listing of the resource.
*/
public function index() {
//
}
/**
* Show the form for creating a new resource.
*/
public function create() {
//
}
/**
* Store a newly created resource in storage.
*/
public function store($request) {
//
}
/**
* Display the specified resource.
*/
public function show($request) {
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit($request) {
//
}
/**
* Update the specified resource in storage.
*/
public function update($request) {
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($request) {
//
}
}Now you can implement the business logic for each method. For example:
public function index() {
$tasks = Task::all();
return JsonResource::collection($tasks);
}
public function store($request) {
$task = Task::create([
'title' => $request->get_param('title'),
'description' => $request->get_param('description'),
'completed' => false
]);
return new JsonResource($task);
}
public function show($request) {
$id = $request->get_param('id');
$task = Task::find($id);
if (!$task) {
return new \WP_Error('task_not_found', 'Task not found', ['status' => 404]);
}
return new JsonResource($task);
}
public function update($request) {
$id = $request->get_param('id');
$task = Task::find($id);
if (!$task) {
return new \WP_Error('task_not_found', 'Task not found', ['status' => 404]);
}
$task->update([
'title' => $request->get_param('title') ?: $task->title,
'description' => $request->get_param('description') ?: $task->description,
'completed' => $request->get_param('completed') ?? $task->completed
]);
return new JsonResource($task);
}
public function destroy($request) {
$id = $request->get_param('id');
$task = Task::find($id);
if (!$task) {
return new \WP_Error('task_not_found', 'Task not found', ['status' => 404]);
}
$task->delete();
return ['message' => 'Task deleted successfully'];
}The CLI automatically:
- Creates the controller with proper namespace based on your project structure
- Includes all CRUD methods when using
--resourceflag - Uses proper WordPress coding standards
- Places the controller in the correct directory structure
- Supports modular architecture when
--moduleoption is used - Automatically detects and applies the correct namespace from your project configuration
Routes
Update src/routes/api.php:
<?php
use Acme\TaskManager\App\Controllers\TaskController;
use AvelPress\Facades\Route;
defined('ABSPATH') || exit;
Route::prefix('task-manager/v1')->guards(['edit_posts'])->group(function () {
Route::get('/tasks', [TaskController::class, 'index']);
Route::post('/tasks', [TaskController::class, 'store']);
Route::get('/tasks/{id}', [TaskController::class, 'show']);
Route::put('/tasks/{id}', [TaskController::class, 'update']);
Route::delete('/tasks/{id}', [TaskController::class, 'destroy']);
});Building and Distributing Your Plugin
AvelPress CLI provides a powerful build system that creates production-ready distributions of your plugin.
Build Configuration
The avelpress.config.php file controls how your plugin is built:
<?php
return [
'build' => [
'prefixer' => [
'namespace_prefix' => 'Acme\\TaskManager\\',
'packages' => [
'avelpress/avelpress',
// Add other vendor packages you want to include
]
]
]
];Building Your Plugin
To create a distribution package:
avel buildThis command will:
- Check Requirements: Verify that all necessary files and configurations are present
- Collect Dependencies: Gather all vendor packages specified in the configuration
- Namespace Prefixing: Add namespace prefixes to prevent conflicts with other plugins
- Process Source Code: Copy and process your
src/directory, updating use statements for vendor packages - Process Vendor Packages: Copy and prefix vendor package namespaces
- Copy Assets: Include your
assets/directory and other necessary files - Create Distribution: Generate both a folder and ZIP file in the
dist/directory
Build Output:
Building distribution package for: acme-task-manager
Using namespace prefix: Acme\TaskManager
Created directory: dist/
Created directory: dist/acme-task-manager/
Copied and processed: src/
Copied and processed vendor package: avelpress/avelpress
Copied and processed Composer autoload files
Copied: assets/
Copied and processed: acme-task-manager.php
Copied: README.md
Created: acme-task-manager.zip
Build completed successfully!
Distribution files created in: dist/
- Folder: dist/acme-task-manager/
- ZIP: dist/acme-task-manager.zipBuild Features
Namespace Prefixing
The build system automatically prefixes namespaces to prevent conflicts:
- Vendor packages: All specified packages get prefixed namespaces
- Source code: Use statements for vendor packages are updated
- Autoload files: Composer autoload files are processed and updated
Automatic File Processing
- PHP files: Namespace and use statement processing
- Non-PHP files: Copied directly without modification
- Main plugin file: Use statements updated for vendor packages
- Composer autoload: All autoload files processed and updated
ZIP Extension Support
The build command includes automatic ZIP extension detection:
- If ZIP extension is available: Creates both folder and ZIP file
- If ZIP extension is missing: Shows installation instructions but continues with folder creation
- No build interruption due to missing ZIP extension
ZIP Extension Installation:
# Ubuntu/Debian
sudo apt-get install php-zip
# CentOS/RHEL
sudo yum install php-zip
# Windows
# Uncomment extension=zip in php.ini
# Docker
RUN docker-php-ext-install zipYou can now test your API endpoints:
# Get all tasks
curl -X GET "https://yoursite.com/wp-json/task-manager/v1/tasks"
# Create a task
curl -X POST "https://yoursite.com/wp-json/task-manager/v1/tasks" \
-H "Content-Type: application/json" \
-d '{"title": "My First Task", "description": "This is a test task"}'
# Get a specific task
curl -X GET "https://yoursite.com/wp-json/task-manager/v1/tasks/1"
# Update a task
curl -X PUT "https://yoursite.com/wp-json/task-manager/v1/tasks/1" \
-H "Content-Type: application/json" \
-d '{"completed": true}'
# Delete a task
curl -X DELETE "https://yoursite.com/wp-json/task-manager/v1/tasks/1"CLI Command Reference
avel new
Create a new AvelPress application (plugin or theme).
Syntax:
avel new <vendor>/<name> [--type=plugin|theme]Options:
--type- Application type:plugin(default) ortheme
Interactive Prompts (for plugins):
- Display name (max 80 characters)
- Short description (max 150 characters)
Examples:
# Create a plugin
avel new acme/task-manager
# Create a theme
avel new acme/my-theme --type=themeavel make:controller
Generate a new controller.
Syntax:
avel make:controller <name> [options]Options:
--resource- Generate resource controller with CRUD methods--module=<name>- Create controller in specific module--path=<path>- Custom controller path (default:src/app/Http/Controllers)
Examples:
# Basic controller
avel make:controller TaskController
# Resource controller with CRUD methods
avel make:controller TaskController --resource
# Controller in module
avel make:controller TaskController --module=TaskManager --resource
# Controller in custom path
avel make:controller Api/TaskController --path=src/app/Api/Controllersavel make:model
Generate a new model.
Syntax:
avel make:model <name> [options]Options:
--timestamps- Enable timestamps for the model--fillable=<list>- Comma-separated list of fillable attributes--table=<name>- Custom table name--prefix=<prefix>- Table prefix--module=<name>- Create model in specific module--path=<path>- Custom model path (default:src/app/Models)
Examples:
# Basic model
avel make:model Task
# Model with timestamps and fillable attributes
avel make:model Task --timestamps --fillable=title,description,completed
# Model in module
avel make:model Task --module=TaskManager --timestamps
# Model with custom table
avel make:model Task --table=custom_tasks --prefix=tm_avel make:migration
Generate a new database migration.
Syntax:
avel make:migration <name> [options]Options:
--module=<name>- Create migration in specific module--app-id=<id>- App ID prefix for table names--path=<path>- Custom migration path (default:src/database/migrations)
Examples:
# Basic migration
avel make:migration create_tasks_table
# Migration in module
avel make:migration create_tasks_table --module=TaskManager
# Migration with app-id prefix
avel make:migration create_tasks_table --app-id=tmavel build
Build a distribution package of your application.
Syntax:
avel buildRequirements:
- Must be run from the root of an AvelPress project
- Requires
avelpress.config.phpconfiguration file
Features:
- Namespace prefixing for vendor packages
- Automatic dependency processing
- ZIP file creation (if ZIP extension available)
- Production-ready distribution package
Configuration: The build process is controlled by avelpress.config.php:
<?php
return [
'build' => [
'prefixer' => [
'namespace_prefix' => 'YourVendor\\YourPackage\\',
'packages' => [
'avelpress/avelpress',
// Other vendor packages
]
]
]
];What's Next?
- Application Structure - Understand how AvelPress organizes code
- Service Providers - Learn about dependency injection
- Database Models - Work with database models
- Routing - Define API and admin routes
