CLI Overview
Quick Start Guide
wheels info
wheels reload
wheels deps
wheels destroy
wheels watch
wheels generate app
wheels generate app-wizard
wheels generate controller
wheels generate model
wheels generate view
wheels generate property
wheels generate route
wheels generate resource
wheels generate api-resource
wheels generate frontend
wheels generate test
wheels generate snippets
wheels scaffold
wheels db create
wheels db drop
wheels db setup
wheels db reset
wheels db status
wheels db version
wheels db rollback
wheels db seed
wheels db dump
wheels db restore
wheels db shell
wheels db schema
wheels dbmigrate info
wheels dbmigrate latest
wheels dbmigrate up
wheels dbmigrate down
wheels dbmigrate reset
wheels dbmigrate exec
wheels dbmigrate create blank
wheels dbmigrate create table
wheels dbmigrate create column
wheels dbmigrate remove table
wheels test
wheels test run
wheels test coverage
wheels test debug
wheels config list
wheels config set
wheels config env
wheels env
wheels env setup
wheels env list
wheels env switch
wheels environment
wheels console
wheels runner
wheels server
wheels server start
wheels server stop
wheels server restart
wheels server status
wheels server log
wheels server open
wheels plugins
wheels plugins list
wheels plugins install
wheels plugins remove
wheels analyze
wheels analyze code
wheels analyze performance
wheels analyze security
wheels security
wheels security scan
wheels optimize
wheels optimize performance
wheels docs
wheels docs generate
wheels docs serve
wheels ci init
wheels docker init
wheels docker deploy
wheels deploy
wheels deploy audit
wheels deploy exec
wheels deploy hooks
wheels deploy init
wheels deploy lock
wheels deploy logs
wheels deploy proxy
wheels deploy push
wheels deploy rollback
wheels deploy secrets
wheels deploy setup
wheels deploy status
wheels deploy stop
Configuration Management
Creating Commands
Service Architecture
Migrations Guide
Testing Guide
Object Relational Mapping
Creating Records
Reading Records
Updating Records
Deleting Records
Column Statistics
Dynamic Finders
Getting Paginated Data
Associations
Nested Properties
Object Validation
Object Callbacks
Calculated Properties
Transactions
Dirty Records
Soft Delete
Automatic Time Stamps
Using Multiple Data Sources
wheels scaffold
This command works correctly without options (parameters). Option support is under development and will be available soon.
Generate complete CRUD scaffolding for a resource.
Synopsis
wheels generate scaffold name=[resourceName] [options]
Alias
wheels g scaffold name=[resourceName] [options]
Description
The wheels scaffold
command generates a complete CRUD (Create, Read, Update, Delete) implementation including model, controller, views, tests, and database migration. It's the fastest way to create a fully functional resource.
Arguments
| Argument | Description | Default |
|----------|-------------|---------|
| name
| Resource name (singular) | Required |
Options
| Option | Description | Default |
|--------|-------------|---------|
| properties
| Model properties (format: name:type,name2:type2) | |
| belongs-to
| Parent model relationships (comma-separated) | |
| has-many
| Child model relationships (comma-separated) | |
| --api
| Generate API-only scaffold (no views) | false
|
| --tests
| Generate test files | true
|
| --migrate
| Run migrations after scaffolding | false
|
| --force
| Overwrite existing files | false
|
Examples
Basic scaffold
wheels generate scaffold name=product
Scaffold with properties
wheels generate scaffold name=product properties=name:string,price:decimal,stock:integer
Scaffold with associations
wheels scaffold name=order properties=total:decimal,status:string \
belongsTo=user hasMany=orderItems
API scaffold
wheels generate scaffold name=product api=true properties=name:string,price:decimal
Scaffold with auto-migration
wheels generate scaffold name=category properties=name:string migrate=true
What Gets Generated
Standard Scaffold
-
Model (
/models/Product.cfc
)- Properties and validations
- Associations
- Business logic
-
Controller (
/controllers/Products.cfc
)- All CRUD actions
- Flash messages
- Error handling
-
Views (
/views/products/
)index.cfm
- List all recordsshow.cfm
- Display single recordnew.cfm
- New record formedit.cfm
- Edit record form_form.cfm
- Shared form partial
-
Migration (
/app/migrator/migrations/[timestamp]_create_products.cfc
)- Create table
- Add indexes
- Define columns
-
Tests (if enabled)
- Model tests
- Controller tests
- Integration tests
API Scaffold
- Model - Same as standard
- API Controller - JSON responses only
- Migration - Same as standard
- API Tests - JSON response tests
- No Views - API doesn't need views
Generated Files Example
For wheels scaffold name=product properties=name:string,price:decimal,stock:integer
:
Model: /models/Product.cfc
component extends="Model" {
function init() {
// Properties
property(name="name", label="Product Name");
property(name="price", label="Price");
property(name="stock", label="Stock Quantity");
// Validations
validatesPresenceOf("name,price,stock");
validatesUniquenessOf("name");
validatesNumericalityOf("price", greaterThan=0);
validatesNumericalityOf("stock", onlyInteger=true, greaterThanOrEqualTo=0);
}
}
Controller: /controllers/Products.cfc
component extends="Controller" {
function init() {
// Filters
}
function index() {
products = model("Product").findAll(order="name");
}
function show() {
product = model("Product").findByKey(params.key);
if (!IsObject(product)) {
flashInsert(error="Product not found.");
redirectTo(action="index");
}
}
function new() {
product = model("Product").new();
}
function create() {
product = model("Product").new(params.product);
if (product.save()) {
flashInsert(success="Product was created successfully.");
redirectTo(action="index");
} else {
flashInsert(error="There was an error creating the product.");
renderView(action="new");
}
}
function edit() {
product = model("Product").findByKey(params.key);
if (!IsObject(product)) {
flashInsert(error="Product not found.");
redirectTo(action="index");
}
}
function update() {
product = model("Product").findByKey(params.key);
if (IsObject(product) && product.update(params.product)) {
flashInsert(success="Product was updated successfully.");
redirectTo(action="index");
} else {
flashInsert(error="There was an error updating the product.");
renderView(action="edit");
}
}
function delete() {
product = model("Product").findByKey(params.key);
if (IsObject(product) && product.delete()) {
flashInsert(success="Product was deleted successfully.");
} else {
flashInsert(error="Product could not be deleted.");
}
redirectTo(action="index");
}
}
View: /views/products/index.cfm
<h1>Products</h1>
#flashMessages()#
<p>#linkTo(text="New Product", action="new", class="btn btn-primary")#</p>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Stock</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<cfloop query="products">
<tr>
<td>#encodeForHtml(products.name)#</td>
<td>#dollarFormat(products.price)#</td>
<td>#products.stock#</td>
<td>
#linkTo(text="Show", action="show", key=products.id)#
#linkTo(text="Edit", action="edit", key=products.id)#
#linkTo(text="Delete", action="delete", key=products.id,
method="delete", confirm="Are you sure?")#
</td>
</tr>
</cfloop>
</tbody>
</table>
Form Partial: /views/products/_form.cfm
#errorMessagesFor("product")#
#textField(objectName="product", property="name", label="Product Name")#
#textField(objectName="product", property="price", label="Price")#
#textField(objectName="product", property="stock", label="Stock Quantity")#
Migration: /app/migrator/migrations/[timestamp]_create_products.cfc
component extends="wheels.migrator.Migration" {
function up() {
transaction {
t = createTable("products");
t.string("name");
t.decimal("price", precision=10, scale=2);
t.integer("stock");
t.timestamps();
t.create();
addIndex(table="products", columns="name", unique=true);
}
}
function down() {
transaction {
dropTable("products");
}
}
}
Routes Configuration
Add to /config/routes.cfm
:
<cfset resources("products")>
This creates all RESTful routes:
- GET /products - index
- GET /products/new - new
- POST /products - create
- GET /products/[key] - show
- GET /products/[key]/edit - edit
- PUT/PATCH /products/[key] - update
- DELETE /products/[key] - delete
Post-Scaffold Steps
-
Run migration (if not using
--migrate
):wheels dbmigrate latest
-
Add routes to
/config/routes.cfm
:<cfset resources("products")>
-
Restart application:
wheels reload
-
Test the scaffold:
- Visit
/products
to see the index - Create, edit, and delete records
- Run generated tests
- Visit
Customization
Adding Search
In controller's index()
:
function index() {
if (StructKeyExists(params, "search")) {
products = model("Product").findAll(
where="name LIKE :search",
params={search: "%#params.search#%"}
);
} else {
products = model("Product").findAll();
}
}
Adding Pagination
function index() {
products = model("Product").findAll(
page=params.page ?: 1,
perPage=20,
order="createdAt DESC"
);
}
Adding Filters
function init() {
filters(through="authenticate", except="index,show");
}
Template Customization
The scaffold command uses templates to generate code. You can customize these templates to match your project's coding standards and markup preferences.
Template Override System
The CLI uses a template override system that allows you to customize the generated code:
- CLI Templates - Default templates are located in the CLI module at
/cli/templates/
- App Templates - Custom templates in your application at
/app/snippets/
override the CLI templates
This means you can modify the generated code structure by creating your own templates in the /app/snippets/
directory.
How It Works
When generating code, the CLI looks for templates in this order:
- First checks
/app/snippets/[template-name]
- Falls back to
/cli/templates/[template-name]
if not found in app
Customizing Templates
To customize scaffold output:
- Copy the template you want to customize from
/cli/templates/
to/app/snippets/
- Modify the template to match your project's needs
- Run scaffold - it will use your custom template
Example for customizing the form template:
# Create the crud directory in your app
mkdir -p app/snippets/crud
# Copy the form template
cp /path/to/wheels/cli/templates/crud/_form.txt app/snippets/crud/
# Edit the template to match your markup
# The CLI will now use your custom template
Available Templates
Templates used by scaffold command:
crud/index.txt
- Index/list viewcrud/show.txt
- Show single record viewcrud/new.txt
- New record form viewcrud/edit.txt
- Edit record form viewcrud/_form.txt
- Form partial shared by new/editModelContent.txt
- Model file structureControllerContent.txt
- Controller file structure
Template Placeholders
Templates use placeholders that get replaced during generation:
|ObjectNameSingular|
- Lowercase singular name (e.g., "product")|ObjectNamePlural|
- Lowercase plural name (e.g., "products")|ObjectNameSingularC|
- Capitalized singular name (e.g., "Product")|ObjectNamePluralC|
- Capitalized plural name (e.g., "Products")|FormFields|
- Generated form fields based on properties<!--- CLI-Appends-Here --->
- Marker for future CLI additions
Best Practices
- Properties: Define all needed properties upfront
- Associations: Include relationships in initial scaffold
- Validation: Add custom validations after generation
- Testing: Always generate and run tests
- Routes: Use RESTful resources when possible
- Security: Add authentication/authorization
- Templates: Customize templates in
/app/snippets/
to match your project standards
Comparison with Individual Generators
Scaffold generates everything at once:
# Scaffold does all of this:
wheels generate model product properties="name:string,price:decimal"
wheels generate controller products --rest
wheels generate view products index,show,new,edit,_form
wheels generate test model product
wheels generate test controller products
wheels dbmigrate create table products
See Also
- wheels generate model - Generate models
- wheels generate controller - Generate controllers
- wheels generate resource - Generate REST resources
- wheels dbmigrate latest - Run migrations
- Synopsis
- Alias
- Arguments
- Options
- Examples
- Basic scaffold
- Scaffold with properties
- Scaffold with associations
- API scaffold
- Scaffold with auto-migration
- What Gets Generated
- Standard Scaffold
- API Scaffold
- Generated Files Example
-
Model:
/models/Product.cfc
-
Controller:
/controllers/Products.cfc
-
View:
/views/products/index.cfm
-
Form Partial:
/views/products/_form.cfm
-
Migration:
/app/migrator/migrations/[timestamp]_create_products.cfc
- Routes Configuration
- Post-Scaffold Steps
- Customization
- Adding Search
- Adding Pagination
- Adding Filters
- Template Customization
- Template Override System
- How It Works
- Customizing Templates
- Available Templates
- Template Placeholders
- Best Practices
- Comparison with Individual Generators
- See Also