ac/model-traits-bundle
Symfony2 bundle that integrates American Councils’ ac/model-traits into your application, providing reusable model traits and related setup for Symfony projects. Useful for sharing common model behavior across entities with minimal boilerplate.
Installation:
composer require american-councils/model-traits-bundle
Add the bundle to config/bundles.php:
return [
// ...
AmericanCouncils\ModelTraitsBundle\ModelTraitsBundle::class => ['all' => true],
];
First Use Case:
Use the HasTimestamps trait in a Laravel model (Symfony2 equivalent in Laravel):
use AmericanCouncils\ModelTraits\HasTimestamps;
class Post extends Model
{
use HasTimestamps;
}
This auto-adds created_at and updated_at columns if they don’t exist.
Where to Look First:
HasSoftDeletes, HasSlug, HasUuid).Model Boilerplate Reduction: Replace repetitive methods with traits:
use AmericanCouncils\ModelTraits\HasSlug;
class Product extends Model
{
use HasSlug;
protected $slugField = 'name'; // Customize slug source
}
Automatically generates slugs from name on save.
Soft Deletes:
use AmericanCouncils\ModelTraits\HasSoftDeletes;
class User extends Model
{
use HasSoftDeletes;
protected $deletedAtColumn = 'deleted_at';
}
Adds delete() and forceDelete() methods; queries exclude soft-deleted records by default.
UUIDs:
use AmericanCouncils\ModelTraits\HasUuid;
class Order extends Model
{
use HasUuid;
protected $primaryKey = 'uuid';
}
Replaces auto-increment IDs with UUIDs; ensure uuid column exists.
Event Hooks:
Use HasEvents to trigger custom logic:
use AmericanCouncils\ModelTraits\HasEvents;
class Comment extends Model
{
use HasEvents;
protected static function bootHasEvents()
{
static::created(function ($model) {
// Send notification on creation
});
}
}
Database Migrations:
For HasTimestamps/HasSoftDeletes, add columns manually or use Laravel’s Schema::table():
Schema::table('posts', function (Blueprint $table) {
$table->timestamps(); // For HasTimestamps
$table->softDeletes(); // For HasSoftDeletes
});
Query Scopes:
Traits like HasSoftDeletes add global scopes. Override in boot() if needed:
protected static function bootHasSoftDeletes()
{
static::addGlobalScope('active', function (Builder $builder) {
$builder->whereNull('deleted_at');
});
}
Customization:
Override trait methods (e.g., generateSlug() in HasSlug) for business logic.
Symfony2 → Laravel Mismatch:
where() vs. Symfony’s createQueryBuilder()).boot() vs. Symfony’s __construct()).Missing Laravel-Specific Features:
Observers, Events, or Accessors/Mutators.use HasTimestamps;
class Post extends Model
{
use HasTimestamps;
public function getTitleAttribute($value)
{
return strtoupper($value); // Mutator
}
}
Database Column Conflicts:
HasTimestamps assume column names (created_at, updated_at). Override:
protected $dates = ['custom_created_at', 'custom_updated_at'];
Trait Loading Order:
boot() runs before traits. Defer trait logic to boot():
use HasEvents;
protected static function bootHasEvents()
{
static::created(function ($model) {
// Runs after Laravel's boot()
});
}
Check Trait Methods:
Use php artisan tinker to inspect trait methods:
$post = new Post();
get_class_methods($post); // List all methods (including traits)
Override for Debugging: Temporarily override a trait method to log behavior:
public function generateSlug()
{
\Log::info('Generating slug for: ' . $this->name);
return parent::generateSlug();
}
Add Custom Traits: Fork the model-traits repo and extend:
namespace App\Traits;
use AmericanCouncils\ModelTraits\Concerns\HasSlug;
trait HasCustomSlug
{
use HasSlug;
public function generateSlug()
{
return strtolower(parent::generateSlug());
}
}
Laravel-Specific Traits: Create Laravel-compatible traits by wrapping Symfony logic:
trait HasLaravelSoftDeletes
{
public static function bootHasSoftDeletes()
{
static::addGlobalScope('softDeletes', function (Builder $builder) {
$builder->whereNull('deleted_at');
});
}
public function delete()
{
$this->forceFill(['deleted_at' => now()])->save();
}
}
Configuration:
Use Laravel’s config() helper to centralize trait settings:
// config/traits.php
return [
'slug_separator' => '-',
];
// In trait:
$separator = config('traits.slug_separator');
How can I help you explore Laravel packages today?