PHPackages                             efati/laravel-scaffolder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. efati/laravel-scaffolder

ActiveLibrary[Admin Panels](/categories/admin)

efati/laravel-scaffolder
========================

Laravel Scaffolder - A powerful package for scaffolding complete feature stacks with Repository, Service, DTO, Policy, Tests, and more.

v8.0.9(7mo ago)28[1 PRs](https://github.com/AfshinEfati/Laravel-Scaffolder/pulls)MITPHPPHP ^8.1CI passing

Since Dec 2Pushed 2w ago1 watchersCompare

[ Source](https://github.com/AfshinEfati/Laravel-Scaffolder)[ Packagist](https://packagist.org/packages/efati/laravel-scaffolder)[ Docs](https://github.com/AfshinEfati/Laravel-Scaffolder)[ RSS](/packages/efati-laravel-scaffolder/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (1)Versions (7)Used By (0)

Laravel Scaffolder
==================

[](#laravel-scaffolder)

Laravel Scaffolder generates a complete, configurable feature stack for Laravel applications: repositories, services, DTOs, actions, policies, controllers, form requests, API resources, providers, feature tests, and OpenAPI documentation.

This README is the single source of project documentation. Command behavior, configuration, Swagger usage, Jalali dates, testing, upgrading, contribution rules, and troubleshooting are maintained here.

**Languages:** [English](#english-documentation) · [فارسی](#%D9%85%D8%B3%D8%AA%D9%86%D8%AF%D8%A7%D8%AA-%D9%81%D8%A7%D8%B1%D8%B3%DB%8C)

English Documentation
---------------------

[](#english-documentation)

Contents
--------

[](#contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Module Command](#module-command)
- [Schema Sources](#schema-sources)
- [Generated Structure](#generated-structure)
- [Configuration](#configuration)
- [Runtime APIs](#runtime-apis)
- [Swagger and OpenAPI](#swagger-and-openapi)
- [Jalali Dates](#jalali-dates)
- [Testing](#testing)
- [Troubleshooting](#troubleshooting)
- [Upgrading and Changelog](#upgrading-and-changelog)
- [Contributing and Security](#contributing-and-security)

Requirements
------------

[](#requirements)

- PHP `^8.1`
- Laravel `^10.0` or `^11.0`
- Composer 2

Installation
------------

[](#installation)

Install the package:

```
composer require efati/laravel-scaffolder
```

Laravel package discovery registers the service provider automatically. Publish the base classes and configuration when you want application-level copies:

```
php artisan vendor:publish \
  --provider="Efati\ModuleGenerator\ModuleGeneratorServiceProvider" \
  --tag=module-generator
```

Publish customizable generator stubs:

```
php artisan vendor:publish \
  --provider="Efati\ModuleGenerator\ModuleGeneratorServiceProvider" \
  --tag=module-generator-stubs
```

Published stubs live in `resources/stubs/module-generator`.

Quick Start
-----------

[](#quick-start)

The command needs an existing Eloquent model unless schema metadata is supplied with `--fields` or `--from-migration`.

```
php artisan make:model Product -m
php artisan make:module Product
```

Generate an explicit API stack:

```
php artisan make:module Product --api
```

Generate the complete stack, including Swagger, actions, policy, requests, resources, tests, DTO, provider, service, repository, and controller:

```
php artisan make:module Product --all
```

Overwrite existing generated files:

```
php artisan make:module Product --all --force
```

Generate without an existing model or migration:

```
php artisan make:module Product --api \
  --fields="name:string:unique,price:decimal(10,2),is_active:boolean,category_id:integer:fk=categories.id"
```

Module Command
--------------

[](#module-command)

```
php artisan make:module {name} [options]

```

### Options

[](#options)

OptionAliasPurpose`--controller=Subdir``-c`Put the controller in a custom subdirectory.`--api`—Generate an API controller; also enables requests and actions unless explicitly disabled.`--requests``-r`Generate store and update form requests.`--tests``-t`Force feature-test generation.`--actions`—Generate CRUD action classes.`--policy`—Generate a policy class.`--swagger``-sg`Generate module OpenAPI/PHPDoc documentation. Used alone, it runs in Swagger-only mode.`--all``-a`Generate the complete module stack.`--full``-f`Same complete-stack behavior as `--all`.`--from-migration=...``-fm`Read field metadata from a migration path or hint.`--fields=...`—Supply inline schema metadata.`--force`—Overwrite existing output files.`--no-controller``-nc`Skip the controller.`--no-resource``-nr`Skip the API resource.`--no-dto``-nd`Skip the DTO.`--no-test``-nt`Skip the feature test.`--no-provider``-np`Skip provider generation and automatic bindings.`--no-actions`—Skip action classes.`--no-policy`—Skip the policy.`--no-swagger`—Skip Swagger documentation.`--api` has no short alias. The `-a` alias belongs to `--all`, `-f` belongs to `--full`, and `--force` has no short alias.

### Common Recipes

[](#common-recipes)

```
# API module with generated validation and actions
php artisan make:module Order --api

# Web controller in a custom folder
php artisan make:module Invoice --controller=Admin/Accounting --no-actions

# Full stack, preserving existing files
php artisan make:module Customer --all

# Full stack, replacing existing files
php artisan make:module Customer --all --force

# Swagger file only for an existing module
php artisan make:module Product --swagger

# Policy without Swagger
php artisan make:module Product --policy --no-swagger
```

Schema Sources
--------------

[](#schema-sources)

The generator merges metadata from these sources:

1. Inline `--fields` definitions.
2. A migration selected with `--from-migration`.
3. Runtime Eloquent metadata and database columns.
4. Model `$fillable` and casts as fallback metadata.

Inline schema has the form `name:type:modifier:modifier`. Commas separate fields; commas inside parentheses such as `decimal(10,2)` are preserved.

### Supported Types

[](#supported-types)

Common normalized types include:

- `string`, `char`, `varchar`
- `text`, `mediumText`, `longText`
- `integer`, `bigInteger`, `foreignId`
- `decimal`, `numeric`, `float`, `double`
- `boolean`
- `date`, `datetime`, `timestamp`
- `json`, `array`
- `uuid`, `email`, `url`

### Supported Modifiers

[](#supported-modifiers)

- `nullable`, `null`, or `optional`
- `required`, `notnull`, or `not-null`
- `unique` or `uniq`
- `fk=table.column`
- `foreign=table.column`
- `references=table.column`

Examples:

```
php artisan make:module Subscription --api \
  --fields="tenant_id:integer:fk=tenants.id,plan:string,status:string,expires_at:datetime:nullable"

php artisan make:module Product --api \
  --fields="sku:string:unique,price:decimal(12,2),metadata:json:nullable"

php artisan make:module Product --api \
  --from-migration=create_products_table
```

Invalid PHP identifiers, reserved keywords, and duplicate field names stop generation instead of producing invalid PHP.

Generated Structure
-------------------

[](#generated-structure)

Depending on options and configuration, a module can create:

```
app/
├── Actions/Product/
├── DTOs/ProductDTO.php
├── Docs/ProductDoc.php
├── Http/Controllers/Api/V1/ProductController.php
├── Http/Requests/Product/
│   ├── StoreProductRequest.php
│   └── UpdateProductRequest.php
├── Http/Resources/ProductResource.php
├── Policies/ProductPolicy.php
├── Providers/ProductServiceProvider.php
├── Repositories/
│   ├── Contracts/ProductRepositoryInterface.php
│   └── Eloquent/ProductRepository.php
└── Services/
    ├── Contracts/ProductServiceInterface.php
    └── ProductService.php

tests/Feature/ProductTest.php

```

### Responsibilities

[](#responsibilities)

- **Repository:** persistence and query access.
- **Service:** application/business operations.
- **DTO:** typed request data transfer.
- **Action:** focused CRUD use cases with generated logging support.
- **Form Request:** validation rules inferred from schema metadata.
- **Resource:** API serialization, casts, dates, and loaded relations.
- **Controller:** API or web orchestration.
- **Provider:** repository/service bindings and provider registration.
- **Policy:** authorization skeleton.
- **Feature Test:** generated CRUD test scaffold.
- **Swagger Doc:** module-level OpenAPI-compatible PHPDoc annotations.

Existing files are skipped unless `--force` is supplied. Empty or failed generator results cause the command to return a failure status rather than reporting false success.

Configuration
-------------

[](#configuration)

The canonical configuration file is `config/module-generator.php` after publishing.

### Paths

[](#paths)

```
'base_namespace' => 'App',

'paths' => [
    'repository' => [
        'eloquent' => 'Repositories/Eloquent',
        'contracts' => 'Repositories/Contracts',
    ],
    'service' => [
        'concretes' => 'Services',
        'contracts' => 'Services/Contracts',
    ],
    'dto' => 'DTOs',
    'provider' => 'Providers',
    'controller' => [
        'api' => 'Http/Controllers/Api/V1',
        'web' => 'Http/Controllers',
    ],
    'resource' => 'Http/Resources',
    'form_request' => 'Http/Requests',
    'actions' => 'Actions',
    'docs' => 'Docs',
],

'tests' => [
    'feature' => 'tests/Feature',
],
```

Generated namespaces follow configured paths. If `dto` changes to `Data`, generated DTO namespaces and references change to `App\Data` as well.

### Defaults

[](#defaults)

```
'defaults' => [
    'with_controller' => true,
    'with_form_requests' => false,
    'with_unit_test' => true,
    'with_resource' => true,
    'with_dto' => true,
    'with_provider' => true,
    'with_actions' => false,
    'controller_middleware' => [],
    'controller_type' => 'api',
],
```

Because the default controller type is `api`, the default command also enables form requests and actions. Set `controller_type` to `web` when the project primarily generates web controllers.

Set the logging channel used by generated actions through:

```
MODULE_GENERATOR_LOG_CHANNEL=stack
```

Runtime APIs
------------

[](#runtime-apis)

Publishing the `module-generator` tag installs reusable base classes and `App\Helpers\ApiResponseHelper`. Generated modules extend or depend on these classes.

### Repository API

[](#repository-api)

Generated repositories extend `App\Repositories\Eloquent\BaseRepository` and implement a generated contract.

Core methods:

MethodResult`getAll()`Returns all records after applying criteria.`find($id)`Returns one model or `null`.`store($data)`Creates and returns a model.`update($id, $data)`Updates a model and returns a boolean.`delete($id)`Deletes a model and returns a boolean.`findDynamic(...)`Applies dynamic filters and returns the first result.`getByDynamic(...)`Applies dynamic filters and returns a collection.`pushCriteria($criteria)`Adds a query criterion.`popCriteria($criteria)`Removes a criterion by object or class.`skipCriteria()`Temporarily disables criteria.Dynamic queries support `where`, eager-loaded `with`, `whereNot`, `whereIn`, `whereNotIn`, between/null filters, equivalent `orWhere` filters, and raw expressions.

```
$products = $productRepository->getByDynamic(
    where: [['status', '=', 'active']],
    with: ['category'],
    whereIn: ['category_id', [1, 2, 3]],
    whereBetween: ['price', [100, 500]],
);

$product = $productRepository->findDynamic(
    where: [
        ['sku', '=', 'SKU-100'],
        ['is_active', '=', true],
    ],
);
```

Each condition accepts either one argument list, a list of argument lists, or an associative form supported by Laravel's query builder.

### Criteria Pattern

[](#criteria-pattern)

A criterion must expose `apply(Builder $query): Builder`. Implementing the published `CriteriaInterface` is recommended.

```
namespace App\Repositories\Criteria;

use Illuminate\Database\Eloquent\Builder;

final class ActiveProductsCriteria
{
    public function apply(Builder $query): Builder
    {
        return $query->where('is_active', true);
    }
}
```

```
$products = $productRepository
    ->pushCriteria(new ActiveProductsCriteria())
    ->getAll();

$productRepository->popCriteria(ActiveProductsCriteria::class);
$unfiltered = $productRepository->skipCriteria()->getAll();
```

Criteria may also be passed as class names with a parameterless constructor. The repository instantiates the class and uses its `apply()` method.

### Service API

[](#service-api)

Generated services wrap their repository and expose:

- `repository()`
- `index()` and `show($id)`
- `store($payload)`, `update($id, $payload)`, and `destroy($id)`
- `findDynamic(...)` and `getByDynamic(...)`
- repository method forwarding through `__call()`

When DTO generation is enabled, generated `store` and `update` methods accept the module DTO and convert it to an array. Otherwise they accept arrays.

```
use App\DTOs\ProductDTO;
use App\Services\ProductService;
use Illuminate\Http\Request;

public function store(Request $request, ProductService $service)
{
    $product = $service->store(ProductDTO::fromRequest($request));

    return response()->json($product, 201);
}
```

### DTO API

[](#dto-api)

Generated DTOs use promoted readonly properties inferred from schema metadata.

```
$dto = ProductDTO::fromRequest($request);

$dto->name;
$dto->price;
$payload = $dto->toArray(); // Omits null properties.
```

DTO inference maps integer casts to `?int`, booleans to `?bool`, numeric casts to `?float`, arrays/JSON to `?array`, and other values to `?string`.

### Action API

[](#action-api)

Generated CRUD actions are invokable and also expose `execute()`. Exceptions are logged through the configured channel and rethrown.

```
use App\Actions\Product\CreateProductAction;
use App\DTOs\ProductDTO;

public function store(Request $request, CreateProductAction $createProduct)
{
    $product = $createProduct(ProductDTO::fromRequest($request));

    return response()->json($product, 201);
}
```

Generated actions include list, list-with-relations, show, create, update, and delete operations.

### API Resources and Relations

[](#api-resources-and-relations)

Generated resources:

- Always include the model identifier.
- Format date/datetime attributes with `ApiResponseHelper::formatDates()`.
- Convert boolean/status attributes with `ApiResponseHelper::getStatus()`.
- Use `RelatedResource::collection()` for collection relations such as `hasMany` and `belongsToMany`.
- Use one resource instance for singular relations.

Load relations before returning the resource:

```
$product = $productService->getByDynamic(
    where: [['id', '=', $id]],
    with: ['category', 'tags'],
)->first();

return new ProductResource($product);
```

### API Response Helper

[](#api-response-helper)

The published `App\Helpers\ApiResponseHelper` provides:

```
use App\Helpers\ApiResponseHelper;

return ApiResponseHelper::successResponse($product, 'Product created', 201);
return ApiResponseHelper::errorResponse('Validation failed', 422, $errors);
return ApiResponseHelper::unauthorized();
return ApiResponseHelper::forbidden();
return ApiResponseHelper::notFound('Product not found');
```

Additional transformations:

```
ApiResponseHelper::formatDates(now());
// ['date' => '2026-06-18', 'time' => '...', 'fa_date' => '...', 'iso' => '...']

ApiResponseHelper::getStatus(true);
// ['name' => 'active', 'fa_name' => 'فعال', 'code' => 1]
```

`getCabinType()` is a domain-oriented convenience mapping included in the published helper and can be removed or customized after publishing.

### Enum Helper

[](#enum-helper)

Use `EnumHelperTrait` in backed enums to expose consistent English/Persian metadata. Define `faName()` when Persian labels are needed.

```
namespace App\Enums;

use Efati\ModuleGenerator\Enums\Concerns\EnumHelperTrait;

enum OrderStatus: string
{
    use EnumHelperTrait;

    case Pending = 'pending';
    case Paid = 'paid';

    public function faName(): string
    {
        return match ($this) {
            self::Pending => 'در انتظار',
            self::Paid => 'پرداخت‌شده',
        };
    }
}
```

```
OrderStatus::toList();
OrderStatus::toMap();
OrderStatus::findByValue('paid');
OrderStatus::findByName('Paid');
```

Each returned item contains `name`, `fa_name`, and `code`.

### Policies, Providers, and Tests

[](#policies-providers-and-tests)

- Generated policies contain standard model authorization methods and can be registered through normal Laravel policy discovery/configuration.
- Generated providers bind repository and service contracts to concrete classes and are inserted into `bootstrap/providers.php` or `config/app.php` when possible.
- Generated feature tests register an API resource route, infer payloads from factories/schema metadata, and cover CRUD behavior. Review generated payloads for domain-specific required data.

Swagger and OpenAPI
-------------------

[](#swagger-and-openapi)

The package contains two documentation paths:

1. `swagger:generate` creates an OpenAPI 3 JSON specification from Laravel routes.
2. `make:module --swagger` creates module PHPDoc annotations in the configured docs directory.

The JSON workflow is standalone and does not require `l5-swagger` or `swagger-php`.

### Standalone Workflow

[](#standalone-workflow)

```
# Copy the bundled UI to storage/swagger-ui
php artisan swagger:init

# Generate storage/swagger-ui/swagger.json
php artisan swagger:generate

# Serve the UI
php artisan swagger:ui
```

Open `http://localhost:8000` unless host or port configuration changes it.

Regenerate the specification before serving:

```
php artisan swagger:ui --refresh
```

### Swagger Commands

[](#swagger-commands)

```
# Initialize or overwrite UI assets
php artisan swagger:init
php artisan swagger:init --force

# Generate JSON from routes
php artisan swagger:generate
php artisan swagger:generate --title="Store API" --version=2.0.0
php artisan swagger:generate --host=https://api.example.com
php artisan swagger:generate --output=storage/swagger-ui/internal.json

# Run the standalone server
php artisan swagger:ui --host=localhost --port=8000

# Inspect or update UI configuration
php artisan swagger:config --show
php artisan swagger:config --theme=dark --primary-color=#8b5cf6
php artisan swagger:config --title="Store API"
php artisan swagger:config --export-env
php artisan swagger:config --reset
```

`make:swagger` is the legacy route-to-PHPDoc generator and remains available for backward compatibility:

```
php artisan make:swagger --force
php artisan make:swagger --path=api/v1
php artisan make:swagger --controller=App\\Http\\Controllers\\Api
php artisan make:swagger --output=app/Docs
```

Prefer `swagger:generate` for the built-in JSON UI workflow.

### Laravel Routes for the UI

[](#laravel-routes-for-the-ui)

To serve the initialized UI and JSON through the Laravel application, register controller routes explicitly:

```
use Efati\ModuleGenerator\Http\Controllers\SwaggerUIController;
use Illuminate\Support\Facades\Route;

Route::get('/api/docs', [SwaggerUIController::class, 'index']);
Route::get('/api/swagger.json', [SwaggerUIController::class, 'spec']);
```

Protect them with normal Laravel middleware when required:

```
Route::middleware('auth:sanctum')->group(function (): void {
    Route::get('/api/docs', [SwaggerUIController::class, 'index']);
    Route::get('/api/swagger.json', [SwaggerUIController::class, 'spec']);
});
```

The package also exposes `RegistersSwaggerRoutes` for applications that prefer a reusable registrar:

```
namespace App\Support;

use Efati\ModuleGenerator\Traits\RegistersSwaggerRoutes;

final class SwaggerRoutes
{
    use RegistersSwaggerRoutes;
}
```

```
use App\Support\SwaggerRoutes;

SwaggerRoutes::registerSwaggerRoutes();
```

This registers `/docs` and `/docs/swagger.json` in the current route context. Wrap the call in a prefixed/middleware route group when a different URL or protection is required.

When `SWAGGER_SECURE_SPEC=true`, the specification endpoint also checks configured authentication guards and returns `403` for anonymous requests.

### Swagger Environment Variables

[](#swagger-environment-variables)

```
SWAGGER_THEME=vanilla
SWAGGER_COLOR_PRIMARY=#3b82f6
SWAGGER_COLOR_PRIMARY_DARK=#1e40af
SWAGGER_COLOR_PRIMARY_LIGHT=#eff6ff
SWAGGER_COLOR_SECONDARY=#06b6d4
SWAGGER_FONT_FAMILY="system-ui, -apple-system, sans-serif"
SWAGGER_FONT_MONO="Fira Code, Courier New, monospace"
SWAGGER_DARK_MODE_ENABLED=true
SWAGGER_DARK_MODE_DEFAULT=auto
SWAGGER_DARK_MODE_PERSIST=true
SWAGGER_UI_TITLE="API Documentation"
SWAGGER_UI_DESCRIPTION="REST API Documentation"
SWAGGER_SHOW_MODELS=true
SWAGGER_SHOW_EXAMPLES=true
SWAGGER_PERSIST_AUTH=true
SWAGGER_SERVER_HOST=localhost
SWAGGER_SERVER_PORT=8000
SWAGGER_SPEC_PATH=storage/swagger-ui
SWAGGER_SPEC_FILENAME=swagger.json
SWAGGER_SECURE_SPEC=false
SWAGGER_AUTH_MIDDLEWARE="auth,auth:api,auth:sanctum"
```

Available themes are `vanilla`, `tailwind`, and `dark`. The UI assets and generated specification share `storage/swagger-ui` by default.

### Module PHPDoc Generation

[](#module-phpdoc-generation)

```
# Add documentation while generating the module
php artisan make:module Product --api --swagger

# Generate only the module documentation file
php artisan make:module Product --swagger
```

The output is compatible with optional OpenAPI annotation tooling, but external packages are not required for the built-in JSON workflow.

Jalali Dates
------------

[](#jalali-dates)

`Goli` provides Jalali/Gregorian conversion while wrapping Carbon. `Verta` extends `Goli` and retains legacy aliases for backward compatibility.

```
use Efati\ModuleGenerator\Support\Goli;
use Efati\ModuleGenerator\Support\Verta;

$date = Goli::now('Asia/Tehran');
$jalali = $date->toGoliDateString();
$jalaliWithTime = $date->toGoliDateTimeString();

$parsed = Goli::parseGoli('1403/01/01 08:30:00', 'Asia/Tehran');
$carbon = $parsed->toCarbon();

[$gy, $gm, $gd] = Goli::goliToGregorian(1403, 1, 1);
[$jy, $jm, $jd] = Goli::gregorianToGoli(2024, 3, 20);

$legacy = Verta::now();
$legacy->toJalaliDateString();
Verta::jalaliToGregorian(1403, 1, 1);
```

The global helper is also available:

```
$date = goli(now(), 'Asia/Tehran');
$same = goli_date(now());
```

Useful APIs include:

- `now()`, `parse()`, `parseGoli()`, `instance()`, `create()`, and `fromTimestamp()`
- `setGoliDate()`, `setGoliDateTime()`, `addDays()`, and `subDays()`
- `toGoliDateString()`, `toGoliDateTimeString()`, `toGoliArray()`
- `goliToGregorian()`, `gregorianToGoli()`, `isLeapGoliYear()`
- `diffForHumans()`, `format()`, `copy()`, `timezone()`, `toCarbon()`
- `persianNumbers()` and `latinNumbers()`

Invalid Gregorian dates, invalid Jalali month lengths, non-leap Esfand 30, and invalid time components throw `InvalidArgumentException`.

The package also includes `GoliDateCast` and `HasGoliDates` for Eloquent integration.

Use the cast directly:

```
use Efati\ModuleGenerator\Casts\GoliDateCast;

protected function casts(): array
{
    return [
        'published_at' => GoliDateCast::class,
    ];
}
```

Or configure multiple attributes through the trait:

```
use Efati\ModuleGenerator\Support\HasGoliDates;

class Post extends Model
{
    use HasGoliDates;

    protected array $goliDates = ['published_at', 'expires_at'];
}
```

Read values are `Goli` instances; assigned `Goli`, Carbon, date objects, timestamps, or parseable strings are stored using the model's Gregorian date format. Runtime casts can be added with `$model->addGoliDateCast('approved_at')`.

Testing
-------

[](#testing)

Install development dependencies and run:

```
composer install
composer test
```

Run syntax checks:

```
find src tests -name '*.php' -print0 | xargs -0 -n1 php -l
```

On Windows with the supplied PHP path:

```
Get-ChildItem src,tests -Recurse -Filter *.php |
  ForEach-Object { & 'C:\php-8.5\php.exe' -l $_.FullName }
```

The GitHub Actions PHP workflow validates supported PHP/Laravel combinations, lints source files, and runs PHPUnit.

Current focused tests cover:

- Jalali and Gregorian date validation.
- `diffForHumans()` behavior.
- legacy `Verta` compatibility.
- Swagger color palette generation and validation.

When changing generators, also test generated output inside a Laravel fixture and lint every generated PHP file.

Troubleshooting
---------------

[](#troubleshooting)

### Model Not Found

[](#model-not-found)

Create the model first or provide schema metadata:

```
php artisan make:model Product -m
php artisan make:module Product --api

# Or without a model
php artisan make:module Product --api --fields="name:string,price:decimal(10,2)"
```

### Existing Files Are Skipped

[](#existing-files-are-skipped)

Use `--force` only when overwriting is intended:

```
php artisan make:module Product --all --force
```

### Stub Not Found

[](#stub-not-found)

Republish stubs and clear application caches:

```
php artisan vendor:publish \
  --provider="Efati\ModuleGenerator\ModuleGeneratorServiceProvider" \
  --tag=module-generator-stubs \
  --force

php artisan optimize:clear
composer dump-autoload
```

### Provider Is Not Registered

[](#provider-is-not-registered)

Laravel 11 uses `bootstrap/providers.php`; older Laravel applications commonly use `config/app.php`. If automatic insertion is not possible, add the generated provider manually.

### Swagger UI Is Missing

[](#swagger-ui-is-missing)

```
php artisan swagger:init --force
php artisan swagger:generate
php artisan swagger:ui
```

Confirm that these files exist:

```
storage/swagger-ui/index.html
storage/swagger-ui/swagger.json

```

### Generated Tests Fail

[](#generated-tests-fail)

- Configure the test database in `.env.testing` or `phpunit.xml`.
- Ensure factories exist for required models.
- Run migrations before the suite.
- Check that route parameters match generated controller bindings.

### Custom Paths Produce Autoload Errors

[](#custom-paths-produce-autoload-errors)

Run `composer dump-autoload` after changing generated paths. Paths must remain under the application namespace configured by `base_namespace`.

Upgrading and Changelog
-----------------------

[](#upgrading-and-changelog)

The current release line is `7.x`. Before upgrading:

1. Review local changes in published configuration and stubs.
2. Update the package with Composer.
3. Republish configuration or stubs only when you intend to merge upstream changes.
4. Run `composer dump-autoload`, PHP lint, and the test suite.
5. Regenerate one representative module in a fixture before applying `--force` broadly.

```
composer update efati/laravel-scaffolder
php artisan vendor:publish \
  --provider="Efati\ModuleGenerator\ModuleGeneratorServiceProvider" \
  --tag=module-generator \
  --force
```

Notable `7.x` capabilities include the built-in standalone Swagger UI, route-based OpenAPI JSON generation, schema-aware module generation, action and policy generation, configurable namespaces, improved generated tests, strict date validation, and backward-compatible `Verta` aliases.

Git history and GitHub releases are the authoritative detailed changelog.

Contributing and Security
-------------------------

[](#contributing-and-security)

Contributions should remain focused, backward-compatible where practical, and covered by tests.

1. Fork the repository and create a focused branch.
2. Follow the existing PHP style and generator patterns.
3. Add or update tests for behavioral changes.
4. Run PHP lint and `composer test`.
5. Open a pull request describing behavior, generated output, and compatibility impact.

For bugs, include Laravel/PHP versions, the command used, relevant configuration, expected output, actual output, and a minimal reproduction.

Do not publish security vulnerabilities in public issues. Report them privately to the repository maintainer through GitHub security reporting or the contact method listed on the repository profile.

License
-------

[](#license)

Laravel Scaffolder is open-source software licensed under the MIT License. See `LICENSE`.

---

مستندات فارسی
-------------

[](#مستندات-فارسی)

Laravel Scaffolder یک پکیج قابل‌تنظیم برای تولید لایه‌های کامل یک قابلیت در پروژه‌های Laravel است. این پکیج Repository، Service، DTO، Action، Policy، Controller، FormRequest، API Resource، Provider، تست Feature و مستندات OpenAPI را تولید می‌کند.

### فهرست فارسی

[](#فهرست-فارسی)

- [نیازمندی‌ها و نصب](#%D9%86%DB%8C%D8%A7%D8%B2%D9%85%D9%86%D8%AF%DB%8C%D9%87%D8%A7-%D9%88-%D9%86%D8%B5%D8%A8)
- [شروع سریع](#%D8%B4%D8%B1%D9%88%D8%B9-%D8%B3%D8%B1%DB%8C%D8%B9-%D9%81%D8%A7%D8%B1%D8%B3%DB%8C)
- [فرمان تولید ماژول](#%D9%81%D8%B1%D9%85%D8%A7%D9%86-%D8%AA%D9%88%D9%84%DB%8C%D8%AF-%D9%85%D8%A7%DA%98%D9%88%D9%84)
- [تعریف Schema](#%D8%AA%D8%B9%D8%B1%DB%8C%D9%81-schema)
- [فایل‌ها و لایه‌های تولیدی](#%D9%81%D8%A7%DB%8C%D9%84%D9%87%D8%A7-%D9%88-%D9%84%D8%A7%DB%8C%D9%87%D9%87%D8%A7%DB%8C-%D8%AA%D9%88%D9%84%DB%8C%D8%AF%DB%8C)
- [تنظیمات](#%D8%AA%D9%86%D8%B8%DB%8C%D9%85%D8%A7%D8%AA-%D9%81%D8%A7%D8%B1%D8%B3%DB%8C)
- [APIهای زمان اجرا](#api%D9%87%D8%A7%DB%8C-%D8%B2%D9%85%D8%A7%D9%86-%D8%A7%D8%AC%D8%B1%D8%A7)
- [Swagger و OpenAPI](#swagger-%D9%88-openapi)
- [تاریخ جلالی](#%D8%AA%D8%A7%D8%B1%DB%8C%D8%AE-%D8%AC%D9%84%D8%A7%D9%84%DB%8C)
- [تست و رفع اشکال](#%D8%AA%D8%B3%D8%AA-%D9%88-%D8%B1%D9%81%D8%B9-%D8%A7%D8%B4%DA%A9%D8%A7%D9%84)
- [ارتقا، مشارکت و امنیت](#%D8%A7%D8%B1%D8%AA%D9%82%D8%A7-%D9%85%D8%B4%D8%A7%D8%B1%DA%A9%D8%AA-%D9%88-%D8%A7%D9%85%D9%86%DB%8C%D8%AA)

### نیازمندی‌ها و نصب

[](#نیازمندی‌ها-و-نصب)

- PHP نسخه `8.1` یا بالاتر در محدوده `^8.1`
- Laravel نسخه `10` یا `11`
- Composer 2

```
composer require efati/laravel-scaffolder
```

Provider پکیج با package discovery لاراول ثبت می‌شود. برای انتشار config، کلاس‌های پایه و helper پاسخ API:

```
php artisan vendor:publish \
  --provider="Efati\ModuleGenerator\ModuleGeneratorServiceProvider" \
  --tag=module-generator
```

برای انتشار stubها و شخصی‌سازی کد تولیدشده:

```
php artisan vendor:publish \
  --provider="Efati\ModuleGenerator\ModuleGeneratorServiceProvider" \
  --tag=module-generator-stubs
```

stubهای منتشرشده در `resources/stubs/module-generator` قرار می‌گیرند.

### شروع سریع فارسی

[](#شروع-سریع-فارسی)

در حالت عادی مدل Eloquent باید وجود داشته باشد:

```
php artisan make:model Product -m
php artisan make:module Product
```

برای تولید صریح ساختار API:

```
php artisan make:module Product --api
```

برای تولید تمام لایه‌ها:

```
php artisan make:module Product --all
```

برای جایگزینی فایل‌های موجود:

```
php artisan make:module Product --all --force
```

بدون مدل یا migration نیز می‌توان schema را مستقیم تعریف کرد:

```
php artisan make:module Product --api \
  --fields="name:string:unique,price:decimal(10,2),is_active:boolean,category_id:integer:fk=categories.id"
```

### فرمان تولید ماژول

[](#فرمان-تولید-ماژول)

```
php artisan make:module {name} [options]

```

گزینهنام کوتاهکاربرد`--controller=Subdir``-c`قرار دادن Controller در زیرمسیر دلخواه.`--api`—تولید Controller نوع API و فعال‌کردن Request و Action مگر اینکه غیرفعال شوند.`--requests``-r`تولید Store و Update FormRequest.`--tests``-t`فعال‌کردن تولید تست Feature.`--actions`—تولید Actionهای CRUD.`--policy`—تولید Policy.`--swagger``-sg`تولید مستندات PHPDoc/OpenAPI ماژول؛ اگر تنها گزینه باشد فقط فایل Swagger تولید می‌شود.`--all``-a`تولید تمام لایه‌ها.`--full``-f`معادل `--all`.`--from-migration=...``-fm`استخراج metadata از migration.`--fields=...`—تعریف schema داخل فرمان.`--force`—بازنویسی فایل‌های موجود.`--no-controller``-nc`عدم تولید Controller.`--no-resource``-nr`عدم تولید Resource.`--no-dto``-nd`عدم تولید DTO.`--no-test``-nt`عدم تولید تست.`--no-provider``-np`عدم تولید و ثبت Provider.`--no-actions`—عدم تولید Actionها.`--no-policy`—عدم تولید Policy.`--no-swagger`—عدم تولید مستندات Swagger.توجه: `--api` نام کوتاه ندارد. `-a` مربوط به `--all`، گزینه `-f` مربوط به `--full` و `--force` بدون نام کوتاه است.

نمونه‌های رایج:

```
# ماژول API با validation و Action
php artisan make:module Order --api

# Controller وب در مسیر دلخواه
php artisan make:module Invoice --controller=Admin/Accounting --no-actions

# تمام لایه‌ها
php artisan make:module Customer --all

# فقط فایل مستندات ماژول موجود
php artisan make:module Product --swagger

# Policy بدون Swagger
php artisan make:module Product --policy --no-swagger
```

### تعریف Schema

[](#تعریف-schema)

اطلاعات فیلدها به ترتیب از این منابع دریافت و ترکیب می‌شود:

1. گزینه `--fields`.
2. migration معرفی‌شده با `--from-migration`.
3. اطلاعات runtime مدل و ستون‌های دیتابیس.
4. مقادیر `$fillable` و castهای مدل.

فرمت هر فیلد:

```
name:type:modifier:modifier

```

فیلدها با کاما جدا می‌شوند؛ کامای داخل پرانتز مثل `decimal(10,2)` بخشی از type است.

typeهای رایج:

- `string`، `char`، `varchar`
- `text`، `mediumText`، `longText`
- `integer`، `bigInteger`، `foreignId`
- `decimal`، `numeric`، `float`، `double`
- `boolean`
- `date`، `datetime`، `timestamp`
- `json`، `array`
- `uuid`، `email`، `url`

modifierها:

- `nullable`، `null` یا `optional`
- `required`، `notnull` یا `not-null`
- `unique` یا `uniq`
- `fk=table.column`
- `foreign=table.column`
- `references=table.column`

```
php artisan make:module Subscription --api \
  --fields="tenant_id:integer:fk=tenants.id,plan:string,status:string,expires_at:datetime:nullable"

php artisan make:module Product --api \
  --fields="sku:string:unique,price:decimal(12,2),metadata:json:nullable"

php artisan make:module Product --api \
  --from-migration=create_products_table
```

نام تکراری، keyword رزروشده PHP و identifier نامعتبر باعث توقف generation می‌شود.

### فایل‌ها و لایه‌های تولیدی

[](#فایل‌ها-و-لایه‌های-تولیدی)

با توجه به گزینه‌ها و config، ساختاری مشابه زیر تولید می‌شود:

```
app/
├── Actions/Product/
├── DTOs/ProductDTO.php
├── Docs/ProductDoc.php
├── Http/Controllers/Api/V1/ProductController.php
├── Http/Requests/Product/
├── Http/Resources/ProductResource.php
├── Policies/ProductPolicy.php
├── Providers/ProductServiceProvider.php
├── Repositories/Contracts/ProductRepositoryInterface.php
├── Repositories/Eloquent/ProductRepository.php
├── Services/Contracts/ProductServiceInterface.php
└── Services/ProductService.php

tests/Feature/ProductTest.php

```

- **Repository:** دسترسی به داده و queryها.
- **Service:** منطق application و business.
- **DTO:** انتقال داده type-safe از Request.
- **Action:** عملیات کوچک و مستقل CRUD همراه logging خطا.
- **FormRequest:** validation تولیدشده از schema.
- **Resource:** تبدیل خروجی API، تاریخ، boolean و relationها.
- **Controller:** هماهنگ‌کردن لایه‌های API یا Web.
- **Provider:** binding رابط‌ها به کلاس‌های concrete.
- **Policy:** اسکلت authorization.
- **Feature Test:** تست اولیه CRUD.
- **Swagger Doc:** annotationهای OpenAPI مربوط به ماژول.

فایل موجود بدون `--force` بازنویسی نمی‌شود. اگر یک generator شکست بخورد، فرمان وضعیت failure برمی‌گرداند.

### تنظیمات فارسی

[](#تنظیمات-فارسی)

فایل اصلی تنظیمات پس از publish برابر `config/module-generator.php` است.

```
'base_namespace' => 'App',

'paths' => [
    'repository' => [
        'eloquent' => 'Repositories/Eloquent',
        'contracts' => 'Repositories/Contracts',
    ],
    'service' => [
        'concretes' => 'Services',
        'contracts' => 'Services/Contracts',
    ],
    'dto' => 'DTOs',
    'provider' => 'Providers',
    'controller' => [
        'api' => 'Http/Controllers/Api/V1',
        'web' => 'Http/Controllers',
    ],
    'resource' => 'Http/Resources',
    'form_request' => 'Http/Requests',
    'actions' => 'Actions',
    'docs' => 'Docs',
],

'tests' => [
    'feature' => 'tests/Feature',
],
```

namespace فایل‌های تولیدی با pathها هماهنگ می‌شود. برای مثال با تغییر `dto` به `Data`، namespace و importهای DTO نیز به `App\Data` تغییر می‌کنند.

```
'defaults' => [
    'with_controller' => true,
    'with_form_requests' => false,
    'with_unit_test' => true,
    'with_resource' => true,
    'with_dto' => true,
    'with_provider' => true,
    'with_actions' => false,
    'controller_middleware' => [],
    'controller_type' => 'api',
],
```

چون مقدار پیش‌فرض `controller_type` برابر `api` است، اجرای ساده فرمان نیز Request و Action را فعال می‌کند. برای پروژه‌های وب مقدار آن را `web` قرار دهید.

کانال log مربوط به Actionهای تولیدی:

```
MODULE_GENERATOR_LOG_CHANNEL=stack
```

### APIهای زمان اجرا

[](#apiهای-زمان-اجرا)

#### Repository

[](#repository)

Repositoryهای تولیدشده از `BaseRepository` ارث‌بری می‌کنند و این عملیات را دارند:

- `getAll()`، `find($id)`، `store($data)`، `update($id, $data)` و `delete($id)`
- `findDynamic(...)` برای دریافت اولین نتیجه
- `getByDynamic(...)` برای دریافت collection
- `pushCriteria()`، `popCriteria()` و `skipCriteria()`

فیلترهای پویا شامل `where`، `with`، `whereNot`، `whereIn`، `whereNotIn`، between، null، نسخه‌های `orWhere` و عبارت‌های raw هستند.

```
$products = $productRepository->getByDynamic(
    where: [['status', '=', 'active']],
    with: ['category'],
    whereIn: ['category_id', [1, 2, 3]],
    whereBetween: ['price', [100, 500]],
);

$product = $productRepository->findDynamic(
    where: [
        ['sku', '=', 'SKU-100'],
        ['is_active', '=', true],
    ],
);
```

#### Criteria

[](#criteria)

Criteria باید متد `apply(Builder $query): Builder` داشته باشد:

```
namespace App\Repositories\Criteria;

use Illuminate\Database\Eloquent\Builder;

final class ActiveProductsCriteria
{
    public function apply(Builder $query): Builder
    {
        return $query->where('is_active', true);
    }
}
```

```
$products = $productRepository
    ->pushCriteria(new ActiveProductsCriteria())
    ->getAll();

$productRepository->popCriteria(ActiveProductsCriteria::class);
$all = $productRepository->skipCriteria()->getAll();
```

#### Service و DTO

[](#service-و-dto)

Service عملیات `index`، `show`، `store`، `update`، `destroy` و queryهای پویا را به Repository متصل می‌کند. همچنین متدهای Repository از طریق `__call()` قابل forward شدن هستند.

در حالت فعال بودن DTO، متدهای store و update یک DTO دریافت می‌کنند:

```
use App\DTOs\ProductDTO;
use App\Services\ProductService;

$dto = ProductDTO::fromRequest($request);
$product = $productService->store($dto);

$dto->name;
$payload = $dto->toArray(); // مقادیر null حذف می‌شوند.
```

نوع propertyهای DTO از cast/schema استخراج می‌شود: integer به `?int`، boolean به `?bool`، numeric به `?float`، JSON/array به `?array` و سایر موارد به `?string`.

#### Action

[](#action)

Actionها invokable هستند و متد `execute()` نیز دارند. exception ثبت می‌شود و دوباره throw خواهد شد.

```
use App\Actions\Product\CreateProductAction;
use App\DTOs\ProductDTO;

public function store(Request $request, CreateProductAction $createProduct)
{
    $product = $createProduct(ProductDTO::fromRequest($request));

    return response()->json($product, 201);
}
```

Actionهای list، list-with-relations، show، create، update و delete تولید می‌شوند.

#### Resource و Relation

[](#resource-و-relation)

Resource تولیدشده:

- شناسه مدل را همیشه اضافه می‌کند.
- تاریخ‌ها را با `ApiResponseHelper::formatDates()` تبدیل می‌کند.
- فیلدهای boolean/status را با `getStatus()` نمایش می‌دهد.
- برای `hasMany` و `belongsToMany` از `RelatedResource::collection()` استفاده می‌کند.
- برای relation تکی یک Resource ایجاد می‌کند.

```
$product = $productService->getByDynamic(
    where: [['id', '=', $id]],
    with: ['category', 'tags'],
)->first();

return new ProductResource($product);
```

#### ApiResponseHelper

[](#apiresponsehelper)

```
use App\Helpers\ApiResponseHelper;

return ApiResponseHelper::successResponse($product, 'محصول ایجاد شد', 201);
return ApiResponseHelper::errorResponse('اعتبارسنجی ناموفق بود', 422, $errors);
return ApiResponseHelper::unauthorized();
return ApiResponseHelper::forbidden();
return ApiResponseHelper::notFound('محصول پیدا نشد');
```

```
ApiResponseHelper::formatDates(now());
// date, time, fa_date, iso

ApiResponseHelper::getStatus(true);
// ['name' => 'active', 'fa_name' => 'فعال', 'code' => 1]
```

متد `getCabinType()` یک mapping نمونه و domain-specific در helper منتشرشده است و می‌توان آن را حذف یا شخصی‌سازی کرد.

#### Enum Helper

[](#enum-helper-1)

برای enumهای backed می‌توان از `EnumHelperTrait` استفاده کرد:

```
namespace App\Enums;

use Efati\ModuleGenerator\Enums\Concerns\EnumHelperTrait;

enum OrderStatus: string
{
    use EnumHelperTrait;

    case Pending = 'pending';
    case Paid = 'paid';

    public function faName(): string
    {
        return match ($this) {
            self::Pending => 'در انتظار',
            self::Paid => 'پرداخت‌شده',
        };
    }
}
```

```
OrderStatus::toList();
OrderStatus::toMap();
OrderStatus::findByValue('paid');
OrderStatus::findByName('Paid');
```

هر خروجی شامل `name`، `fa_name` و `code` است.

#### Policy، Provider و تست تولیدی

[](#policy-provider-و-تست-تولیدی)

- Policy شامل متدهای استاندارد authorization مدل است.
- Provider رابط Repository و Service را bind کرده و در `bootstrap/providers.php` یا `config/app.php` ثبت می‌شود.
- تست Feature یک route نوع `apiResource` ثبت می‌کند، payload را از factory/schema می‌سازد و عملیات CRUD را پوشش می‌دهد. داده‌های domain-specific باید پس از generation بازبینی شوند.

### Swagger و OpenAPI

[](#swagger-و-openapi)

پکیج دو مسیر مستندسازی دارد:

1. فرمان `swagger:generate` که از routeهای Laravel فایل OpenAPI JSON می‌سازد.
2. گزینه `make:module --swagger` که فایل PHPDoc مربوط به ماژول را تولید می‌کند.

workflow اصلی بدون `l5-swagger` و `swagger-php` کار می‌کند:

```
php artisan swagger:init
php artisan swagger:generate
php artisan swagger:ui
```

آدرس پیش‌فرض سرور مستقل `http://localhost:8000` است.

```
# تولید مجدد spec قبل از اجرا
php artisan swagger:ui --refresh

# تنظیم host و port
php artisan swagger:ui --host=localhost --port=8080

# تنظیم metadata خروجی
php artisan swagger:generate --title="Store API" --version=2.0.0
php artisan swagger:generate --host=https://api.example.com
php artisan swagger:generate --output=storage/swagger-ui/internal.json
```

تنظیم UI:

```
php artisan swagger:config --show
php artisan swagger:config --theme=dark --primary-color=#8b5cf6
php artisan swagger:config --title="Store API"
php artisan swagger:config --export-env
php artisan swagger:config --reset
php artisan swagger:init --force
```

تم‌های موجود: `vanilla`، `tailwind` و `dark`.

مهم‌ترین متغیرهای env:

```
SWAGGER_THEME=vanilla
SWAGGER_COLOR_PRIMARY=#3b82f6
SWAGGER_COLOR_SECONDARY=#06b6d4
SWAGGER_UI_TITLE="API Documentation"
SWAGGER_UI_DESCRIPTION="REST API Documentation"
SWAGGER_SERVER_HOST=localhost
SWAGGER_SERVER_PORT=8000
SWAGGER_SPEC_PATH=storage/swagger-ui
SWAGGER_SPEC_FILENAME=swagger.json
SWAGGER_SECURE_SPEC=false
SWAGGER_PERSIST_AUTH=true
```

برای routeهای داخل خود Laravel:

```
use Efati\ModuleGenerator\Http\Controllers\SwaggerUIController;
use Illuminate\Support\Facades\Route;

Route::get('/api/docs', [SwaggerUIController::class, 'index']);
Route::get('/api/swagger.json', [SwaggerUIController::class, 'spec']);
```

یا registrar قابل استفاده مجدد:

```
namespace App\Support;

use Efati\ModuleGenerator\Traits\RegistersSwaggerRoutes;

final class SwaggerRoutes
{
    use RegistersSwaggerRoutes;
}
```

```
SwaggerRoutes::registerSwaggerRoutes();
```

این فراخوانی routeهای `/docs` و `/docs/swagger.json` را در context فعلی route ثبت می‌کند. برای prefix یا middleware دلخواه، آن را داخل route group فراخوانی کنید.

با `SWAGGER_SECURE_SPEC=true` endpoint فایل JSON guardهای تعریف‌شده authentication را بررسی می‌کند.

فرمان قدیمی `make:swagger` برای backward compatibility باقی مانده است، اما برای UI داخلی استفاده از `swagger:generate` پیشنهاد می‌شود:

```
php artisan make:swagger --force
php artisan make:swagger --path=api/v1
php artisan make:swagger --controller=App\\Http\\Controllers\\Api
php artisan make:swagger --output=app/Docs
```

### تاریخ جلالی

[](#تاریخ-جلالی)

کلاس `Goli` تبدیل جلالی/میلادی را روی Carbon فراهم می‌کند. کلاس `Verta` از `Goli` ارث‌بری کرده و aliasهای نسخه قدیمی را حفظ می‌کند.

```
use Efati\ModuleGenerator\Support\Goli;
use Efati\ModuleGenerator\Support\Verta;

$date = Goli::now('Asia/Tehran');
$date->toGoliDateString();
$date->toGoliDateTimeString();
$date->format('Y/m/d H:i', true);
$date->diffForHumans(persianDigits: true);

$parsed = Goli::parseGoli('1403/01/01 08:30:00', 'Asia/Tehran');
$carbon = $parsed->toCarbon();

[$gy, $gm, $gd] = Goli::goliToGregorian(1403, 1, 1);
[$jy, $jm, $jd] = Goli::gregorianToGoli(2024, 3, 20);

$legacy = Verta::now();
$legacy->toJalaliDateString();
Verta::jalaliToGregorian(1403, 1, 1);
```

helperها:

```
$date = goli(now(), 'Asia/Tehran');
$same = goli_date(now());
```

APIهای مهم:

- `now()`، `parse()`، `parseGoli()`، `instance()`، `create()` و `fromTimestamp()`
- `setGoliDate()`، `setGoliDateTime()`، `addDays()` و `subDays()`
- `toGoliDateString()`، `toGoliDateTimeString()`، `toGoliArray()`
- `format()`، `formatGregorian()`، `diffForHumans()` و `toCarbon()`
- `goliToGregorian()`، `gregorianToGoli()` و `isLeapGoliYear()`
- `persianNumbers()` و `latinNumbers()`

تاریخ میلادی نامعتبر، طول نامعتبر ماه جلالی، روز ۳۰ اسفند در سال غیرکبیسه و زمان نامعتبر exception ایجاد می‌کنند.

استفاده از cast:

```
use Efati\ModuleGenerator\Casts\GoliDateCast;

protected function casts(): array
{
    return [
        'published_at' => GoliDateCast::class,
    ];
}
```

استفاده از trait برای چند فیلد:

```
use Efati\ModuleGenerator\Support\HasGoliDates;

class Post extends Model
{
    use HasGoliDates;

    protected array $goliDates = ['published_at', 'expires_at'];
}
```

مقادیر خوانده‌شده نمونه `Goli` هستند و مقادیر ورودی با فرمت میلادی مدل ذخیره می‌شوند. در runtime نیز می‌توان نوشت:

```
$post->addGoliDateCast('approved_at');
```

### تست و رفع اشکال

[](#تست-و-رفع-اشکال)

```
composer install
composer test
```

lint در Linux یا داخل container:

```
find src tests -name '*.php' -print0 | xargs -0 -n1 php -l
```

در Windows:

```
Get-ChildItem src,tests -Recurse -Filter *.php |
  ForEach-Object { & 'C:\php-8.5\php.exe' -l $_.FullName }
```

workflow PHP در GitHub Actions نسخه‌های پشتیبانی‌شده PHP/Laravel را نصب، lint و PHPUnit را اجرا می‌کند.

مشکلات رایج:

- **Model پیدا نمی‌شود:** مدل را بسازید یا از `--fields`/`--from-migration` استفاده کنید.
- **فایل موجود skip می‌شود:** در صورت اطمینان `--force` اضافه کنید.
- **Stub پیدا نمی‌شود:** stubها را با `--force` دوباره publish کرده، `php artisan optimize:clear` و `composer dump-autoload` اجرا کنید.
- **Provider ثبت نشده:** Provider را دستی به `bootstrap/providers.php` یا `config/app.php` اضافه کنید.
- **Swagger UI وجود ندارد:** `swagger:init --force`، سپس `swagger:generate` و `swagger:ui` اجرا کنید.
- **تست تولیدی شکست می‌خورد:** دیتابیس تست، migrationها، factoryها و داده‌های اجباری domain را بررسی کنید.
- **namespace سفارشی autoload نمی‌شود:** `composer dump-autoload` اجرا کنید و مطمئن شوید path زیر namespace برنامه قرار دارد.

### ارتقا، مشارکت و امنیت

[](#ارتقا-مشارکت-و-امنیت)

نسخه فعلی در شاخه `7.x` است. برای ارتقا:

```
composer update efati/laravel-scaffolder
composer dump-autoload
composer test
```

قبل از publish مجدد config یا stubها، تغییرات محلی خود را بررسی کنید. ابتدا generation را روی یک fixture یا ماژول نمونه آزمایش کنید و سپس از `--force` در پروژه اصلی استفاده کنید.

برای مشارکت:

1. یک branch محدود و مشخص ایجاد کنید.
2. الگوی فعلی PHP و generatorها را رعایت کنید.
3. برای تغییرات رفتاری تست اضافه کنید.
4. lint و `composer test` را اجرا کنید.
5. در Pull Request اثر تغییر روی خروجی تولیدی و compatibility را توضیح دهید.

برای گزارش باگ، نسخه PHP/Laravel، فرمان اجراشده، config مرتبط، خروجی مورد انتظار، خروجی واقعی و نمونه بازتولید را ارسال کنید.

آسیب‌پذیری امنیتی را در Issue عمومی منتشر نکنید؛ از بخش Security Reporting گیت‌هاب یا راه ارتباطی خصوصی maintainer استفاده کنید.

این پروژه تحت مجوز MIT منتشر شده است. فایل `LICENSE` را ببینید.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance83

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 97.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

211d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/39827008?v=4)[Afshin](/maintainers/AfshinEfati)[@AfshinEfati](https://github.com/AfshinEfati)

---

Top Contributors

[![AfshinEfati](https://avatars.githubusercontent.com/u/39827008?v=4)](https://github.com/AfshinEfati "AfshinEfati (288 commits)")[![google-labs-jules[bot]](https://avatars.githubusercontent.com/in/842251?v=4)](https://github.com/google-labs-jules[bot] "google-labs-jules[bot] (8 commits)")

---

Tags

laravellaravel-packagerepository-patternservicelaravelgeneratorscaffoldservicecrudrepositorydtoPolicyscaffolder

### Embed Badge

![Health badge](/badges/efati-laravel-scaffolder/health.svg)

```
[![Health](https://phpackages.com/badges/efati-laravel-scaffolder/health.svg)](https://phpackages.com/packages/efati-laravel-scaffolder)
```

###  Alternatives

[backpack/crud

Quickly build admin interfaces using Laravel, Bootstrap and JavaScript.

3.4k3.7M223](/packages/backpack-crud)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
