dcardenasl/ci4-api-scaffolding
Composer 安装命令:
composer require dcardenasl/ci4-api-scaffolding
包简介
CRUD scaffolding engine for CodeIgniter 4 APIs built on dcardenasl/ci4-api-core. Generates DTOs, services, controllers, migrations, routes, tests and OpenAPI docs via spark commands.
关键字:
README 文档
README
CRUD scaffolding engine for CodeIgniter 4 APIs built on dcardenasl/ci4-api-core. One command generates DTOs, service, controller, migration, routes, language files, and tests — all wired to the ci4-api-core base classes.
Pre-1.0 policy: MINOR bumps may contain breaking changes. Pin to
~0.x.0or exact version until v1.0.0.
Table of Contents
- Requirements
- Installation
- Quick Start
- Configuration
- Available Commands
- Field Types
- Field Modifiers
- Generated Artifacts
- Scaffolding Boundaries
- Compatibility Matrix
- Development
- Troubleshooting
- Example Project
Requirements
- PHP
^8.2 - CodeIgniter 4
^4.7 dcardenasl/ci4-api-core^0.9(installed automatically as a dependency)
Installation
composer require --dev dcardenasl/ci4-api-scaffolding:^0.7
Quick Start
bash vendor/bin/make-crud.sh Article Blog \
'title:string:required|searchable,body:text:required,published:bool:nullable' yes
php spark module:check Article --domain Blog
php spark migrate
Configuration
Create app/Config/Scaffolding.php extending BaseScaffoldingConfig. If your project follows ci4-api-starter conventions, the bundled defaults work without any overrides:
<?php declare(strict_types=1); namespace Config; use dcardenasl\Ci4ApiScaffolding\Config\BaseScaffoldingConfig; use dcardenasl\Ci4ApiScaffolding\Config\ScaffoldingConfig; class Scaffolding extends BaseScaffoldingConfig { public function build(): ScaffoldingConfig { return ScaffoldingConfig::defaults(); } }
To customize base classes, paths, or route filters, pass named arguments to ScaffoldingConfig:
use dcardenasl\Ci4ApiScaffolding\Config\BaseScaffoldingConfig; use dcardenasl\Ci4ApiScaffolding\Config\ScaffoldingConfig; use dcardenasl\Ci4ApiScaffolding\Config\ScaffoldingPaths; class Scaffolding extends BaseScaffoldingConfig { public function build(): ScaffoldingConfig { $defaults = ScaffoldingConfig::defaults(); return new ScaffoldingConfig( ...(array) $defaults, // Lock new routes behind a custom permission instead of the default // superadmin-only gate: protectedRouteFilters: ['jwtauth', 'permission:catalog.admin', 'throttle'], // Override where generated controllers are written: paths: new ScaffoldingPaths(controllers: 'Controllers/Api/V2'), ); } }
Default route filters (when no Scaffolding config is found): ['jwtauth', 'permission:iam.superadmin-access', 'throttle']. New resources are unreachable by non-superadmins until you intentionally loosen this filter.
All configurable options (ScaffoldingConfig constructor parameters):
| Option | Default | Purpose |
|---|---|---|
controllerBaseClass |
dcardenasl\Ci4ApiCore\Http\ApiController |
Base class generated controllers extend |
serviceBaseClass |
dcardenasl\Ci4ApiCore\Services\BaseCrudService |
Base class generated services extend |
requestDtoBaseClass |
dcardenasl\Ci4ApiCore\Dto\BaseRequestDTO |
Base class generated request DTOs extend |
responseDtoInterface |
dcardenasl\Ci4ApiCore\Dto\DataTransferObjectInterface |
Interface response DTOs implement |
modelBaseClass |
dcardenasl\Ci4ApiCore\Models\BaseAuditableModel |
Base class generated models extend |
protectedRouteFilters |
['jwtauth', 'permission:iam.superadmin-access', 'throttle'] |
Filters on the protected route group |
appNamespace |
App |
Top-level namespace of the consumer app |
paths |
ScaffoldingPaths::defaults() |
All output directories (see ScaffoldingPaths) |
openApiTagPrefix |
null (uses domain name) |
Custom OpenAPI tag prefix |
conditionalControllerTraits |
[] |
fieldName => TraitFQCN map for auto-injected controller traits |
Path overrides (ScaffoldingPaths constructor parameters, all relative to APPPATH):
| Option | Default |
|---|---|
controllers |
Controllers/Api/V1 |
services |
Services |
interfaces |
Interfaces |
requestDtos |
DTO/Request |
responseDtos |
DTO/Response |
models |
Models |
entities |
Entities |
migrations |
Database/Migrations |
routes |
Config/Routes/v1 |
documentation |
Documentation |
languageEn |
Language/en |
languageEs |
Language/es |
unitTests |
tests/Unit/Services (relative to ROOTPATH) |
integrationTests |
tests/Integration/Models (relative to ROOTPATH) |
featureTests |
tests/Feature/Controllers (relative to ROOTPATH) |
Available Commands
| Command | Shell wrapper | Description |
|---|---|---|
php spark make:crud |
bash vendor/bin/make-crud.sh |
Generate a full CRUD module |
php spark make:crud:remove |
— | Remove a previously scaffolded module |
php spark module:check |
bash vendor/bin/validate-crud.sh |
Validate 14 post-scaffold wiring checkpoints |
php spark scaffold:check |
— | Verify Config\Scaffolding exists and all FQCNs resolve |
php spark swagger:generate |
— | Generate public/swagger.json from OpenAPI annotations |
Always use
vendor/bin/make-crud.shin non-TTY environments (CI, Claude Code, scripts).php spark make:crudfalls back to interactive mode when--fieldsis not provided, which hangs in non-TTY contexts.
make:crud — full options
# Shell wrapper (recommended for scripts and CI) bash vendor/bin/make-crud.sh <Resource> <Domain> '<fields>' [softDelete=yes] [route] [--dry-run] [--no-wire] [--migrate] # Direct spark command (TTY only) php spark make:crud <Resource> \ [--domain <Domain>] \ [--fields '<fields>'] \ [--route <route-slug>] \ [--soft-delete yes|no] \ [--dry-run] \ [--no-wire] \ [--skip-fk-validation]
| Option | Default | Purpose |
|---|---|---|
--domain / arg 2 |
Catalog |
Domain folder (groups related resources) |
--fields / arg 3 |
interactive | Field definition string (see Field Types) |
--route / arg 5 |
kebab-case plural of resource | Route slug used in the URL |
--soft-delete / arg 4 |
yes |
Emit deleted_at column and soft-delete logic |
--version |
v1 |
Target a versioned route directory (e.g. --version v2 writes routes to Config/Routes/v2/) |
--dry-run |
off | Preview planned files and wiring without writing anything |
--no-wire |
off | Generate files but skip Services.php injection; prints snippets to paste manually |
--skip-fk-validation |
off | Skip the FK target existence check when the database is unreachable |
--migrate (wrapper only) |
off | Auto-run php spark migrate after scaffolding |
make:crud:remove — full options
php spark make:crud:remove <Resource> [--domain <Domain>] [--force]
--force skips the confirmation prompt (useful in CI). Without --force, the command lists the files it would delete and asks for confirmation.
module:check / validate-crud.sh
# Via spark (inside consumer project) php spark module:check <Resource> --domain <Domain> # Via shell wrapper bash vendor/bin/validate-crud.sh <Resource> <Domain>
Validates 14 post-scaffold wiring checkpoints: migration exists, table naming, soft-delete consistency, controller/model/service/route presence, Services.php wiring, language files, test files. Exits non-zero if any checkpoint fails.
scaffold:check
php spark scaffold:check
Read-only diagnostic — never writes files. Verifies that app/Config/Scaffolding.php exists, extends BaseScaffoldingConfig, and that all 14 FQCNs it declares (base classes, interfaces, traits) are loadable. Run after first install or after bumping dcardenasl/ci4-api-core to confirm the config still points at real classes.
If the file is missing, the command prints the cp command to bootstrap a default config from the bundled example.
swagger:generate
php spark swagger:generate
Generates public/swagger.json from OpenAPI annotations. Scans app/Config/OpenApi.php, app/Controllers/, app/Documentation/, app/DTO/, and vendor/dcardenasl/ci4-api-core/src/Dto/ by default. Requires zircote/swagger-php in the consumer's require-dev:
composer require --dev zircote/swagger-php
To scan additional directories, subclass the command and override scanPaths():
class MySwaggerGenerate extends \dcardenasl\Ci4ApiScaffolding\Commands\SwaggerGenerate { protected function scanPaths(): array { return [...parent::scanPaths(), APPPATH . 'Modules/']; } }
Field Types
Field type codes used in the --fields string. All types are recognized case-sensitively.
| Type | Alias | PHP type | DB column | OpenAPI | Validation (auto-added) |
|---|---|---|---|---|---|
string |
— | string |
VARCHAR(255) |
string |
string|max_length[255] |
text |
— | string |
TEXT |
string |
string |
int |
integer |
int |
INT |
integer |
integer |
decimal |
— | float |
DECIMAL(10,2) |
number (float) |
decimal |
bool |
— | bool |
TINYINT(1) |
boolean |
boolean_like |
email |
— | string |
VARCHAR(255) |
string (email) |
string|valid_email|max_length[255] |
date |
— | string |
DATE |
string (date) |
valid_date[Y-m-d] |
datetime |
— | string |
DATETIME |
string (date-time) |
valid_date |
json |
— | array |
JSON |
object |
permit_empty |
fk |
relation |
int |
INT + FK constraint |
integer |
is_natural_no_zero|is_not_unique[table.id] |
FK field syntax — uses a 4-segment form because the target table name is a required third segment:
author_id:fk:users:required
category_id:fk:categories:required|filterable
category_id:relation:categories:required|filterable
Field Modifiers
Modifiers follow the type (or the FK table) and are separated by |:
name:type:modifier1|modifier2
name:fk:target_table:modifier1|modifier2
name:relation:target_table:modifier1|modifier2
| Modifier | Effect |
|---|---|
required |
required validation rule; non-nullable column |
nullable |
Nullable column; permit_empty validation rule |
searchable |
Adds FULLTEXT index; controller gets HasSearchableIndex trait |
filterable |
Adds field to the model's $filterableFields whitelist |
unique |
Adds UNIQUE index + is_unique[table.column] validation |
index |
Adds a plain (non-unique) index |
cascade |
FK/relation only — ON DELETE CASCADE (default for fk and relation fields) |
restrict |
FK/relation only — ON DELETE RESTRICT |
setnull |
FK/relation only — ON DELETE SET NULL |
Full example:
'title:string:required|searchable,price:decimal:required|filterable,author_id:fk:users:required|restrict'
Boolean validation contract — bool currently maps to boolean_like, which is part of the supported starter contract (ci4-api-starter and ci4-domain-starter both ship and register that custom rule). If a non-starter consumer uses this package, it must expose an equivalent boolean_like validation rule or adapt the generated rule set after scaffolding.
Generated Artifacts
make:crud Article Blog 'title:string:required' yes creates 17 files:
app/DTO/Request/Blog/ArticleIndexRequestDTO.php
app/DTO/Request/Blog/ArticleCreateRequestDTO.php
app/DTO/Request/Blog/ArticleUpdateRequestDTO.php
app/DTO/Response/Blog/ArticleResponseDTO.php
app/Database/Migrations/<timestamp>_CreateArticlesTable.php
app/Entities/ArticleEntity.php
app/Models/ArticleModel.php
app/Interfaces/Blog/ArticleServiceInterface.php
app/Services/Blog/ArticleService.php
app/Controllers/Api/V1/Blog/ArticleController.php
app/Documentation/Blog/ArticleEndpoints.php
app/Config/Routes/v1/blog.php
app/Language/en/Articles.php
app/Language/es/Articles.php
tests/Unit/Services/Blog/ArticleServiceTest.php
tests/Integration/Models/ArticleModelTest.php
tests/Feature/Controllers/Blog/ArticleControllerTest.php
Services.php is also updated (or a snippet is printed with --no-wire) to register the new service and response mapper.
Scaffolding Boundaries
make:crud is designed for flat CRUD resources. It gives you a correct starting module for entities that behave like:
- one primary table
- standard list/show/create/update/delete
- scalar fields and conventional foreign keys
- standard DTO/model/controller/service wiring
It is not a full aggregate generator. If your resource needs any of the following, expect manual extension after scaffolding:
- custom workflow actions such as
publish,archive,approve - nested sub-resources such as
/items/{id}/media - relation arrays in payloads such as
tag_ids[]or embeddedmedia[] - pivot tables with composite primary keys and no synthetic
id - cross-field invariants such as "if
is_for_sale=true, thenpriceandcurrencyare required" - response enrichment that joins child collections or computed data
Practical rule:
- use
make:crudto establish the module skeleton and conventions - then evolve the generated service/controller/routes into an aggregate by hand
The scaffolder is successful when it removes boilerplate and preserves architectural consistency. It is not trying to replace domain modeling for complex aggregates.
CSV export/import is intentionally outside the upstream API scaffold contract. In this workspace, that admin-facing bulk workflow lives in ci4-admin-starter, where the generator can align the export route with the current index filters and surface import validation in the admin UI.
Compatibility Matrix
| PHP 8.2 | PHP 8.3 | PHP 8.4 | |
|---|---|---|---|
| CI4 4.7.* | ✅ | ✅ | ✅* |
* PHP 8.4 is tested against the locked CI4 version in the test job. The explicit CI4-compatibility matrix covers PHP 8.2 and 8.3. CI4 4.5.x and 4.6.x were dropped: 4.5.x for security advisories, 4.6.x because v0.3.2 widened the floor to ^4.7.
CI runs on every push: PHPStan level 8, PHP CS Fixer, full unit suite, E2E smoke test (creates a real CI4 project and scaffolds into it). PHP 8.2 additionally collects coverage.
Development
# Run all quality checks composer quality # PHPStan level 8 + PHPUnit + CS-Fixer + security audit # Run tests only composer test -- --testsuite Unit composer test -- --testsuite E2E # Run E2E smoke test against a real vanilla CI4 project CI4_CORE_PATH=../ci4-api-core bash bin/e2e-smoke.sh # Auto-fix code style composer cs-fix
For architecture constraints that generated code must satisfy, see docs/ARCHITECTURE_CONTRACT.md.
Troubleshooting
--fields is empty / scaffold produces a partial module
Always single-quote the fields string. Unquoted pipes (|) are consumed by the shell before the command sees them:
# Wrong — shell eats the pipe bash vendor/bin/make-crud.sh Article Blog title:string:required|searchable yes # Correct bash vendor/bin/make-crud.sh Article Blog 'title:string:required|searchable' yes
php spark make:crud hangs in a script / CI
It entered interactive mode because --fields was empty and stdin is not a TTY. Use vendor/bin/make-crud.sh instead, which guards against this and requires --fields in non-TTY contexts.
Wiring failed / Services.php was not modified
The ConfigWireman uses AST-based injection and expects Services.php to follow the CI4 convention (a class with static factory methods in a trait). Run with --no-wire to get the snippet to paste manually:
php spark make:crud Article --domain Blog --fields '...' --no-wire
FK validation aborts because the DB is unreachable
Pass --skip-fk-validation when you know the target tables exist but the DB isn't available (e.g. in a fresh setup before migrate):
php spark make:crud Article --domain Blog --fields 'author_id:fk:users:required' --skip-fk-validation
Scaffolded routes don't appear in php spark routes:list
New route files are not hot-reloaded. Restart the server after scaffolding:
pkill -f 'spark serve'; php spark serve --port 8080 &
module:check fails on a valid module
Run php spark module:check <Resource> --domain <Domain> to see which of the 14 checkpoints failed and why.
Example Project
ci4-api-core-example is a complete, runnable Catalog API (Categories + Products) built entirely with this scaffolding engine — minimal hand-written code. Each step is a separate git commit so you can trace exactly what make-crud.sh generates, from a blank CI4 project to a production-ready API with filtering, searching, pagination, and OpenAPI docs.
License
MIT — see LICENSE.
dcardenasl/ci4-api-scaffolding 适用场景与选型建议
dcardenasl/ci4-api-scaffolding 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 844 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 05 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「generator」 「codeigniter」 「crud」 「scaffolding」 「spark」 「dto」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 dcardenasl/ci4-api-scaffolding 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 dcardenasl/ci4-api-scaffolding 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 dcardenasl/ci4-api-scaffolding 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Memio's PrettyPrinter, used to generate PHP code from given Model
Gii Generator for double model generation
The CodeIgniter Redis package
A PSR-7 compatible library for making CRUD API endpoints
Admin panel generator for Laravel 8 and based on Vuetify Admin, a separate SPA admin framework running on top of REST APIs.
统计信息
- 总下载量: 844
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 50
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-10