Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Grease Laravel Package

onelearningcommunity/grease

Grease is a menu of independent, byte-identical performance tiers for Laravel's hot paths—Eloquent hydration, casting and serialization, events, Blade, config, validation, the container and router. Opt in per tier; the model trait is the zero-config starting point. Zero framework changes, and anythi...

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Check your framework floor first. v0.9.1 requires laravel/framework ^12.69.2 || ^13.33 (PHP 8.2–8.5). Composer will not offer the package below those floors, so bump within your current major before installing:

    composer update laravel/framework --with-dependencies
    composer require onelearningcommunity/grease
    

    If you are stuck on an older 12.x/13.x patch, stay on 0.9.0 — do not force the constraint.

  2. Publish config (if needed)

    php artisan vendor:publish --provider="OneLearningCommunity\Grease\GreaseServiceProvider"
    
    'enabled' => env('GREASE_ENABLED', true),
    
  3. First use case: prove parity, not speed. Grease overrides framework internals, so the first thing to run on your codebase is the shipped parity trait against your hairiest model — one with casts, a custom getTable(), or a runtime setTable():

    use OneLearningCommunity\Grease\Testing\HasGreaseWholeStateParityTest;
    
    class InvoiceParityTest extends TestCase
    {
        use HasGreaseWholeStateParityTest;
    
        protected function modelClass(): string
        {
            return Invoice::class;
        }
    }
    

    It compares the entire instance state (cold / warm / hydrated) against vanilla. Green there means you can trust the savings; measure with Debugbar/XHProf afterwards.


Implementation Patterns

Common Workflows

  1. Upgrade 0.9.0 → 0.9.1 in the right order. Framework patch first, then composer update onelearningcommunity/grease, then the full suite. 0.9.1 mirrors upstream drift since 0.9.0, so a mixed state (new Grease, stale Laravel) is not a supported combination.

  2. Query-time casting now round-trips. Model::query()->withCasts([...]) is applied to greased rows exactly as vanilla. If you had a workaround applying casts manually after hydration, delete it.

  3. Partitioned / archive tables are now safe. Runtime setTable() propagates to hydrated rows, so save()/delete() hit the query's table rather than the class table. The old caveat is gone — this is the pattern to reach for:

    $rows = Order::query()->setTable('orders_2025_09')->where('status', 'open')->get();
    $rows->first()->save(); // writes to orders_2025_09
    
  4. Convention-named models stay cheap; overrides don't. Models without $table get the derived name memoized per class. Any getTable() override (sharded, AsPivot, your own) is called per row, as vanilla does — budget for that in hot loops.

  5. Routing: upgrade if you use GreaseRoutingServiceProvider. route() parameters containing %, ? or # were emitted raw by the URL fast path, truncating the path. Fixed on 12.69.2 / 13.31. On 12.69.2+, 0.9.1 is required, not optional.

  6. Blade/Livewire surfaces. ComponentAttributeBag::merge() now terminates a style default with ; (12.63 / 13.19 parity), and the Livewire compatibility proof now covers Livewire 4. Re-run component snapshot tests after upgrading.

Integration Tips

  • Add the parity trait to CI for every model with a non-default table, casts, or #[Refreshes]. It is the cheapest regression net you will get for a package that patches internals.
  • Pin laravel/framework to a known-good patch and let your scheduled build (not your deploy) discover drift — Grease's own CI runs weekly against latest releases precisely because upstream moves.
  • Keep GREASE_ENABLED=false wired to an env flag so you can bisect a behaviour difference in one deploy.

Gotchas and Tips

Pitfalls

  1. composer update silently does nothing. If you are below the floors, Composer just won't offer 0.9.1 and you'll assume you're current. Verify with composer show onelearningcommunity/grease after updating.

  2. Request::all() key order differs by major. On 13.26+ input keys keep position and win a collision with an uploaded file; 12.x keeps the old order (probed once per process). Tests asserting array order across majors will lie to you.

  3. #[Refreshes] was being dropped after the first model per class before 0.9.1 — if you saw stale attributes on second-and-later models, that was the bug, not your code.

  4. resolveClassAttribute() now reads attributes on traits (13.21/13.22) and uses a property-keyed cache. Trait-declared attributes that appeared ignored are now honoured — re-check any test that asserted the old behaviour.

  5. The parity tripwire is a feature. HasGreaseWholeStateParityTest fails deliberately when Laravel ships a new Eloquent attribute class. Don't mute it; that failure is your early warning that Grease hasn't mirrored the new state yet.

  6. Caching conflicts still apply. Avoid remember()-style caching around rows mutated via touch()/updated_at, and clear cache when stale data appears:

    php artisan cache:clear
    

Debugging Tips

  • Diff greased vs vanilla instance state directly when a parity test goes red:
    $vanilla = Model::withoutGrease()->find(1); // or run with GREASE_ENABLED=false
    $greased = Model::find(1);
    dd($vanilla->getAttributes(), $greased->getAttributes());
    
  • Log queries and compare counts with optimization on/off:
    \DB::enableQueryLog();
    $results = User::where(...)->get();
    dd(\DB::getQueryLog());
    
  • Kill switch per request (CLI, Nova toolbars, debugging):
    \OneLearningCommunity\Grease\Facades\Grease::disable();
    
  • 'log_optimizations' => true in config/grease.php when you need to see which paths were taken.

Extension Points

  1. Custom optimizers via the service provider — but treat every override as a parity liability and cover it with the whole-state test:

    Grease::extend(function ($query, $model) {
        if ($model instanceof Post) {
            $query->select(['id', 'title', 'created_at']);
        }
    });
    
  2. Query builder overrides remain available for app-specific builders:

    use OneLearningCommunity\Grease\Concerns\OptimizedQuery;
    
    class CustomQueryBuilder extends Builder
    {
        use OptimizedQuery;
    }
    
  3. Version-gated behaviour. With two supported majors in flight (12 and 13), branch any extension that depends on ordering or attribute resolution rather than assuming one shape:

    if (app()->runningInConsole()) {
        \OneLearningCommunity\Grease\Facades\Grease::disable();
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel