anas/easy-dev

๐Ÿš€ A powerful Laravel package that supercharges development with beautiful UI, interactive CRUD generation, Repository & Service patterns, and intelligent relationship detection.
76 11
Install
composer require anas/easy-dev
Latest Version:v2.1.1
PHP:^8.1
License:MIT
Last Updated:Mar 22, 2026
Links: GitHub  ·  Packagist
Maintainer: anasnashat

๐Ÿš€ Laravel Easy Dev v2

Latest Version on Packagist Total Downloads License: MIT

Laravel Easy Dev is a powerful code generation toolkit that supercharges your Laravel development. Generate complete CRUD systems with Repository & Service patterns, auto-detect model relationships, create policies, DTOs, observers, filters, enums, and more โ€” all with a beautiful interactive CLI.


๐Ÿ“‹ Table of Contents


โœจ Features

Feature Description
๐Ÿ—๏ธ CRUD Generation Model, Migration, Controllers (API + Web), Requests, Resources, Routes
๐Ÿ—„๏ธ Repository Pattern Repository + Interface with full CRUD method signatures
๐Ÿ”ง Service Layer Service + Interface with business logic separation
๐Ÿ›ก๏ธ Policies Authorization policy with viewAny, view, create, update, delete, restore, forceDelete
๐Ÿ“ฆ DTOs Data Transfer Objects with fromRequest(), fromModel(), toArray()
๐Ÿ‘๏ธ Observers Model lifecycle hooks: creating, created, updating, updated, deleting, deleted
๐Ÿ” Query Filters Reusable filter classes with apply() method
๐Ÿท๏ธ Enums PHP 8.1+ string-backed enums with values() and label() helpers
๐Ÿ”„ Relationship Detection Auto-detect belongsTo, hasMany, morphTo, morphMany from schema
๐Ÿ”ฎ Dry-Run Mode Preview all files before creating โ€” nothing is written to disk
โ†ฉ๏ธ Rollback Automatic cleanup on generation failure
๐ŸŽจ Beautiful CLI Progress bars, colored output, interactive wizard

๐Ÿ“‹ Requirements

  • PHP 8.1 or higher
  • Laravel 9.x / 10.x / 11.x / 12.x
  • Database MySQL, PostgreSQL, or SQLite

๐Ÿ“ฆ Installation

composer require anas/easy-dev --dev

The package auto-registers via Laravel package discovery. No manual setup needed.

Publish Configuration (optional)

php artisan vendor:publish --tag=easy-dev-config

Publish Stubs (optional)

php artisan vendor:publish --tag=easy-dev-stubs

Stubs are copied to resources/stubs/vendor/easy-dev/ where you can customize them.


๐Ÿš€ Quick Start

# 1. Generate a complete CRUD for "Product"
php artisan easy-dev:crud Product

# 2. Run the generated migration
php artisan migrate

# 3. Check your routes
php artisan route:list --path=products

That's it! You now have a Model, Migration, Web Controller, API Controller, Form Requests, API Resources, and Routes โ€” all generated and ready to use.


๐Ÿ“– Commands Reference

1. easy-dev:crud

The core command. Generates a complete CRUD system for a model.

php artisan easy-dev:crud {model} [options]

Options

Option Description
--with-repository Generate Repository pattern (Repository + Interface)
--with-service Generate Service layer (Service + Interface)
--with-policy Generate authorization Policy
--with-dto Generate Data Transfer Object
--with-observer Generate model Observer
--api-only Generate only API controller and routes (no web)
--web-only Generate only web controller and routes (no API)
--without-interface Skip Interface generation for Repository/Service
--dry-run Preview files without creating them

Examples

# Basic CRUD (Model + Migration + Controllers + Requests + Resources + Routes)
php artisan easy-dev:crud Post

# Full architecture stack
php artisan easy-dev:crud Order --with-repository --with-service --with-policy --with-dto --with-observer

# API-only with service layer
php artisan easy-dev:crud Product --api-only --with-service

# Preview what would be generated
php artisan easy-dev:crud Invoice --with-repository --with-service --dry-run

Generated Files (basic)

File Path
Model app/Models/Post.php
Migration database/migrations/xxxx_create_posts_table.php
Web Controller app/Http/Controllers/PostController.php
API Controller app/Http/Controllers/Api/PostApiController.php
Store Request app/Http/Requests/StorePostRequest.php
Update Request app/Http/Requests/UpdatePostRequest.php
API Resource app/Http/Resources/PostResource.php
API Collection app/Http/Resources/PostCollection.php

Additional Files (with flags)

Flag Files Generated
--with-repository app/Repositories/PostRepository.php, app/Repositories/Contracts/PostRepositoryInterface.php
--with-service app/Services/PostService.php, app/Services/Contracts/PostServiceInterface.php
--with-policy app/Policies/PostPolicy.php
--with-dto app/DTOs/PostData.php
--with-observer app/Observers/PostObserver.php

2. easy-dev:make

Interactive CRUD generator with a guided wizard. Wraps easy-dev:crud with a beautiful step-by-step UI.

# Interactive mode (no arguments โ€” wizard asks questions)
php artisan easy-dev:make

# Non-interactive mode (same options as easy-dev:crud)
php artisan easy-dev:make Product --with-repository --with-service

3. easy-dev:policy

Generate an authorization policy for an existing model.

php artisan easy-dev:policy {model}

Generated file: app/Policies/{Model}Policy.php

Methods included:

  • viewAny(User $user) โ€” List permission
  • view(User $user, Model $model) โ€” Read permission
  • create(User $user) โ€” Create permission
  • update(User $user, Model $model) โ€” Update permission
  • delete(User $user, Model $model) โ€” Delete permission
  • restore(User $user, Model $model) โ€” Restore soft-deleted
  • forceDelete(User $user, Model $model) โ€” Permanently delete

Usage in controllers:

$this->authorize('viewAny', Post::class);
$this->authorize('update', $post);

4. easy-dev:dto

Generate a Data Transfer Object for a model.

php artisan easy-dev:dto {model}

Generated file: app/DTOs/{Model}Data.php

Methods included:

  • fromRequest(Request $request): self โ€” Create from validated request
  • fromModel(Model $model): self โ€” Create from Eloquent model
  • toArray(): array โ€” Convert to array

Usage:

// In a controller
$dto = PostData::fromRequest($request);
$dto = PostData::fromModel($post);
$array = $dto->toArray();

5. easy-dev:observer

Generate a model observer with lifecycle hooks.

php artisan easy-dev:observer {model}

Generated file: app/Observers/{Model}Observer.php

Hooks included: creating, created, updating, updated, deleting, deleted

Register in AppServiceProvider::boot():

use App\Models\Post;
use App\Observers\PostObserver;

Post::observe(PostObserver::class);

Or use the #[ObservedBy] attribute (Laravel 10+):

use App\Observers\PostObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;

#[ObservedBy(PostObserver::class)]
class Post extends Model { }

6. easy-dev:filter

Generate a query filter class for a model.

php artisan easy-dev:filter {model}

Generated file: app/Filters/{Model}Filter.php

Usage:

// In a controller
$query = Post::query();
$filtered = PostFilter::apply($query, $request->validated());
return PostResource::collection($filtered->paginate());

7. easy-dev:enum

Generate a PHP 8.1+ backed enum.

php artisan easy-dev:enum {name} --values={comma-separated-values}

Generated file: app/Enums/{Name}.php

Example:

php artisan easy-dev:enum OrderStatus --values=pending,processing,shipped,delivered,cancelled

Generated code:

enum OrderStatus: string
{
    case PENDING = 'pending';
    case PROCESSING = 'processing';
    case SHIPPED = 'shipped';
    case DELIVERED = 'delivered';
    case CANCELLED = 'cancelled';

    public static function values(): array { ... }
    public function label(): string { ... }
}

Usage:

// In a migration
$table->string('status')->default(OrderStatus::PENDING->value);

// In a model cast
protected $casts = ['status' => OrderStatus::class];

// In code
OrderStatus::values(); // ['pending', 'processing', 'shipped', ...]
OrderStatus::PENDING->label(); // 'Pending'

8. easy-dev:repository

Generate repository pattern files for an existing model.

php artisan easy-dev:repository {model} [--without-interface]

Generated files:

  • app/Repositories/{Model}Repository.php
  • app/Repositories/Interfaces/{Model}RepositoryInterface.php

Register the binding in a service provider:

$this->app->bind(
    PostRepositoryInterface::class,
    PostRepository::class
);

Use via dependency injection:

public function __construct(protected PostRepositoryInterface $repository) {}

9. easy-dev:api-resource

Generate API Resource and Collection classes for an existing model.

php artisan easy-dev:api-resource {model} [--without-collection]

Generated files:

  • app/Http/Resources/{Model}Resource.php
  • app/Http/Resources/{Model}Collection.php

Usage:

return new PostResource($post);
return new PostCollection(Post::paginate());

10. easy-dev:sync-relations

Auto-detect relationships from your database schema or migration files and add them to models.

# Sync a specific model
php artisan easy-dev:sync-relations Product

# Sync ALL models
php artisan easy-dev:sync-relations --all

Detects:

  • belongsTo โ€” from foreignId columns in the model's migration
  • hasMany โ€” by scanning other migrations for foreign keys referencing this model
  • morphTo / morphMany โ€” from $table->morphs() columns

How it works:

  1. Finds the model's migration file
  2. Parses foreignId() and morphs() calls
  3. Scans all other migrations for reverse relationships
  4. Adds relationship methods to model files (skips if already exists)
  5. Optionally adds reverse relationships to related models

11. easy-dev:add-relation

Manually add a relationship method to an existing model.

php artisan easy-dev:add-relation {model} {relation} {related-model} [--method=name]

Supported relation types: hasOne, hasMany, belongsTo, belongsToMany, morphTo, morphOne, morphMany

Example:

php artisan easy-dev:add-relation User hasMany Post
# Adds posts() method to User model
# Optionally adds belongsTo inverse on Post model

12. easy-dev:help

Display the built-in help guide with all commands, options, and examples.

php artisan easy-dev:help
php artisan easy-dev:help --examples

๐Ÿ—๏ธ Generated Architecture

When you run easy-dev:crud with all flags, the generated file structure follows clean architecture principles:

app/
โ”œโ”€โ”€ DTOs/
โ”‚   โ””โ”€โ”€ ProductData.php                    # Data Transfer Object
โ”œโ”€โ”€ Enums/
โ”‚   โ””โ”€โ”€ ProductStatus.php                  # PHP 8.1+ Enum
โ”œโ”€โ”€ Filters/
โ”‚   โ””โ”€โ”€ ProductFilter.php                  # Query Filter
โ”œโ”€โ”€ Http/
โ”‚   โ”œโ”€โ”€ Controllers/
โ”‚   โ”‚   โ”œโ”€โ”€ ProductController.php          # Web Controller
โ”‚   โ”‚   โ””โ”€โ”€ Api/
โ”‚   โ”‚       โ””โ”€โ”€ ProductApiController.php   # API Controller
โ”‚   โ”œโ”€โ”€ Requests/
โ”‚   โ”‚   โ”œโ”€โ”€ StoreProductRequest.php        # Store Validation
โ”‚   โ”‚   โ””โ”€โ”€ UpdateProductRequest.php       # Update Validation
โ”‚   โ””โ”€โ”€ Resources/
โ”‚       โ”œโ”€โ”€ ProductResource.php            # API Resource
โ”‚       โ””โ”€โ”€ ProductCollection.php          # API Collection
โ”œโ”€โ”€ Models/
โ”‚   โ””โ”€โ”€ Product.php                        # Eloquent Model
โ”œโ”€โ”€ Observers/
โ”‚   โ””โ”€โ”€ ProductObserver.php                # Model Observer
โ”œโ”€โ”€ Policies/
โ”‚   โ””โ”€โ”€ ProductPolicy.php                  # Authorization Policy
โ”œโ”€โ”€ Repositories/
โ”‚   โ”œโ”€โ”€ ProductRepository.php              # Repository Implementation
โ”‚   โ””โ”€โ”€ Contracts/
โ”‚       โ””โ”€โ”€ ProductRepositoryInterface.php # Repository Interface
โ””โ”€โ”€ Services/
    โ”œโ”€โ”€ ProductService.php                 # Service Implementation
    โ””โ”€โ”€ Contracts/
        โ””โ”€โ”€ ProductServiceInterface.php    # Service Interface

database/
โ””โ”€โ”€ migrations/
    โ””โ”€โ”€ xxxx_create_products_table.php     # Migration

routes/
โ”œโ”€โ”€ api.php                                # API routes appended
โ””โ”€โ”€ web.php                                # Web routes appended

๐Ÿ”ฎ Dry-Run Mode

Preview exactly what would be generated โ€” without writing a single file:

php artisan easy-dev:crud Invoice --with-repository --with-service --with-policy --dry-run

Output:

๐Ÿ” DRY RUN โ€” Previewing CRUD generation for Invoice...

Files that would be created:

  ๐Ÿ“„ app/Models/Invoice.php
  ๐Ÿ“„ database/migrations/*_create_invoices_table.php
  ๐Ÿ“„ app/Repositories/InvoiceRepository.php
  ๐Ÿ“„ app/Repositories/Contracts/InvoiceRepositoryInterface.php
  ๐Ÿ“„ app/Services/InvoiceService.php
  ๐Ÿ“„ app/Services/Contracts/InvoiceServiceInterface.php
  ๐Ÿ“„ app/Http/Controllers/Api/InvoiceApiController.php
  ๐Ÿ“„ app/Http/Resources/InvoiceResource.php
  ๐Ÿ“„ app/Http/Resources/InvoiceCollection.php
  ๐Ÿ“„ app/Http/Controllers/InvoiceController.php
  ๐Ÿ“„ app/Http/Requests/StoreInvoiceRequest.php
  ๐Ÿ“„ app/Http/Requests/UpdateInvoiceRequest.php
  ๐Ÿ“„ app/Policies/InvoicePolicy.php

Files that would be modified:
  โœ๏ธ  routes/api.php
  โœ๏ธ  routes/web.php
  โœ๏ธ  app/Providers/RepositoryServiceProvider.php

No files were created or modified (dry-run mode).

โš™๏ธ Configuration

After publishing the config (php artisan vendor:publish --tag=easy-dev-config), edit config/easy-dev.php:

Model Namespace

'model_namespace' => 'App\\Models\\',

File Output Paths

'paths' => [
    'models'              => app_path('Models'),
    'controllers'         => app_path('Http/Controllers'),
    'api_controllers'     => app_path('Http/Controllers/Api'),
    'requests'            => app_path('Http/Requests'),
    'repositories'        => app_path('Repositories'),
    'repository_contracts' => app_path('Repositories/Contracts'),
    'services'            => app_path('Services'),
    'service_contracts'   => app_path('Services/Contracts'),
    'migrations'          => database_path('migrations'),
],

Route Configuration

'routes' => [
    'api_prefix'          => 'api',
    'web_prefix'          => '',
    'web_middleware'       => ['web'],
    'api_middleware'       => ['api'],
    'route_model_binding' => true,
],

Default Options

Set defaults so you don't repeat flags every time:

'defaults' => [
    'with_repository'          => false,  // Set true to always generate repos
    'with_service'             => false,  // Set true to always generate services
    'with_interface'           => true,   // Generate interfaces by default
    'generate_api_controller'  => true,   // Generate API controllers
    'generate_web_controller'  => true,   // Generate web controllers
],

Validation Rules

Auto-generated validation rules based on column types:

'validation' => [
    'rules' => [
        'string'   => 'required|string|max:255',
        'text'     => 'required|string',
        'integer'  => 'required|integer',
        'decimal'  => 'required|numeric',
        'boolean'  => 'required|boolean',
        'date'     => 'required|date',
        'email'    => 'required|email|max:255',
        'json'     => 'required|json',
    ],
    'field_patterns' => [
        'email'    => 'required|email|max:255',
        'password' => 'required|string|min:8',
        'slug'     => 'required|string|max:255|unique:{table}',
        '_id'      => 'required|integer|exists:{table},id',
    ],
],

Relationship Detection

'relationships' => [
    'auto_detect'                   => true,
    'detect_polymorphic'            => true,
    'generate_reverse_relationships' => true,
    'foreign_key_suffix'            => '_id',
    'polymorphic_suffix'            => '_type',
],

UI Settings

'ui' => [
    'show_progress_bar'        => true,
    'show_banner'              => true,
    'use_icons'                => true,
    'colored_output'           => true,
    'interactive_mode_default' => false,
],

๐ŸŽจ Customizing Stubs

After publishing stubs with php artisan vendor:publish --tag=easy-dev-stubs, you can customize any template in resources/stubs/vendor/easy-dev/.

Available Stubs (34 total)

Category Stubs
Models model.stub
Controllers controller.stub, controller.enhanced.stub, controller.api.stub, controller.api.enhanced.stub, controller.repository.stub, controller.api.service.stub, controller.web.service.stub
Repository repository.stub, repository.enhanced.stub, repository.interface.stub, repository.interface.enhanced.stub
Service service.stub, service.enhanced.stub, service.interface.stub, service.interface.enhanced.stub
Requests request.store.stub, request.update.stub, request.enhanced.stub
Resources api.resource.stub, api.collection.stub
New Generators policy.stub, dto.stub, observer.stub, filter.stub, enum.stub
Relations relations/belongsTo.stub, relations/hasOne.stub, relations/hasMany.stub, relations/belongsToMany.stub, relations/morphTo.stub, relations/morphOne.stub, relations/morphMany.stub
Other factory.stub

Stub Variables

All stubs use {{ variable }} placeholders:

Variable Description Example
{{ ModelName }} PascalCase model name Product
{{ modelName }} camelCase model name product
{{ tableName }} Snake_case plural table products
{{ RepositoryName }} Repository class name ProductRepository
{{ InterfaceName }} Interface class name ProductRepositoryInterface
{{ ServiceName }} Service class name ProductService
{{ fillable }} Fillable fields array ['name', 'price', 'stock']
{{ validationRules }} Validation rules 'name' => 'required|string|max:255'

๐Ÿ”„ Relationship Detection

The sync-relations command uses a multi-source approach:

graph TD
    A[easy-dev:sync-relations] --> B{Database tables exist?}
    B -->|Yes| C[Query PRAGMA foreign_key_list]
    B -->|No| D[Parse migration files]
    C --> E[Extract belongsTo relations]
    D --> F[Regex parse foreignId calls]
    D --> G[Regex parse morphs calls]
    F --> E
    G --> H[Extract morphTo relations]
    E --> I[Scan other migrations for reverse FK]
    I --> J[Extract hasMany relations]
    E & H & J --> K[Deduplicate by method name]
    K --> L[Insert into Model file]

Detection sources:

  1. Database schema โ€” PRAGMA foreign_key_list (SQLite) or information_schema (MySQL/PgSQL)
  2. Migration files โ€” Regex parsing of foreignId(), constrained(), and morphs() calls
  3. Cross-migration scanning โ€” finds reverse relationships in other migration files

๐Ÿ’ผ Real-World Workflows

E-Commerce Product Catalog

# 1. Create the enum for product status
php artisan easy-dev:enum ProductStatus --values=draft,active,archived

# 2. Create the full Product CRUD with all layers
php artisan easy-dev:crud Product --with-repository --with-service --with-policy --with-dto --with-observer

# 3. Create Category with basic CRUD
php artisan easy-dev:crud Category

# 4. Run migrations
php artisan migrate

# 5. Auto-detect relationships between Product and Category
php artisan easy-dev:sync-relations --all

# 6. Add a filter for product queries
php artisan easy-dev:filter Product

API-First Microservice

# API-only CRUD with service layer
php artisan easy-dev:crud User --api-only --with-service --with-dto

# Generate API resources for responses
php artisan easy-dev:api-resource User

# Add policies for authorization
php artisan easy-dev:policy User

Adding to an Existing Model

# Add repository pattern to existing model
php artisan easy-dev:repository Customer

# Add API resources
php artisan easy-dev:api-resource Customer

# Add relationships
php artisan easy-dev:add-relation Customer hasMany Order
php artisan easy-dev:add-relation Order belongsTo Customer

๐Ÿงช Testing

The package includes a comprehensive test suite:

cd packages/laravel-easy-dev
composer test

# Or with testdox output
vendor/bin/phpunit --testdox

Test suite: 67 tests, 176 assertions โ€” covering CRUD generation, dry-run mode, individual generators, relationship commands, and all services.


๐Ÿค Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create your feature branch: git checkout -b feature/amazing-feature
  3. Run the test suite: composer test
  4. Commit your changes: git commit -m 'Add amazing feature'
  5. Push to the branch: git push origin feature/amazing-feature
  6. Open a Pull Request

๐Ÿ“„ License

The MIT License (MIT). See LICENSE.md for details.

๐Ÿ‘จโ€๐Ÿ’ป Credits


Made with โค๏ธ for the Laravel community

โญ Star on GitHub โ€ข ๐Ÿ› Report Issues โ€ข ๐Ÿ’ฌ Discussions