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 Api Laravel Package

tomatophp/tomato-api

A Laravel package from the TomatoPHP ecosystem that helps you build and manage RESTful APIs, providing ready-made endpoints and scaffolding to speed up backend development and integrate your TomatoPHP apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Before anything else, check that it resolves. Last release was 2023-03-31, so the illuminate/* constraints sit in the Laravel 9–10 band. Run this in a throwaway branch on your actual app:

composer why-not laravel/framework "^11.0"
composer require tomatophp/tomato-api --dry-run

Read the full dependency tree the dry run prints — TomatoPHP packages pull on each other, and if this drags in an admin panel or roles/permissions package you're adopting that ecosystem's auth and routing conventions, which is a much bigger commitment than "a CRUD generator." If it won't resolve on your target Laravel version, stop here: everything below becomes a fork exercise, not an install.

Install, then publish — including the stubs.

composer require tomatophp/tomato-api
php artisan vendor:publish --provider="TomatoPHP\TomatoApi\TomatoApiServiceProvider"

You're looking for config (config/tomato-api.php), stub templates, and possibly a route file. Publish the stubs even if you don't plan to customize them yet — whether stubs are overridable is the single fact that decides whether this is a forkable asset or a dead end. Commit whatever lands before you generate a single file.

Wire up Sanctum. The package advertises token auth, so nothing generated will authenticate until the host app provides it:

composer require laravel/sanctum
php artisan install:api        # Laravel 11+; otherwise publish Sanctum migrations manually

HasApiTokens on your User, and auth:sanctum on the middleware group your config points at.

First use case: one boring model, then a five-file read. Pick a Category or a Tag — nothing touching User or payments. Find the generator command (php artisan list | grep tomato, or read the service provider), run it, then open every emitted file in this order:

  1. Routes — versioned (/api/v1/...)? What middleware actually got attached?
  2. Controller — where does the repository come from, and what does index return?
  3. Form requests — real validation rules, or ['required'] placeholders?
  4. Repository interface + Eloquent implementation — sane query building, or Model::all()?
  5. API Resource — field whitelist, or return parent::toArray()?

That read is your whole evaluation. Everything after it is deciding what to do with what you found.

Implementation Patterns

Treat it as a scaffold-and-extract tool, not a runtime dependency. The durable day-to-day workflow is: generate → review the diff → harden → commit as ordinary application code. Generated files stand alone; you aren't married to the vendor once they exist. Which means: commit generated output as normal source, and never regenerate it in CI.

Depend on the interface, not the model. The repository layer only earns its keep if controllers inject the contract:

final class CategoryController extends Controller
{
    public function __construct(
        private readonly CategoryRepositoryInterface $categories,
    ) {}

    public function index(): CategoryCollection
    {
        return new CategoryCollection($this->categories->paginate());
    }
}

If generated controllers call Category::query() directly, the abstraction is decorative — either wire it through properly or drop the pattern entirely and stop paying the indirection tax.

Harden the stubs once, generate many times. Highest-leverage move available. After your first resource proves out, edit the published stubs so every subsequent resource inherits your house rules:

  • authorize() in form requests, or an explicit policy binding
  • $fillable / $guarded on models — never trust the generator here
  • Pagination defaults and a stable sort order in the collection
  • Rate-limit middleware on the route group
  • The /v1 prefix, if it isn't already there

Patch twenty generated controllers by hand instead and you've built an internal framework with no design authority behind it.

Keep the version segment from day one. /api/v1/categories costs nothing now and buys a migration path later. If generated routes aren't versioned, fix the stub before adding a second resource — retrofitting a prefix across ten route files is pure churn.

Token issuance lives in your app, not the generator. Generated endpoints assume an authenticated user; they don't mint tokens. A small controller is the right home:

Route::post('/v1/tokens', [TokenController::class, 'store'])->middleware('throttle:6,1');

Scope tokens with Sanctum abilities so a read-only mobile client can't delete records.

One integration test per resource, written immediately. The generator ships no regression safety net, and re-running it can overwrite files. A RefreshDatabase feature test hitting index/show/store/update/destroy against status codes plus an authorization failure case is ~40 lines and is the only thing that will tell you a regeneration broke something.

For anything unusual, use the generator as a reference, not a shortcut. Plain CRUD models earn the scaffolding. Nested relations, computed fields, non-trivial filtering — hand-write the controller and copy only the parts that match your conventions, usually the resource class and the route registration.

Gotchas and Tips

Generated endpoints almost certainly ship without authorization. Silent and high-impact. Scaffolding emits stub defaults, and stub defaults are never policies. Before any generated resource hits a shared environment, verify index/show don't leak records across tenants and update/destroy check ownership — not merely auth. Put it in the PR template so every new resource re-triggers the check.

Mass assignment is on you. Controllers typically pass $request->validated() straight into create()/update(). If the form request's rules leak is_admin or tenant_id, a client sets it. Read rules() field by field the first few times; the generator will not protect you.

Regeneration overwrites hand edits. Classic generator failure mode. Pick one strategy and stay consistent: (a) generate once and treat the output as immutable-from-the-generator ordinary code, or (b) customize stubs so you never need to hand-edit. Mixing the two loses work.

Route collisions are easy to create. Regenerating a resource that already has routes registered duplicates bindings, and Laravel resolves the first match — producing confusing 404s and stale behavior. After every regeneration:

php artisan route:list --path=api

Confirm exactly one entry per verb per resource.

Config publish collisions. If your app already has an api.php route file or a Sanctum config, publishing this package's config can silently shadow it (or be shadowed). Diff what vendor:publish produced against what was already there, and check migration timestamps for prefix collisions.

Pin the version and name an owner. "tomatophp/tomato-api": "1.x" with no caret, plus a line in your README saying who owns the generated code. Zero stars, zero dependents, no release since March 2023 means "we use this package" is operationally identical to "we maintain a fork of it." Say it out loud so the next person doesn't wait on upstream.

Pre-agree the stop rule: rewrite more than roughly a third and you're not being saved time. Timebox the spike to one or two days on one model. If you're rewriting more than ~⅓ of the generated files to match house conventions, discard it. Having the threshold agreed up front stops the team from rationalizing past a bad result.

Extension points, ranked. Published stubs (shape the output) > published config (middleware, rate limits, route prefix) > container bindings for the repository interfaces (swap implementations, inject fakes) > everything else. If the stubs turn out not to be publishable, that's your signal to treat the repo as a reference implementation and write the templates in-house — a few hundred lines you fully control beats a dependency nobody maintains.

Debugging generated behavior. When an endpoint misbehaves, suspect in this order: middleware actually attached to the route (check route:list -v), the form request rejecting or passing too much, then the repository's query builder. The generated controller is usually the thinnest and least interesting layer.

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
shitoudev/permissionmanager