Getting Started
This guide will walk you through creating your first AvelPress application. We'll build a simple plugin that demonstrates the core concepts of the framework 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-cli
This ensures you always get the latest stable version and all dependencies are managed automatically.
Available CLI Commands
The AvelPress CLI provides the following commands:
avel new
- Create a new AvelPress application (plugin or theme)avel 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 application
Testing Your Plugin
1. Activate the Plugin
- Upload your plugin to
/wp-content/plugins/
- Activate it in the WordPress admin
2. Test API Endpoints
You can also create a theme instead:
avel new acme/my-theme --type=theme
After creation, navigate to your project and install dependencies:
cd acme-task-manager
composer install
This will generate the following structure:
acme-task-manager/
├── acme-task-manager.php # Main plugin file
├── avelpress.config.php # Build configuration
├── composer.json
├── .gitignore
├── assets/
├── src/
│ ├── app/
│ │ ├── Controllers/
│ │ ├── Http/
│ │ ├── Models/
│ │ ├── Modules/
│ │ ├── Providers/
│ │ │ └── AppServiceProvider.php
│ │ └── Services/
│ ├── bootstrap/
│ │ └── providers.php
│ ├── config/
│ │ └── app.php
│ ├── database/
│ │ └── migrations/
│ ├── resources/
│ │ └── views/
│ └── routes/
│ └── api.php
└── vendor/ # Composer dependencies
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.
Database Migration
Use the AvelPress CLI to create a migration:
avel make:migration create_tasks_table
Advanced Migration Options:
# Create migration in a specific module
avel make:migration create_tasks_table --module=TaskManager
# Create migration with app-id prefix for table names
avel make:migration create_tasks_table --app-id=tm
# Create migration in custom path
avel make:migration create_tasks_table --path=custom/path/migrations
This will create a migration file in src/database/migrations/
with a timestamp prefix (e.g., 2024_07_22_143052_create_tasks_table.php
).
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-app
to prefix table names automatically
Note: When using the
timestamps()
method, the columnscreated_at
andupdated_at
will 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 --timestamps
Advanced 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 --timestamps
This 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
--fillable
option - Enables timestamps if
--timestamps
flag 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
Task
model expects a table namedtasks
. The difference is that AvelPress automatically detects and applies the WordPress table prefix (e.g.,wp_tasks
if 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 --resource
Advanced 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 --resource
This 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
--resource
flag - Uses proper WordPress coding standards
- Places the controller in the correct directory structure
- Supports modular architecture when
--module
option 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 build
This 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.zip
Build 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 zip
You 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=theme
avel 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/Controllers
avel 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=tm
avel build
Build a distribution package of your application.
Syntax:
avel build
Requirements:
- Must be run from the root of an AvelPress project
- Requires
avelpress.config.php
configuration 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?
Congratulations! You've created your first AvelPress plugin and learned how to use the CLI tools. Here's what you can explore next:
- Application Structure - Understand how AvelPress organizes code
- Service Providers - Learn about dependency injection and service containers
- Database Relationships - Add relationships between models
- JSON Resources - Customize API responses
- Validation - Add request validation
- CLI Reference - Complete CLI command documentation
Key Concepts Learned
In this tutorial, you learned:
- CLI Usage - How to use the AvelPress CLI to scaffold applications
- Project Structure - Understanding the generated directory structure
- Application Initialization - How to bootstrap AvelPress
- Service Providers - How to organize and register services
- Migrations - How to manage database schema changes with CLI generators
- Models - How to create models with various options using CLI
- Controllers - How to generate controllers with CRUD methods
- Routing - How to define API endpoints
- Build System - How to create production-ready distributions
- Namespace Prefixing - How the build system prevents conflicts
Best Practices
Project Organization
- Use modules for complex applications (
--module
option) - Follow consistent naming conventions
- Keep related functionality together
CLI Usage
- Use
--resource
flag for CRUD controllers - Include
--timestamps
for models that need audit trails - Use
--fillable
to explicitly define mass-assignable attributes - Use
--app-id
for table prefixing in migrations
Build and Distribution
- Always test your build output before distribution
- Keep your
avelpress.config.php
updated with required packages - Use semantic versioning for your releases
- Include proper documentation in your distribution package