Loading...
Ask or search...
Ctrl K
Loading...

wheels generate controller

Generate a controller with actions and optional views.

Synopsis

wheels generate controller name=<controllerName> [options]

#Can also be used as:
wheels g controller name=<controllerName> [options]

Parameter Syntax

CommandBox supports multiple parameter formats:

  • Named parameters: name=value (e.g., name=Products, actions=index,show)
  • Flag parameters: --flag equals flag=true (e.g., --rest equals rest=true)
  • Flag with value: --flag=value equals flag=value (e.g., --actions=index,show)

Note: Flag syntax (--flag) avoids positional/named parameter conflicts and is recommended for boolean options.

Description

The wheels generate controller command creates a new controller CFC file with specified actions and optionally generates corresponding view files. It supports both traditional and RESTful controller patterns.

Arguments

| Argument | Description | Default | |----------|-------------|---------| | name | Name of the controller to create (usually plural) | Required |

Options

| Option | Description | Default | |--------|-------------|---------| | actions | Actions to generate (comma-delimited) | index | | rest | Generate RESTful controller with CRUD actions | false | | api | Generate API controller (no view-related actions) | false | | description | Controller description comment | "" | | force | Overwrite existing files | false |

Examples

Basic controller

wheels generate controller name=Products

Creates:

  • app/controllers/Products.cfc with index action

Controller with description

wheels generate controller name=Users --description="Handles user management operations"

Creates controller with description comment at the top.

Controller with multiple actions

wheels generate controller name=Products --actions=index,show,new,create

Creates controller with specified actions.

RESTful controller

wheels generate controller name=Products --rest

Automatically generates all RESTful actions and views:

  • index, show, new, create, edit, update, delete

API controller

wheels generate controller name=Orders --api --description="API endpoint for order processing"

Creates:

  • app/controllers/Orders.cfc with JSON responses
  • No view files generated

Custom actions with description

wheels generate controller name=Reports --actions=dashboard,monthly,export --description="Reporting controller"

Generated Code

Basic Controller

component extends="Controller" {

  /**
	* Controller config settings
	**/
	function config() {

	}

    /**
     * index action
     */
    function index() {
        // TODO: Implement index action
    }
}

Controller with Description

/**
 * Handles user management operations
 */
component extends="Controller" {

  /**
	* Controller config settings
	**/
	function config() {

	}

    /**
     * index action
     */
    function index() {
        // TODO: Implement index action
    }
}

RESTful Controller

component extends="Controller" {

	function config() {
		verifies(except="index,new,create", params="key", paramsTypes="integer", handler="objectNotFound");
	}

	/**
	* View all Products
	**/
	function index() {
		products=model("product").findAll();
	}

	/**
	* View Product
	**/
	function show() {
		product=model("product").findByKey(params.key);
	}

	/**
	* Add New Product
	**/
	function new() {
		product=model("product").new();
	}

	/**
	* Create Product
	**/
	function create() {
		product=model("product").create(params.product);
		if(product.hasErrors()){
			renderView(action="new");
		} else {
			redirectTo(action="index", success="Product successfully created");
		}
	}

	/**
	* Edit Product
	**/
	function edit() {
		product=model("product").findByKey(params.key);
	}

	/**
	* Update Product
	**/
	function update() {
		product=model("product").findByKey(params.key);
		if(product.update(params.product)){
			redirectTo(action="index", success="Product successfully updated");
		} else {
			renderView(action="edit");
		}
	}

	/**
	* Delete Product
	**/
	function delete() {
		product=model("product").deleteByKey(params.key);
		redirectTo(action="index", success="Product successfully deleted");
	}

	/**
	* Redirect away if verifies fails, or if an object can't be found
	**/
	function objectNotFound() {
		redirectTo(action="index", error="That Product wasn't found");
	}

}

API Controller

/**
 * API endpoint for order processing
 */
component extends="wheels.Controller" {

    function init() {
        provides("json");
		filters(through="setJsonResponse");
    }

    /**
     * GET /orders
     * Returns a list of all orders
     */
    function index() {
        local.orders = model("order").findAll();
        renderWith(data={ orders=local.orders });
    }

    /**
     * GET /orders/:key
     * Returns a specific order by ID
     */
    function show() {
        local.order = model("order").findByKey(params.key);

        if (IsObject(local.order)) {
            renderWith(data={ order=local.order });
        } else {
            renderWith(data={ error="Record not found" }, status=404);
        }
    }

    /**
     * POST /orders
     * Creates a new order
     */
    function create() {
        local.order = model("order").new(params.order);

        if (local.order.save()) {
            renderWith(data={ order=local.order }, status=201);
        } else {
            renderWith(data={ error="Validation failed", errors=local.order.allErrors() }, status=422);
        }
    }

    /**
     * PUT /orders/:key
     * Updates an existing order
     */
    function update() {
        local.order = model("order").findByKey(params.key);

        if (IsObject(local.order)) {
            local.order.update(params.order);

            if (local.order.hasErrors()) {
                renderWith(data={ error="Validation failed", errors=local.order.allErrors() }, status=422);
            } else {
                renderWith(data={ order=local.order });
            }
        } else {
            renderWith(data={ error="Record not found" }, status=404);
        }
    }

    /**
     * DELETE /orders/:key
     * Deletes a order
     */
    function delete() {
        local.order = model("order").findByKey(params.key);

        if (IsObject(local.order)) {
            local.order.delete();
            renderWith(data={}, status=204);
        } else {
            renderWith(data={ error="Record not found" }, status=404);
        }
    }

	/**
	* Set Response to JSON
	*/
	private function setJsonResponse() {
		params.format = "json";
	}

}

View Generation

Views are automatically generated for non-API controllers:

index.cfm

<h1>Products</h1>

<p>#linkTo(text="New Product", action="new")#</p>

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
        <cfloop query="products">
            <tr>
                <td>#products.name#</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>

Naming Conventions

  • Controller names: PascalCase, typically plural (Products, Users)
  • Action names: camelCase (index, show, createProduct)
  • File locations:
    • Controllers: /controllers/
    • Nested: /controllers/admin/Products.cfc
    • Views: /views/{controller}/

Routes Configuration

Add routes in /config/routes.cfm:

Traditional Routes

<cfscript>
mapper()
    .get(name="products", to="products##index")
    .get(name="product", to="products##show")
    .post(name="products", to="products##create")
    .wildcard()
.end();
</cfscript>

RESTful Resources

<cfscript>
mapper()
    .resources("products")
    .wildcard()
.end();
</cfscript>

Testing

Generate tests alongside controllers:

wheels generate controller name=products --rest
wheels generate test controller name=products

Best Practices

  1. Use plural names for resource controllers
  2. Keep controllers focused on single resources
  3. Use --rest for standard CRUD operations
  4. Implement proper error handling
  5. Add authentication in config() method
  6. Use filters for common functionality

Common Patterns

Authentication Filter

function config() {
    filters(through="authenticate", except="index,show");
}

private function authenticate() {
    if (!session.isLoggedIn) {
        redirectTo(controller="sessions", action="new");
    }
}

Pagination

function index() {
    products = model("Product").findAll(
        page=params.page ?: 1,
        perPage=25,
        order="createdAt DESC"
    );
}
function index() {
    if (StructKeyExists(params, "q")) {
        products = model("Product").findAll(
            where="name LIKE :search OR description LIKE :search",
            params={search: "%#params.q#%"}
        );
    } else {
        products = model("Product").findAll();
    }
}

See Also