meehh / laravel-goat
Terminal-first Laravel feature generator โ template & boilerplate for full feature slices (Model, Requests, Resources, Service, Repository, Policy, Tests) from a single migration or ERD. Not just CRUD.
Package info
pkg:composer/meehh/laravel-goat
Requires
- php: ^8.3
- illuminate/console: ^11.0|^12.0|^13.0
- illuminate/filesystem: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^9.0|^10.0
- phpunit/phpunit: ^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
php artisan goat:make Product
Why GOAT?
You paste a schema. GOAT ships the whole slice โ not just a controller.
|
You give Schema::create('products', function($t){ $t->id(); $t->foreignId('category_id')->constrained(); $t->string('name'); $t->decimal('price',10,2); $t->timestamps(); }); or a plain ERD:
|
You get โ template-ready
Service โ Repository, Resource, Policy, Tests included. |
No AI. No SaaS. No web UI. Pure PHP โ runs 100% locally.
โจ Feature Generator, not just CRUD
| CRUD generator | GOAT โ Feature / Template / Boilerplate |
|---|---|
| Model + Controller | + Service + Repository (separation) |
| No validation | + Store/Update Requests with inferred rules |
| No API layer | + JsonResource |
| No auth | + Policy (7 methods) |
| No tests | + Feature tests (5 scenarios) |
| One table = one file | ERD with N tables โ N slices |
| Hardcoded paths | All paths & namespaces configurable |
| Fixed stubs | Publish & customize โ vendor:publish --tag=goat-stubs |
Use it as:
- CRUD scaffold for admin panels
- Feature slice for clean architecture (Service/Repo)
- Boilerplate / template for new domains (
Inventory,Order,Booking) - Rapid prototyping from an ERD whiteboard
โก 10 seconds to first feature
composer require meehh/laravel-goat --dev php artisan goat:make Product
๐ GOAT โ Laravel Feature Generator
How do you want to define Product?
โฏ Paste Migration
Paste ERD
Use Existing Migration
Paste your migration. Press Ctrl+D when finished:
> Schema::create('products', ...);
> ^D
โ Schema detected
Product (products)
โโโ id bigInteger (PK)
โโโ category_id foreignId โ categories.id
โโโ name string
โโโ price decimal
โโโ created_at timestamp
Generate:
โ Model โ Migration โ Requests โ Resource โ Controller โ Service โ Repository โ Policy โ Tests
โ app/Models/Product.php
โ app/Services/ProductService.php
...
๐ GOAT generated Product successfully!
CI / non-interactive
cat migration.php | php artisan goat:make Product --from=migration --force cat erd.txt | php artisan goat:make Product --from=erd --force php artisan goat:make Product --from=database/migrations/2024_01_01_create_products_table.php php artisan goat:make Product --only=model,resource,request php artisan goat:make Product --except=policy,test # custom paths โ e.g. repo/admin instead of repositories/ php artisan goat:make Hello --paths=repository=app/Repo/Admin,model=app/Domain/Models --force # โ app/Repo/Admin/HelloRepository.php (App\Repo\Admin) + app/Domain/Models/Hello.php php artisan goat:make World --module=Admin --force # โ app/Modules/Admin/Models/World.php + app/Modules/Admin/Repositories/... # interactive: after schema preview GOAT asks โCustomize output paths?โ โ type per component
๐ Custom paths โ you choose where files go
No more locked app/Repositories. Put any artifact anywhere โ per run, no config edit needed:
# single: repo/Admin instead of repositories/ php artisan goat:make Hello --paths=repository=app/Repo/Admin --force # โ app/Repo/Admin/HelloRepository.php (namespace App\Repo\Admin auto) # multiple: split models & repos php artisan goat:make Hello --paths=repository=app/Repo/Admin,model=app/Domain/Models --force # โ app/Domain/Models/Hello.php (App\Domain\Models) # module: group everything under app/Modules/{Module} php artisan goat:make World --module=Admin --force # โ app/Modules/Admin/Models/World.php # app/Modules/Admin/Repositories/WorldRepository.php # app/Modules/Admin/Services/WorldService.php # tests/Feature/Modules/Admin/WorldTest.php # interactive: no flags โ after schema GOAT asks โCustomize output paths?โ โ y โ type per component php artisan goat:make Product
--paths is key=path comma-separated (model,migration,request,resource,controller,service,repository,policy,test). Paths can be absolute or app/... relative โ namespaces inferred automatically (app/Repo/Admin โ App\Repo\Admin). For permanent change, publish config/goat.php.
๐งฌ Inputs โ Migration or ERD โ one schema
Migration โ understands Blueprint:
id, string, text, integer, bigInteger, decimal, float, boolean, date, datetime, timestamp, foreignId, uuid, json, enum, softDeletes, timestamps, unique, nullable, default, constrained, indexโฆ
ERD โ plain text, forgiving:
inventories
------------
id bigint PK
product_name varchar
sku varchar UNIQUE
quantity integer
price decimal(10,2)
created_at timestamp
No type? Inferred (quantityโinteger, priceโdecimal, descriptionโtext). Handles PK, FK -> categories.id, UNIQUE, DEFAULT 0, varchar(100).
ERD full example
products
---------
id bigint PK
category_id bigint FK -> categories.id
name varchar
price decimal(10,2)
categories
----------
id bigint PK
name varchar
GoatSchema is the single source of truth โ parsers feed it, 9 generators consume it.
๐งฉ What gets generated
Product.php โ fillable, casts, belongsTo(Category::class)
protected $fillable = ['category_id','name','price']; protected function casts(): array { return ['price' => 'decimal:2']; } public function category(){ return $this->belongsTo(Category::class,'category_id'); }
Requests โ required/sometimes + string/integer/numeric/exists:categories,id/unique + max:255
Controller โ thin index/store/show/update/destroy, delegates to ProductService, uses ProductResource
Service โ Repository โ business vs query split, paginate/all/find/create/update/delete
Policy โ viewAny/view/create/update/delete/restore/forceDelete (edit stub to fit)
Test โ test_can_list_products โฆ test_can_delete_product with factory payloads
๐จ Customize Everything
// config/goat.php return [ 'paths' => [ 'model' => app_path('Models'), 'migration' => database_path('migrations'), 'request' => app_path('Http/Requests'), 'resource' => app_path('Http/Resources'), 'controller' => app_path('Http/Controllers'), 'service' => app_path('Services'), 'repository' => app_path('Repositories'), 'policy' => app_path('Policies'), 'test' => base_path('tests/Feature'), ], 'namespaces' => ['model' => 'App\\Models', /* ... */], 'generate' => ['model'=>true, /* ... */], ];
Stubs โ one per artifact:
stubs/model.stub, migration.stub, request.stub, resource.stub,
controller.stub, service.stub, repository.stub, policy.stub, test.stub
php artisan vendor:publish --tag=goat-stubs
# โ resources/stubs/vendor/goat/*.stub โ edit once, generate forever
StubRenderer prefers your published stub, falls back to package default.
๐ก๏ธ Safety & DX
- Never overwrites without
--forceโโ Product.php already exists. Use --force - Validates
--only/--except, empty input, unsupported types, bad table names โ no stack trace dumps - Naming via
NameResolver(productsโProduct,product_itemsโProductItem,category_idโcategory) --only=model,resource --except=policycomposable
๐๏ธ Architecture โ 2026
src/
โโโ Commands/MakeCommand.php # UX, STDIN, --from/--only/--except/--force
โโโ Parsers/MigrationParser.php # Blueprint โ GoatSchema
โ ErdParser.php # ERD โ GoatSchema (infer types)
โโโ Schema/GoatSchema|Table|Column|Relationship # โ single source
โโโ Generators/* (9) # Model/Migration/Request/Resource/Controller/Service/Repository/Policy/Test
โโโ Support/NameResolver|StubRenderer|FileWriter|GoatConfig
โโโ GoatServiceProvider.php # config + publish + command
No giant generator. Each artifact isolated, stub-driven, testable.
๐งช Tests
composer install composer test # vendor/bin/phpunit โ 40 tests
Covers: migration/ERD parsing, columns, relationships, naming, 9 generators, CLI, --only/--except/--force, file protection, stubs.
๐ฆ Install (GitHub)
composer config repositories.goat vcs https://github.com/CodeWithTeds/meehh.git composer require meehh/laravel-goat:@dev --dev
Once on Packagist: composer require meehh/laravel-goat --dev
Requires PHP ^8.3 ยท Laravel 11|12|13
๐บ๏ธ Roadmap
--api/--webpresets, enum casts, factories,--allfor multi-table ERD,goat:make --from=openapi
PRs welcome. Build your next feature with php artisan goat:make.
Built for builders who ship features, not boilerplate.
MIT ยท Owned by Prof Alex Software Dev / TE-AD ยท github.com/CodeWithTeds/meehh ยท Report issue ยท php artisan goat:make
