Pular para o conteúdo principal

Code Generator

The code generator creates PHP classes based on your database tables, dramatically speeding up development.

What It Generates​

The code generator supports two architectural patterns:

Repository Pattern (Default)​

  • Model - PHP class with properties matching table columns
  • Repository - Data access layer with ORM integration
  • Service - Business logic layer extending BaseService
  • REST API - Complete CRUD endpoints (GET, POST, PUT)
  • Functional Tests - Test suite for the CRUD API
  • Config - Automatic DI bindings (added automatically with --save)

ActiveRecord Pattern (with --activerecord)​

  • Model - PHP class with properties and ActiveRecord trait for direct database operations
  • REST API - Complete CRUD endpoints (GET, POST, PUT)
  • Functional Tests - Test suite for the CRUD API

The delete endpoint is not generated; write it by hand where the entity needs one.

The generated routes are GET /{table}/{id}, GET /{table}, POST /{table} and PUT /{table}/{id}. POST and PUT take the same body, the writable fields; the key is generated on POST and taken from the path on PUT, so a key sent in the body is refused.

From columns to the OpenAPI schema​

Each column becomes an OA\Property on the model and in the request body of POST and PUT. That schema is what #[ValidateRequest] enforces on the request (400 on failure), what the model is checked against on every save() (see below), and what the API docs publish:

ColumnGenerated
int, bigint, decimal, date, datetime, ...type and format
NULL allowednullable: true
NOT NULLlisted in required
char(N) / varchar(N)maxLength: N
NOT NULL text (char, varchar, text) with no defaultminLength: 1: an empty string is refused like a missing value
primary key (auto-increment, or a UUID seeded by TableUuidPKAttribute), virtual generated columnreadOnly: true: the server generates it; the API returns it and does not take it

Value ranges (minimum, maximum) cannot be read from a column type; add them by hand.

The model's table attribute also declares validator: SchemaValidator::class. The model is then checked against its own schema every time it is saved, not only when a request comes in: a command line script, a queue consumer or a service that saves it gets the same 400. A readOnly property, such as the generated key, is not required for that check. Writes that do not go through save() (UpdateQuery, InsertBulkQuery, raw SQL) are not checked. See OpenAPI Integration.

The generated functional test also sends invalid bodies straight to the server, on POST and on PUT: the key in the body, the required fields missing, and an empty value for each minLength column. It expects 400. They are sent without the OpenAPI spec on the client side, so the test client does not stop them first.

Usage​

APP_ENV=<environment> php gluo codegen:<component> --table=<table_name> [options]
php gluo --env=<environment> codegen:<component> --table=<table_name> [options]

Required​

  • --table=<name> - Database table name

Environment​

You can specify the environment in two ways:

  • Set the APP_ENV environment variable
  • Use the --env=<environment> parameter (overrides APP_ENV)

Note: At least one method must be used to specify the environment (dev, test, prod).

Arguments (at least one required)​

ArgumentDescriptionRepository PatternActiveRecord Pattern
allGenerate all components✓ All components✓ Model, Controller, Test
modelGenerate Model✓✓ (with ActiveRecord trait)
repo or repositoryGenerate Repository✓✗ Not applicable
serviceGenerate Service✓✗ Not applicable
controllerGenerate REST controller✓✓
testGenerate Test✓✓

Options​

  • --activerecord - Use ActiveRecord pattern instead of a Repository pattern
  • --save - Save generated files to disk (otherwise prints to console)
  • --debug - Show debug information

Examples​

The commands below run from the repository root, which is also the PHP application root. Generated files land under src/ (model, repository, service, controller), tests/ (the functional test) and config/ (the DI bindings, with --save).

Repository Pattern (Default)​

Generate all components for the project table using the Repository pattern:

# Using APP_ENV
APP_ENV=dev php gluo codegen:all --table=project --save

# Using --env parameter
php gluo --env=dev codegen:all --table=project --save

This creates:

  • src/Model/Project.php
  • src/Repository/ProjectRepository.php
  • src/Service/ProjectService.php
  • src/Controller/ProjectController.php
  • tests/Controller/ProjectTest.php
  • Automatically adds DI bindings to config/dev/04-repositories.php and config/dev/05-services.php

Generate only specific components:

APP_ENV=dev php gluo codegen --table=project model controller --save

ActiveRecord Pattern​

Generate all components for the note table using the ActiveRecord pattern:

# Using APP_ENV
APP_ENV=test php gluo codegen:all --table=note --activerecord --save

# Using --env parameter
php gluo --env=test codegen:all --table=note --activerecord --save

This creates:

  • src/Model/Note.php (with ActiveRecord trait)
  • src/Controller/NoteController.php
  • tests/Controller/NoteTest.php

Generate only the model:

APP_ENV=test php gluo codegen:model --table=note --activerecord --save

Preview Without Saving​

Preview the generated REST controller without saving to disk:

APP_ENV=dev php gluo codegen:controller --table=project
php gluo --env=dev codegen:all --table=note --activerecord

Automatic Configuration​

Automatic DI Bindings (Repository Pattern Only)

When using --save with the Repository pattern, repository and service bindings are automatically added to the configuration files:

  • Repositories → config/dev/04-repositories.php
  • Services → config/dev/05-services.php

No manual configuration needed!

Note: ActiveRecord pattern does not require DI bindings since models use the ActiveRecord trait for direct database access.

Example output:

Processing Repository for table project...
File saved in src/Repository/ProjectRepository.php
Added use statement for ProjectRepository to 04-repositories.php
Added DI binding for ProjectRepository to 04-repositories.php

Important Notes​

Overwriting Files

Using --save will overwrite existing files without warning. Be careful when regenerating files you've customized.

After Generation

After generating REST controllers, remember to:

  1. Run php gluo openapi to update the OpenAPI specification
  2. Run php gluo test to verify the generated tests pass

Customizing Templates​

You can modify existing templates or create your own. The default templates ship inside byjg/gluo-core (vendor/byjg/gluo-core/templates/codegen/) and use the Jinja template engine for PHP. To customize, copy them into your project — a local templates/codegen/ directory takes precedence over the package templates:

mkdir -p templates/codegen
cp -r vendor/byjg/gluo-core/templates/codegen/* templates/codegen/

Available templates:

Repository Pattern:

  • model.php.jinja - Model class template
  • repository.php.jinja - Repository class template
  • service.php.jinja - Service class template
  • controller.php.jinja - REST controller template
  • test.php.jinja - Test class template

ActiveRecord Pattern:

  • model.php.jinja - Same model template; the activerecord variable switches it to the ActiveRecord trait
  • controlleractiverecord.php.jinja - REST controller for ActiveRecord template
  • Uses the same test.php.jinja template as a Repository pattern

Template variables available (see Template Customization for the full field-level reference):

  • className - PascalCase class name (e.g., UserProfile)
  • tableName - Original table name (e.g., user_profile)
  • varTableName - camelCase variable name (e.g., userProfile)
  • restPath / restTag - REST route path (e.g., user/profile) and OpenAPI tag
  • namespace - Project namespace
  • fields - Array of table columns (keys: field, property, type, php_type, openapi_type, openapi_format, openapi_max_length, null, key, default, extra)
  • primaryKeys - Array of primary key column names
  • nullableFields / nonNullableFields - camelCase property lists
  • indexes - Table indexes (with camelColumnName)
  • autoIncrement - "yes" when the PK auto-increments
  • activerecord - True in ActiveRecord mode
  • hasCreatedAt / hasUpdatedAt / hasDeletedAt - Timestamp-trait switches