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

Resource Generator Laravel Package

cloudstudio/resource-generator

Laravel package that generates resource classes from your Eloquent models, cutting the boilerplate out of API scaffolding. Point it at a model and get ready-to-edit resources, so you spend less time on repetitive setup and more on your app's logic.

View on GitHub
Deep Wiki
Context7

Getting Started

Confirm the target before you install anything. The repo tagline says "Resource Generator for Laravel Nova," while the package description talks about generic Laravel resource scaffolding (models, controllers, requests, routes). Those are different tools with different prerequisites — one requires a paid Nova license. Run php artisan list | grep -i resource immediately after install and read the command signatures; scope from source, not from the README prose.

Install pinned, dev-only. This is a build-time code generator. It has no service provider responsibilities you want in production, no middleware, no runtime hooks. It belongs in require-dev:

composer require --dev cloudstudio/resource-generator

Pin the exact version in composer.json ("cloudstudio/resource-generator": "x.y.z"), not a caret range. Last release is 2022-03-12, so a caret constraint is a live wire the next time someone runs composer update on a Laravel 10/11 app.

Check the compatibility gate first, not after. Verify three things before spending real time: PHP version, Laravel major, Nova major. A 2022 release realistically tops out around Laravel 8/9 and Nova 3/early 4. Also watch for a doctrine/dbal constraint — schema-introspecting packages commonly pin it, and it conflicts easily. If Composer refuses to resolve, that is a cheap, loud failure and you should stop there rather than hand-patching constraints.

Point it at one small table, on a throwaway branch. Seed a local database or restore a staging dump. Generation against a live/shared schema is non-deterministic and you will not be able to diff two runs. Then:

  1. php artisan vendor:publish to pull out config and stubs (check which tags the package registers — you want the stubs if you plan to customize namespaces).
  2. Pick a reference table with a mix of belongsTo, belongsToMany, and ideally one polymorphic relation.
  3. Generate, then git diff / read every generated file.
  4. Compare against one hand-written Nova resource you already trust.

First real use case: a lookup table (categories, statuses, regions) with a single belongsTo pointing at it. Small blast radius, obvious correctness criteria (does the index render, does the detail page load, does the relationship field populate), and it validates the whole workflow in under an hour. Do not start with your users or orders table — that's where the introspection weak spots live, and you'll misattribute the failures to the tool rather than to schema complexity.

Implementation Patterns

Generate into a scratch namespace, then promote. The single most valuable pattern with any schema-driven generator: don't write directly into app/Nova. If the package's config exposes a target path/namespace (most do), point it at app/Nova/_Generated or a throwaway branch, diff the output, and copy the good parts into place. This turns a destructive command into a reviewable one.

One module per run, dependency order. Generate lookup/reference tables first so relationship targets exist, then dependent entities. Running the whole schema at once produces a wall of files nobody reviews carefully, and the mistakes that matter (wrong foreign key inference, pivot tables emitted as first-class resources) get buried in the noise.

Treat generated output as a first draft you own, and hand-tune immediately. The generated resource gets you the fields() skeleton and the model wiring. What it will not get right — and what you add by hand on nearly every resource:

  • $this->resource instanceof Model guards and field-level ->rules() / ->creationRules() / ->updateRules() for validation. Introspection can't infer your business rules from column types.
  • Policies. Default authorization methods allow everyone with Nova access. Write the policy before the resource ships, not after.
  • Filters, Lenses, Actions, and metrics — scaffolding generally doesn't emit these, and if it does, review them skeptically.
  • Field display semantics: ->sortable() only on real columns, ->searchable() only where the index supports it, ->hideFromIndex() for long text/JSON, ->onlyOnDetail() for expensive relations.
  • $this->resource::newModel() defaults, public static $group, $title, $search, $perPageOptions.

Customize the stubs once, not each file. Publish the stubs and edit them to bake in your house conventions: your base Resource class, standard traits (LogsActivity, HasFilters — whatever you use), a $group derived from the domain, a consistent namespace. This is where the package pays for itself repeatedly — every subsequent resource inherits your conventions instead of Nova's defaults, so review time per resource drops instead of staying flat.

Override introspection via config for the types it gets wrong. Field/relationship mapping is config-driven, so most weak spots are fixable without touching vendor code: column type → Nova field class, foreign key → relationship type. Keep that config in the repo next to the generated code, with a comment on each override explaining why (e.g. "json → KeyValue"). It doubles as documentation of your schema's irregularities.

Snapshot the invocation in a runbook. Because you should not re-run this routinely, record the exact command, the seed/snapshot used, the pinned version, and the date in docs/. Six months later someone will want to add a column to a resource and will reach for the generator out of habit; the runbook is what stops them from clobbering three hand-tuned fields.

Static-analysis the output in CI, not the generator. Generated files go through Pint, PHPStan/Larastan, and php -l like any other code. Never wire the generator into CI — it's non-deterministic across environments and it would regress hand edits.

Gotchas and Tips

Regeneration overwrites, and that is the expensive failure mode. Assume any re-run clobbers hand edits in the target directory. Guard rails: branch-per-generation, generate to a scratch path, and git status before and after. If you genuinely need to regenerate after schema changes, delete the generated file first, regenerate, then re-apply your hand edits as a diff — never merge blindly over a working resource.

Generated code can load cleanly and still render wrong. php -l passing means nothing here. The real smoke test is: hit the Nova index, open a detail page, edit and save a record, and exercise each relationship field. Wrong foreign-key inference and missing casts surface at query time or as silently empty fields, not as errors.

Known introspection weak spots — check these first:

  • Polymorphic relations. morphTo needs both the *_type and *_id columns recognized together; generators frequently emit a plain BelongsTo on the ID with the type column as a stray field.
  • Pivot tables. Likely emitted as their own standalone resources. Almost always wrong — delete them and use BelongsToMany on the parents.
  • Enums. Backed enums on string columns come out as TextField/SelectField with no options. Replace with SelectField::make()->options(Enum::class).
  • JSON columns. Usually degrade to Textarea/TextField. Swap for KeyValue or a custom field.
  • Non-standard primary keys. UUIDs and non-id keys need $primaryKey, $keyType, public $incrementing = false on the model — introspection often misses this and Nova's detail route 404s.
  • Timestamps and soft-delete columns leaking into fields() as editable inputs.
  • Decimals and money coming out as Number with a float step. Use Number::make(...)->step(0.01) or Currency.

Relationship naming mismatches. Nova derives its relationship field label and the underlying method name from the generated code. If your model method is author() and the column is user_id, the generated field may reference a method that doesn't exist — instant error at render. Grep the generated BelongsTo/HasMany calls and match them against your model methods explicitly.

Config caching bites during iteration. Change a mapping in the package config and the old value persists until php artisan config:clear. If a mapping "isn't taking effect," clear config before you start reading vendor source.

Name collisions with existing resources. Generating for users when app/Nova/User.php already exists is either a silent overwrite or a Class already exists fatal, depending on the package's behavior. Check what exists in the target namespace before every run, and note that the tool's file naming may not match your hand-written conventions (UserResource vs User).

Extension points, in order of preference: (1) config-driven field/relationship mapping, (2) published stubs, (3) subclassing or decorating the Artisan command in your own app/Console, (4) forking — MIT permits it and the surface is small. Reach for (4) only if you've already decided the tool is worth keeping, because a fork is a maintenance commitment with no upstream to rebase onto.

Plan the retirement on day one. When the domain work is done, remove the package from require-dev (or vendor a patched copy if you had to fork) and leave the runbook behind. This is the right ending: the durable artifact is the PHP, and the package contributes nothing at runtime. Leaving it pinned indefinitely means dependabot flags you'll triage forever for a tool you never run again.

Write the exit criterion before you start. If, on your reference module, editing the generated output takes longer than authoring the resource from scratch, keep the hand-written version and drop the tool. That's a successful hour of evaluation, not a failure — and it's the outcome most likely on Laravel 10+/Nova 4.3x+ until you've proven otherwise.

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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo