wendelladriel/
laravel-expressive
g4t.io

Typed Objects for Eloquent with Expressive

72 stars by Yannick Lyn Fatt

Typed Objects for Eloquent

README from wendelladriel/laravel-expressive Open on GitHub →

Installation

You can install the package via composer:

composer require wendelladriel/laravel-expressive

You can publish the config file with:

php artisan vendor:publish --tag="expressive"

Usage

Add the IsExpressive trait to models that should convert to typed Expressive objects:

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use WendellAdriel\Expressive\Concerns\IsExpressive;

#[Fillable(['name', 'email', 'role', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
    use IsExpressive, Notifiable;

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }

    public function address(): HasOne
    {
        return $this->hasOne(Address::class);
    }

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'role' => UserRole::class,
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    protected function displayName(): Attribute
    {
        return Attribute::make(
            get: fn (): string => "{$this->name} ({$this->role->value})",
        );
    }
}

Generate an Expressive class from a model:

php artisan make:expressive User --model="App\Models\User"

Generate classes for discovered models in bulk when you want to scaffold a project at once:

php artisan expressive:generate --path="app/Models"

Check generated classes for model drift in CI:

php artisan expressive:sync --all

The generated class will live in App\Expressive by default:

use App\Enums\UserRole;
use App\Expressive\Address;
use App\Expressive\Post;
use App\Models\User as UserModel;
use Carbon\CarbonInterface;
use Illuminate\Support\Collection;
use WendellAdriel\Expressive\Attributes\Relationship;
use WendellAdriel\Expressive\Attributes\Virtual;
use WendellAdriel\Expressive\Expressive;

/**
 * @extends Expressive<UserModel>
 */
final class User extends Expressive
{
    public ?int $id = null;

    public string $name;

    public string $email;

    public UserRole $role;

    public string $password;

    public ?string $rememberToken = null;

    public ?CarbonInterface $emailVerifiedAt = null;

    public ?CarbonInterface $createdAt = null;

    public ?CarbonInterface $updatedAt = null;

    #[Relationship]
    public ?Address $address = null;

    /** @var Collection<int, Post>|null */
    #[Relationship]
    public ?Collection $posts = null;

    #[Virtual]
    public ?string $displayName = null;
}

Loaded relationships are converted recursively. A HasOne relation becomes the related model's Expressive object, and a HasMany relation becomes a Collection of Expressive objects.

Convert models, collections, and builders:

$user = User::findOrFail(1)->expressive(attributes: ['display_name']);
$users = User::query()->get()->expressive(relationships: ['posts']);
$users = User::query()
    ->where('active', true)
    ->expressive(relationships: ['posts']);

Access the full documentation here.

Changelog

Please see the changelog for more information on what has changed recently.

Contributing

Thank you for considering contributing to Expressive! You can read the contribution guide here.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

Expressive is open-sourced software licensed under the MIT license.

More from the ecosystem

marcreichel/
laya-php
g4t.io
3 53

LayaPHP: Self-Hosted Text Classification for PHP and Laravel

Classify text in PHP without an LLM bill: typed decisions in 100+ languages, self-hosted. Laravel-ready SDK for Laya, a Jev AI alternative.

ai classification decision-engine
marcreichel/laya-php via Laravel News
Josh-Dovey/
postcodes-laravel
g4t.io
5 9

Postcodes for Laravel: GB Postcode Lookup and Geography Data

Postcodes for Laravel adds typed GB postcode lookups, validation, geography data, distance searches, and test fakes through the GB Postcodes API.

Josh-Dovey/postcodes-laravel via Laravel News
RedberryProducts/
mailbox-for-laravel
g4t.io
4 115

Mailbox for Laravel: Preview and Test Rendered Email

Mailbox for Laravel captures outgoing mail in a local dashboard and lets you test rendered HTML, recipients, and attachments with fluent assertions.

RedberryProducts/mailbox-for-laravel via Laravel News