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

Tomato Resource Laravel Package

tomatophp/tomato-resource

Tomato Resource generates complete CRUD resources for your TomatoPHP admin panel, turning Eloquent models into ready-to-use forms, tables, and pages with sensible defaults and configurable builders.

View on GitHub
Deep Wiki
Context7

Getting Started

Install it as part of the Tomato stack, not on its own. tomato-resource is the resource-definition layer for Tomato Admin — it gives you a fluent, class-based way to describe a model's columns, relationships, validation, filters, and actions in one place, then generates the migration, model, and CRUD wiring that tomato-crud and tomato-forms consume. Installing it alone gets you a config file and a base class; the payoff only lands once the sibling packages are present.

composer require tomatophp/tomato-resource
php artisan vendor:publish --tag=tomato-resource-config
php artisan vendor:publish --tag=tomato-resource-migrations
php artisan vendor:publish --tag=tomato-resource-lang   # only if you need label overrides
php artisan migrate
php artisan optimize:clear

Pin the version while you evaluate — "tomatophp/tomato-resource": "1.0.*". The latest tag is v1.0.0 from October 2023, with nothing since, so treat the constraint as a deliberate lock rather than a convenience.

Read these three things first, in this order:

  1. config/tomato-resource.php — the only real documented contract. It tells you which field types are supported, where generated files land, and which modules are enabled. Everything else below depends on what your checkout actually says in this file.
  2. The base resource class in src/ — this is where field definitions, table columns, form schema, filters, and actions are declared, and your generated resource classes extend it. It's also your primary extension point.
  3. The published migrations — the resources meta-table it installs. Inspect this before running migrate anywhere shared.

First use case — the intended day-one loop: boot the Tomato Admin panel, open the Resource builder, define a small table (posts with title:string, body:text, published:boolean), generate it, then read the emitted migration and model side by side against your field list. Confirm every field survived. Wire the model into a tomato-crud page and confirm index/create/edit render. That one end-to-end pass tells you more about this package than any amount of reading, because the generator's behaviour on unsupported types is silent — it drops the column rather than throwing.

Implementation Patterns

Let the generator own the artifact files, but commit the output. Generate in development, review the emitted migration and model by hand, then commit them as ordinary application code. Do not run the generator in CI or at deploy time — the whole value of a scaffolding tool is that the output is reviewed once and then becomes yours.

One resource class per model, and treat it as the single source of truth. If you find yourself editing the generated model's $fillable or casts by hand, that logic belongs in the resource definition, a subclass, or the base class — otherwise it drifts on the next regeneration.

Compose with tomato-crud deliberately. A resource gives you a schema, a migration, and a model — not a screen. The standard shape is the generated model plus a CRUD controller that consumes the resource schema:

// generated by tomato-resource
class Post extends Model { /* table, casts, relations */ }

// your admin page, backed by tomato-crud
class PostController extends TomatoCrud
{
    // points at the Post resource schema for columns/forms/filters
}

Keep screen-level concerns (eager loading, per-page size, row actions) in the controller and schema-level concerns in the resource class. Mixing them is what makes these screens painful six months in.

Subclass the base resource class for cross-cutting defaults. If every resource needs soft deletes, a UUID primary key, a common cast set, or a created_at column in the table, subclass the base and register your subclass so new generations inherit it automatically. This is the highest-leverage customization in the package and the one most likely to save you real time across a backlog of CRUD screens.

Use it for the back-office tables you'd otherwise hand-build. Internal admin panels, reference-data management, support tooling — that's where the schema → migration → model → CRUD pipeline pays for itself. It is not a fit for customer-facing schema, where you want migrations you wrote and understand line by line.

Diff every generated migration against your intended schema before committing. Unsupported field types typically show up as a silently dropped column rather than an exception, so the diff is your only reliable check — make it a habit after every generation, not a debugging step after something breaks.

Keep an interface boundary around the resource layer. Wrap your resource definitions behind your own base class rather than spreading direct references to the vendor class across the codebase. Given the package's age and adoption signals, this keeps a future swap or fork cheap — it costs you one class today.

Gotchas and Tips

  • It's v1.0.0 with a changelog-link release note. No feature list, no breaking-change list, no documented Laravel/PHP matrix. Read composer.json and the tagged diff yourself before adopting, and pin the version — expect config keys and class names to churn between minors.

  • Not standalone, by design. If the admin surface doesn't render, the problem is almost always tomato-admin or tomato-crud, not this package. Verify the parent panel boots before you start debugging anything here.

  • Migrations are the risk surface. A generator that writes migrations can quietly conflict with an existing schema. Always diff published migrations against your database, and run migrate on a scrubbed copy first. Take a backup and have a rollback plan before the first production deploy that includes these migrations.

  • Naming collisions are silent-ish and destructive. Generated model and controller names derive from the table name. If App\Models\Post already exists, the generator may overwrite it or refuse depending on config. Check output paths in config/tomato-resource.php before generating into a populated app/ directory — and never generate into a directory you haven't just backed up or committed.

  • Assume regeneration overwrites. Any custom logic living inline in a generated file will be lost on the next generation. Put customizations in a subclass, trait, or the base resource class — never inline.

  • Cache is the number one "my new field doesn't show" cause. After generating or editing a resource definition, run php artisan optimize:clear (at minimum config:clear). If a field appears in the migration but not the UI, clear cache before you start reading source.

  • Silent field drops. Unsupported field types usually don't throw — they produce a migration missing that column. Diff the generated migration against your intended schema after every generation, and log the resource definition that produced the output if it's wrong; reduce failures to the smallest failing field set rather than reverse-engineering generator internals.

  • Extension points live in two places: the base resource class (shared behaviour, custom field types) and the published config (output paths, enabled modules). Don't patch vendor files — you'll lose it on the next composer update, and in a v1.0.0 package the internal API isn't stable enough to make patches worthwhile anyway.

  • Authorization and validation assumptions are undocumented. The package scaffolds CRUD screens; it doesn't tell you what it assumes about policies or tenancy. Wire authorization explicitly at the controller layer and add your own validation rules — don't assume the resource definition's types are enforced server-side.

  • Load-test any resource-heavy screen. The CRUD layer may paginate without eager loading. Check query counts on index pages over a realistic dataset before it reaches a high-traffic admin area.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console