Search by

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.

Maintainers

Package info

github.com/CodeWithTeds/meehh

Documentation

pkg:composer/meehh/laravel-goat

Transparency log

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-05 03:38 UTC

This package is auto-updated.

Last update: 2026-09-05 07:19:27 UTC


README

GOAT โ€” meeeh

๐Ÿ GOAT

Terminal-first Laravel Feature Generator

Template ยท Boilerplate ยท Feature Slice โ€” from a single migration or ERD

๐Ÿ Your schema is already there. Why build around it manually when the structure you've already defined could be the starting point for everything that comes next?

PHP ^8.3 Laravel 11|12|13 Tests 40/40 License MIT Local First Version v1.0.0 Owner Prof Alex / TE-AD

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:

products
---------
id bigint PK
name varchar
price decimal(10,2)

You get โ€” template-ready

Product
โ”œโ”€โ”€ ๐Ÿ“„ 2024_*_create_products_table.php
โ”œโ”€โ”€ ๐Ÿงฉ Product.php (fillable, casts, belongsTo)
โ”œโ”€โ”€ โœ… StoreProductRequest.php
โ”œโ”€โ”€ โœ… UpdateProductRequest.php
โ”œโ”€โ”€ ๐Ÿ”Œ ProductResource.php
โ”œโ”€โ”€ ๐ŸŽฎ ProductController.php (thin)
โ”œโ”€โ”€ ๐Ÿง  ProductService.php (business)
โ”œโ”€โ”€ ๐Ÿ—„๏ธ ProductRepository.php (query)
โ”œโ”€โ”€ ๐Ÿ”’ ProductPolicy.php
โ””โ”€โ”€ ๐Ÿงช ProductTest.php

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=policy composable

๐Ÿ—๏ธ 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 / --web presets, enum casts, factories, --all for 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