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

Laravel Resource Modifier Laravel Package

toneflix-code/laravel-resource-modifier

A Laravel package for modifying API resources on the fly, letting you add, remove, or transform fields in JsonResource responses without rewriting resource classes. Useful for tailoring API output per request, user role, or context.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer (2.0 moved the vendor name — the old toneflix-code/... package is a different, now-superseded package name):

composer require toneflix/laravel-resource-modifier

Before you run that, confirm your platform matches the 2.0 constraints, because they are hard gates rather than soft suggestions:

  • PHP ^8.3|^8.4
  • Illuminate ^12.0|^13.0

If you are on Laravel 11 or PHP 8.2, stop here — 2.0 will not install, and toneflix-code/laravel-resource-modifier 1.1.5 is your ceiling until you upgrade the framework.

Laravel's package discovery should register the service provider automatically. If the README mentions a config file, publish it before touching any resource classes:

php artisan vendor:publish --tag=resource-modifier-config

Where to look first:

  1. README — updated in 2.0 for Laravel 12/13; the package is still small (0 stars, 0 dependents), so the README remains effectively the only documentation. Read it end to end before adopting.
  2. src/ directory — identify the service provider, any trait(s) meant to be applied to resources, and any middleware or macro registration. Note the namespace is now Toneflix\ResourceModifier; if you are porting code from 1.x, every import changes.
  3. composer.json — with 2.0 the constraint check is no longer advisory. Verify PHP ^8.3|^8.4 and Illuminate ^12.0|^13.0 against your app before composer require, not after a failed CI run.

First use case: you have an existing UserResource that injects debugging or internal metadata (timestamps, feature flags, IDs you don't want exposed) via with() or additional(), and you want a single, reusable place to strip or reshape that meta block across many resources instead of editing each toArray() method.

A minimal adoption path is:

use Illuminate\Http\Resources\Json\JsonResource;
// use the package's trait or base class here — check src/ for the exact name
use Toneflix\ResourceModifier\Concerns\ModifiesResourceMeta;

class UserResource extends JsonResource
{
    use ModifiesResourceMeta;

    public function toArray($request): array
    {
        return [
            'id'   => $this->id,
            'name' => $this->name,
        ];
    }
}

Then hit an endpoint that returns this resource and compare the raw JSON against the pre-adoption response. That diff is the fastest way to understand what the package actually intercepts.

Implementation Patterns

Centralize meta removal on a base resource. Rather than applying the modifier to every resource individually, create an App\Http\Resources\Resource base class that applies the trait, then extend it everywhere. This gives you one place to change behavior when the package updates or when you outgrow it — and, as 2.0 demonstrated, one place to absorb a vendor/namespace rename instead of editing dozens of files.

Alias the vendor namespace behind your own base class. 2.0 renamed both the package and the namespace with no functional change to the resource behavior. If your app only ever references Toneflix\ResourceModifier in a single base class, that upgrade was a two-line diff; if it references it in forty resources, it was a find-and-replace with a real chance of a missed import. Treat the vendor namespace as an implementation detail.

Conditional meta based on the request context. The most common real-world need is exposing extra metadata to internal consumers (admin dashboards, mobile apps you control) while hiding it from public clients. Use $request inside the modifier so the decision lives next to the resource:

public function toArray($request): array
{
    return [
        'id' => $this->id,
        // meta is conditionally shaped via the package's hook
    ];
}

Compose with pagination. Paginated resource collections get a meta object generated by Laravel's ResourceResponse containing pagination links and counts. If your package modifier replaces meta wholesale, you will silently break clients that read meta.current_page. The safe pattern is to merge your custom keys into the existing pagination meta rather than return a fresh array:

// conceptual — verify the exact hook signature against src/
'meta' => array_merge($paginationMeta, [
    'generated_at' => now()->toIso8601String(),
]),

Apply modifiers per-resource rather than globally at first. A global middleware or macro that rewrites every response is tempting, but it makes debugging harder and couples unrelated endpoints. Roll out resource-by-resource, keep the old toArray() output as an assertion in a feature test, and only promote to a global modifier once you have confidence.

Use it as an escape hatch, not a data-shaping layer. The package is for intercepting and trimming metadata. Keep business-field shaping in toArray(); keep metadata concerns (pagination extras, debug info, versioning) in the modifier. Mixing the two makes the modifier a second toArray() and defeats the purpose.

Integration with existing API tests. Add a test that asserts the absence of unwanted meta keys, not just the presence of wanted ones:

$response->assertJsonMissingPath('meta.internal_flag');
$response->assertJsonPath('meta.current_page', 1);

This catches regressions both when the package changes and when a developer accidentally reintroduces with() data. It is also your safety net for a major bump like 2.0, which claims behavior is unchanged — the test proves it on your payloads rather than in the changelog.

Upgrade 1.x → 2.x as a discrete commit. The release notes prescribe a remove-then-require dance; do it on its own branch with the test suite as the gate:

composer remove toneflix-code/laravel-resource-modifier
composer require toneflix/laravel-resource-modifier:^2.0

Then replace ToneflixCode\ResourceModifier with Toneflix\ResourceModifier in your imports and in the published config, which can carry fully-qualified class names in string form and will otherwise fail at runtime rather than at compile time.

Gotchas and Tips

2.0 is a rename, not a rewrite — but the rename is total. Package name, vendor name, and namespace all changed at once, and the platform floor moved to PHP 8.3 / Laravel 12. Nothing in the changelog suggests resource-visible behavior changed, so the risk of upgrading is almost entirely mechanical: stale use statements, a published config pointing at the old namespace, and CI images still on PHP 8.2. Plan the upgrade as a dependency-and-import sweep, not as a behavior review.

Both packages can end up installed. If composer remove is skipped or a lockfile is partially resolved, you can end up with toneflix-code/laravel-resource-modifier and toneflix/laravel-resource-modifier coexisting and two service providers registering the same hooks. Check composer show | grep resource-modifier after the upgrade and confirm exactly one entry remains.

Clear autoload and opcache after the namespace swap. Class "ToneflixCode\ResourceModifier\..." not found after upgrading is almost always vendor/composer/autoload_classmap.php or a warm opcache in a container, not a code error. Run composer dump-autoload -o and restart PHP-FPM/Octane before you start debugging your resource classes.

Pin the exact 2.x line, not ^2.0. The package has a 0-star/0-dependent profile, and 1.x → 2.0 shipped as a breaking rename. Use "toneflix/laravel-resource-modifier": "2.0.*" so a patch release cannot change response shape or force another rename mid-sprint, and add a Dependabot/Renovate entry so upgrades arrive as a reviewed PR rather than an unattended composer update. Treat every major as a breaking-change review by default.

Empty with() output drops the key entirely. Laravel only emits the merged with data when it is non-empty. If your modifier returns [], expect the meta key to disappear rather than render as {}. Clients that do response.meta?.x will be fine; clients that assume meta exists will break. Decide deliberately which contract you want.

Pagination meta collisions are the biggest risk. Because paginated responses build meta inside ResourceResponse, any wholesale replacement will strip links, current_page, total, and friends. Always test a paginated endpoint, not just a single-resource one — this is the failure mode most likely to reach production.

additional() and with() are not the same hook. additional() is recursive-merged at the top level and can clobber nested keys; with() is intended for top-level siblings of data. If you see unexpected key duplication (arrays turning into arrays-of-arrays), you are hitting array_merge_recursive behavior. Flatten or normalize before returning.

JsonResource::withoutWrapping() changes everything. If your app has disabled the data envelope, the location of meta shifts. Verify the modifier against your actual wrapping configuration in AppServiceProvider::boot(), not against a fresh Laravel skeleton.

Debugging: dump the response, not the resource. When meta looks wrong, use ->toResponse(request())->getData(true) so you see the fully wrapped output including pagination and additional merges. Dumping the raw array from toArray() hides exactly the layer the package operates on.

Middleware order matters if the package registers one. Response-modifying middleware runs on the way out, so it executes in reverse registration order. If you have TrimStrings, CORS, or a response-caching middleware, the modifier may run before or after them depending on where it is registered. Use php artisan route:list -v and the bootstrap/app.php middleware stack (Laravel 12/13 style — 2.0 targets 12+, so there is no Kernel to check) to confirm ordering.

Extension points worth checking in src/: a published config array (for global toggles), any registered macros on JsonResource (usable in with()), and any ResourceResponse subclass the provider binds. If none of these exist, fork-free extension means extending the package's trait in your own base resource — a small wrapper class is often cleaner than fighting the package.

Fallback plan. If the package proves too thin (likely, given its size), the same behavior is roughly 20 lines in a base resource using with(), additional(), and a ResourceResponse override. Keep the modifier logic behind your own App\Http\Resources\Resource base class so a future swap-out — or the next vendor rename — is a one-file change rather than a find-and-replace across dozens of resources.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource