a2workspace/laravel-model-builder
A Laravel package for generating and scaffolding Eloquent model classes from your database schema, helping you build models faster with less boilerplate.
Install the package with Composer and let Laravel auto-discover the service provider:
composer require <vendor>/<package>
Publish the package assets (config and stubs) so you can inspect what the generator will produce:
php artisan vendor:publish --provider="<Vendor>\<Package>\<Package>ServiceProvider"
This is the first place to look — the published config typically controls the target namespace, output path, and stub used by the generator.
Generate your first builder:
php artisan make:builder Invoice
BuilderMakeCommand scaffolds a dedicated builder class (commonly App\Builders\InvoiceBuilder) that you can attach to your Eloquent model.
Open the generated file and confirm the namespace and parent class resolve correctly. If the command errors out, verify the package version is v1.1.1 or later — that release specifically fixes a bug in BuilderMakeCommand, so an older install can fail at generation time even when the package is otherwise installed correctly.
First real use case: take one messy model that is full of repetitive scopeActive(), scopeRecent(), scopeForUser() methods and move them into a generated builder. That immediately demonstrates the value of the package and validates that the scaffolding wired up correctly.
Encapsulate query intent in the builder. Treat the builder as the single home for reusable, composable query fragments rather than scattering scopes across models:
// app/Builders/InvoiceBuilder.php
public function overdue(): static
{
return $this->where('due_at', '<', now())
->whereNull('paid_at');
}
public function forCustomer(int $customerId): static
{
return $this->where('customer_id', $customerId);
}
Because builders are chainable, this composes naturally at the call site:
Invoice::query()->overdue()->forCustomer($id)->latest()->get();
Wire the builder to the model once. Most packages of this shape expose a method or property on the model that returns a custom builder instance. Resolve the model's newEloquentBuilder() (or the package-provided equivalent) once per model and leave it alone — retrofitting it across a large codebase is the expensive part, so do it opportunistically.
Inject builders into services and actions. Where a builder is not tied to a single model, resolve it from the container in a form request, action class, or dedicated filter object. This keeps controllers thin and makes query logic testable in isolation.
Test at the builder level, not the endpoint level. Assert generated SQL or result sets directly against the builder. This is much faster and localises failures:
$sql = Invoice::query()->overdue()->toSql();
Regenerate after the upgrade. Because v1.1.1 is a bug fix inside the generator itself, existing generated builders are untouched — only future invocations of make:builder benefit. If a builder previously failed to scaffold, re-run the command now. If you have customised published stubs, diff them against the new package stubs after upgrading so your copies pick up the fix.
Pin and review. Keep the version constrained in composer.json and read the changelog on each patch release. A patch that repairs a generator is low-risk, but it can silently change the shape of newly generated classes.
Stale published stubs mask the fix. If you published stubs before upgrading to v1.1.1, the generator will keep using your old copies and the BuilderMakeCommand fix may appear not to work. Re-publish with --force (after committing or backing up local edits) or manually diff your stub against the vendor copy under vendor/<vendor>/<package>/stubs.
Clear caches after upgrading. Run php artisan config:clear and, in production, php artisan config:cache. A cached config pointing at an old stub path or namespace is a common cause of "the fix did nothing" reports.
Namespace mismatches are the usual root cause of generator failures. BuilderMakeCommand derives the target namespace from config; if you have renamed or relocated your app/ structure (e.g. custom App\Domain\... layout), update the package config before generating, or the command will write to a path that does not match the class it emits.
Naming convention expectations. Most generators infer a model from the builder name (Invoice → InvoiceBuilder, model Invoice). If your model lives in a non-standard namespace or has an unconventional name, pass the explicit option or edit the generated file rather than fighting the inference.
Watch for silent no-op commands. A generator that exits successfully but produces an empty or namespace-less file is worse than one that throws. After upgrading, generate one throwaway builder and open it before bulk-generating anything.
Do not put business logic in the builder. Builders should express query shape, not side effects, authorisation, or formatting. Keeping that boundary clean makes them safe to reuse and easy to test.
Extension points to prefer. If the package exposes a configurable stub or a base builder class, extend the base class rather than editing generated files — generated files are disposable and will be overwritten on regeneration, whereas a base class survives.
Debugging failures. Run the command with -vvv to get the underlying exception. A generator error usually traces back to one of three things: unresolvable namespace, missing/unwritable output directory, or a malformed stub.
Upgrade risk assessment for v1.1.1. This is a patch release containing only a Chinese-language note: "fix BuilderMakeCommand error." No new features, no deprecations, no breaking changes. Treat it as a safe, recommended upgrade if you rely on make:builder; skip it only if your builders are already generated and you are frozen mid-release.
How can I help you explore Laravel packages today?