Eloquent Models
AvelPress provides an Eloquent-style ORM that makes it easy to work with your database. Each database table has a corresponding "Model" that is used to interact with that table.
Creating Models
Using the CLI
The easiest way to create a model is using the AvelPress CLI:
# Basic model
avel make:model User
# Model with fillable attributes and timestamps
avel make:model User --fillable=name,email,status --timestamps
# Model in a specific module
avel make:model User --module=Auth --fillable=name,email --timestamps
# Model with custom table name and prefix
avel make:model User --table=wp_custom_users --prefix=custom_ --fillable=name,email
The CLI will automatically:
- Create the model file with proper namespace
- Set up fillable attributes if provided
- Enable timestamps if specified
- Add table prefix if specified
- Use proper WordPress coding standards
- Place the model in the correct directory structure
Manual Model Creation
You can also create models manually by extending the base Model
class:
<?php
namespace App\Models;
use AvelPress\Database\Eloquent\Model;
defined( 'ABSPATH' ) || exit;
class User extends Model {
// The table associated with the model
protected $table = 'users';
// The primary key for the model
protected $primaryKey = 'id';
// Indicates if the model should be timestamped
public $timestamps = true;
// The attributes that are mass assignable
protected $fillable = [
'name',
'email',
'password',
];
// The attributes that should be hidden for arrays
protected $hidden = [
'password',
'remember_token',
];
}
Model Configuration
Table Names
By convention, the table name is the plural form of the model name in lowercase. If your table name differs, specify it explicitly:
class User extends Model
{
protected $table = 'custom_users_table';
}
Table Prefix
If your tables use a custom prefix, you can specify it:
class User extends Model
{
protected $prefix = 'custom_';
}
Primary Keys
AvelPress assumes your table has a primary key column named id
. If different:
class User extends Model
{
protected $primaryKey = 'user_id';
// If your primary key is not an incrementing integer
public $incrementing = false;
// If your primary key is not an integer
protected $keyType = 'string';
}
Mass Assignment
Fillable Attributes
Define which attributes can be mass-assigned:
class User extends Model
{
protected $fillable = [
'name',
'email',
'status',
];
}
// Now you can use mass assignment
$user = User::create([
'name' => 'John Doe',
'email' => 'john@example.com',
'status' => 'active'
]);
Guarded Attributes
Alternatively, define which attributes should be protected:
class User extends Model
{
// Everything except these can be mass-assigned
protected $guarded = [
'id',
'password',
];
}
Timestamps
Automatic Timestamps
Enable automatic timestamp management:
class Post extends Model
{
public $timestamps = true;
// Customize timestamp column names if needed
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
}
Custom Timestamp Format
class Post extends Model
{
public $timestamps = true;
protected function getDateFormat()
{
return 'Y-m-d H:i:s';
}
}
Retrieving Models
All Models
// Get all users
$users = User::all();
// Get all with specific columns
$users = User::all(['name', 'email']);
Finding Models
// Find by primary key
$user = User::find(1);
// Find or fail (throws exception if not found)
$user = User::findOrFail(1);
// Find by multiple IDs
$users = User::find([1, 2, 3]);
// First match
$user = User::where('email', 'john@example.com')->first();
// First or fail
$user = User::where('email', 'john@example.com')->firstOrFail();
Query Builder Methods
Models provide access to all query builder methods:
// Where clauses
$activeUsers = User::where('status', 'active')->get();
// Multiple conditions
$users = User::where('status', 'active')
->where('age', '>', 18)
->get();
// Order and limit
$recentUsers = User::orderBy('created_at', 'desc')
->limit(10)
->get();
// Counting
$count = User::where('status', 'active')->count();
// Pagination
$users = User::paginate(15);
Creating and Updating
Creating Models
// Method 1: New instance
$user = new User;
$user->name = 'John Doe';
$user->email = 'john@example.com';
$user->save();
// Method 2: Mass assignment with create()
$user = User::create([
'name' => 'John Doe',
'email' => 'john@example.com',
]);
// Method 3: firstOrCreate (find or create)
$user = User::firstOrCreate(
['email' => 'john@example.com'],
['name' => 'John Doe', 'status' => 'active']
);
// Method 4: updateOrCreate
$user = User::updateOrCreate(
['email' => 'john@example.com'],
['name' => 'John Doe', 'status' => 'active']
);
Updating Models
// Update single model
$user = User::find(1);
$user->name = 'Jane Doe';
$user->save();
// Mass update
$user->update(['name' => 'Jane Doe', 'status' => 'inactive']);
// Update multiple models
User::where('status', 'pending')
->update(['status' => 'active']);
Deleting Models
Delete Single Model
$user = User::find(1);
$user->delete();
// Or delete by ID
User::destroy(1);
// Delete multiple
User::destroy([1, 2, 3]);
Delete by Query
// Delete all inactive users
User::where('status', 'inactive')->delete();
Soft Deletes
Enable soft deletes to mark records as deleted without actually removing them:
<?php
namespace App\Models;
use AvelPress\Database\Eloquent\Model;
use AvelPress\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $fillable = ['name', 'email'];
}
// This will set deleted_at timestamp instead of removing the record
$user = User::find(1);
$user->delete();
// Include soft deleted models
$users = User::withTrashed()->get();
// Only soft deleted models
$deletedUsers = User::onlyTrashed()->get();
// Restore soft deleted model
$user = User::withTrashed()->find(1);
$user->restore();
// Force delete (permanent)
$user->forceDelete();
Accessors and Mutators
Accessors
Transform data when retrieving from the database:
class User extends Model
{
// Get first name from full name
public function getFirstNameAttribute()
{
return explode(' ', $this->name)[0];
}
// Format email as lowercase
public function getEmailAttribute($value)
{
return strtolower($value);
}
// Get full URL for avatar
public function getAvatarUrlAttribute()
{
if ($this->avatar) {
return wp_upload_dir()['baseurl'] . '/avatars/' . $this->avatar;
}
return null;
}
}
$user = User::find(1);
echo $user->first_name; // Calls getFirstNameAttribute()
echo $user->avatar_url; // Calls getAvatarUrlAttribute()
Mutators
Transform data when saving to the database:
class User extends Model
{
// Hash password automatically
public function setPasswordAttribute($value)
{
$this->attributes['password'] = wp_hash_password($value);
}
// Store email as lowercase
public function setEmailAttribute($value)
{
$this->attributes['email'] = strtolower($value);
}
// Auto-generate slug from title
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
$this->attributes['slug'] = sanitize_title($value);
}
}
$user = new User;
$user->password = 'plaintext'; // Automatically hashed
$user->email = 'JOHN@EXAMPLE.COM'; // Stored as lowercase
$user->save();
Serialization
Array / JSON Conversion
$user = User::find(1);
// Convert to array
$array = $user->toArray();
// Convert to JSON
$json = $user->toJson();
// When returning from API routes, automatic conversion happens
return $user; // Automatically converts to JSON
Hiding Attributes
class User extends Model
{
protected $hidden = ['password', 'remember_token'];
// Or specify visible attributes
protected $visible = ['name', 'email'];
}
Appending Accessors
class User extends Model
{
protected $appends = ['first_name', 'avatar_url'];
public function getFirstNameAttribute()
{
return explode(' ', $this->name)[0];
}
public function getAvatarUrlAttribute()
{
return $this->avatar ? '/avatars/' . $this->avatar : null;
}
}
Model Events
Available Events
class User extends Model
{
protected static function boot()
{
parent::boot();
// Before creating
static::creating(function ($user) {
$user->uuid = wp_generate_uuid4();
});
// After creating
static::created(function ($user) {
// Send welcome email
wp_mail($user->email, 'Welcome!', 'Welcome to our site!');
});
// Before updating
static::updating(function ($user) {
// Log the change
error_log("User {$user->id} is being updated");
});
// After updating
static::updated(function ($user) {
// Clear cache
wp_cache_delete("user_{$user->id}");
});
// Before deleting
static::deleting(function ($user) {
// Delete related data
$user->posts()->delete();
});
}
}
Complete Example
Here's a complete User model with various features:
<?php
namespace App\Models;
use AvelPress\Database\Eloquent\Model;
use AvelPress\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
protected $table = 'users';
protected $primaryKey = 'id';
public $timestamps = true;
protected $fillable = [
'name',
'email',
'status',
'avatar',
];
protected $hidden = [
'password',
'remember_token',
];
protected $appends = [
'first_name',
'avatar_url',
];
// Accessors
public function getFirstNameAttribute()
{
return explode(' ', $this->name)[0];
}
public function getAvatarUrlAttribute()
{
if ($this->avatar) {
return wp_upload_dir()['baseurl'] . '/avatars/' . $this->avatar;
}
return get_avatar_url($this->email);
}
// Mutators
public function setEmailAttribute($value)
{
$this->attributes['email'] = strtolower(trim($value));
}
public function setPasswordAttribute($value)
{
$this->attributes['password'] = wp_hash_password($value);
}
// Relationships
public function posts()
{
return $this->hasMany(Post::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
// Model events
protected static function boot()
{
parent::boot();
static::creating(function ($user) {
$user->uuid = wp_generate_uuid4();
});
static::created(function ($user) {
// Create default profile
$user->profile()->create(['bio' => '']);
});
}
}
This Eloquent implementation provides a powerful and familiar way to work with your data while staying true to WordPress conventions and best practices.