Loading...

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 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

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

wheels generate property

This command works correctly without options (parameters). Option support is under development and will be available soon.

Add properties to existing model files.

Synopsis

wheels generate property [name] [options]
wheels g property [name] [options]

Description

The wheels generate property command generates a database migration to add a property to an existing model and scaffolds it into _form.cfm and show.cfm views.

Arguments

| Argument | Description | Default | |----------|-------------|---------| | name | Table name | Required |

Options

| Option | Description | Default | |--------|-------------|---------| | column-name | Name of column | Required | | data-type | Type of column | string | | default | Default value for column | | | --null | Whether to allow null values | | | limit | Character or integer size limit for column | | | precision | Precision value for decimal columns | | | scale | Scale value for decimal columns | |

Property Syntax

Basic Format

propertyName:type:option1:option2

Data Type Options

  • biginteger - Large integer
  • binary - Binary data
  • boolean - Boolean (true/false)
  • date - Date only
  • datetime - Date and time
  • decimal - Decimal numbers
  • float - Floating point
  • integer - Integer
  • string - Variable character (VARCHAR)
  • text - Long text
  • time - Time only
  • timestamp - Timestamp
  • uuid - UUID/GUID

Examples

String property

wheels generate property user column-name=firstname

Creates a string/textField property called firstname on the User model.

Boolean property with default

wheels generate property user column-name=isActive data-type=boolean default=0

Creates a boolean/checkbox property with default value of 0 (false).

Datetime property

wheels generate property user column-name=lastloggedin data-type=datetime

Creates a datetime property on the User model.

Decimal property with precision

wheels generate property product column-name=price data-type=decimal precision=10 scale=2

Add calculated property

wheels generate property user "fullName:calculated"

Generated Code Examples

Basic Property Addition

Before:

component extends="Model" {
    
    function init() {
        // Existing code
    }
    
}

After:

component extends="Model" {
    
    function init() {
        // Existing code
        
        // Properties
        property(name="email", sql="email");
        
        // Validations
        validatesPresenceOf(properties="email");
        validatesUniquenessOf(properties="email");
        validatesFormatOf(property="email", regEx="^[^@\s]+@[^@\s]+\.[^@\s]+$");
    }
    
}

Multiple Properties

Command:

wheels generate property product "name:string:required description:text price:float:required:default=0.00 inStock:boolean:default=true"

Generated:

component extends="Model" {
    
    function init() {
        // Properties
        property(name="name", sql="name");
        property(name="description", sql="description");
        property(name="price", sql="price", default=0.00);
        property(name="inStock", sql="in_stock", default=true);
        
        // Validations
        validatesPresenceOf(properties="name,price");
        validatesNumericalityOf(property="price", allowBlank=false, greaterThanOrEqualTo=0);
    }
    
}

Association Property

Command:

wheels generate property comment "userId:integer:required:belongsTo=user postId:integer:required:belongsTo=post"

Generated:

component extends="Model" {
    
    function init() {
        // Associations
        belongsTo(name="user", foreignKey="userId");
        belongsTo(name="post", foreignKey="postId");
        
        // Properties
        property(name="userId", sql="user_id");
        property(name="postId", sql="post_id");
        
        // Validations
        validatesPresenceOf(properties="userId,postId");
    }
    
}

Calculated Property

Command:

wheels generate property user fullName:calculated --callbacks

Generated:

component extends="Model" {
    
    function init() {
        // Properties
        property(name="fullName", sql="", calculated=true);
    }
    
    // Calculated property getter
    function getFullName() {
        return this.firstName & " " & this.lastName;
    }
    
}

Migration Generation

When --migrate=true (default), generates migration:

Migration File

app/migrator/migrations/[timestamp]_add_properties_to_[model].cfc:

component extends="wheels.migrator.Migration" hint="Add properties to product" {

    function up() {
        transaction {
            addColumn(table="products", columnName="sku", columnType="string", limit=50, null=false);
            addColumn(table="products", columnName="price", columnType="decimal", precision=10, scale=2, null=false, default=0.00);
            addColumn(table="products", columnName="stock", columnType="integer", null=true, default=0);
            
            addIndex(table="products", columnNames="sku", unique=true);
        }
    }
    
    function down() {
        transaction {
            removeIndex(table="products", columnNames="sku");
            removeColumn(table="products", columnName="stock");
            removeColumn(table="products", columnName="price");
            removeColumn(table="products", columnName="sku");
        }
    }

}

Validation Rules

Automatic Validations

Based on property type and options:

| Type | Validations Applied | |------|-------------------| | string:required | validatesPresenceOf, validatesLengthOf | | string:unique | validatesUniquenessOf | | email | validatesFormatOf with email regex | | integer | validatesNumericalityOf(onlyInteger=true) | | float | validatesNumericalityOf | | boolean | validatesInclusionOf(list="true,false,0,1") | | date | validatesFormatOf with date pattern |

Custom Validations

Add custom validation rules:

wheels generate property user "age:integer:min=18:max=120"

Generated:

validatesNumericalityOf(property="age", greaterThanOrEqualTo=18, lessThanOrEqualTo=120);

Property Callbacks

Generate with callbacks:

wheels generate property user lastLoginAt:datetime --callbacks

Generated:

function init() {
    // Properties
    property(name="lastLoginAt", sql="last_login_at");
    
    // Callbacks
    beforeUpdate("updateLastLoginAt");
}

private function updateLastLoginAt() {
    if (hasChanged("lastLoginAt")) {
        // Custom logic here
    }
}

Complex Properties

Enum-like Property

wheels generate property order "status:string:default=pending:inclusion=pending,processing,shipped,delivered"

Generated:

property(name="status", sql="status", default="pending");
validatesInclusionOf(property="status", list="pending,processing,shipped,delivered");

File Upload Property

wheels generate property user "avatar:string:fileField"

Generated:

property(name="avatar", sql="avatar");

// In the init() method
afterSave("processAvatarUpload");
beforeDelete("deleteAvatarFile");

private function processAvatarUpload() {
    if (hasChanged("avatar") && isUploadedFile("avatar")) {
        // Handle file upload
    }
}

JSON Property

wheels generate property user "preferences:text:json"

Generated:

property(name="preferences", sql="preferences");

function getPreferences() {
    if (isJSON(this.preferences)) {
        return deserializeJSON(this.preferences);
    }
    return {};
}

function setPreferences(required struct value) {
    this.preferences = serializeJSON(arguments.value);
}

Property Modifiers

Encrypted Property

wheels generate property user "ssn:string:encrypted"

Generated:

property(name="ssn", sql="ssn");

beforeSave("encryptSSN");
afterFind("decryptSSN");

private function encryptSSN() {
    if (hasChanged("ssn") && Len(this.ssn)) {
        this.ssn = encrypt(this.ssn, application.encryptionKey);
    }
}

private function decryptSSN() {
    if (Len(this.ssn)) {
        this.ssn = decrypt(this.ssn, application.encryptionKey);
    }
}

Slugged Property

wheels generate property post "slug:string:unique:fromProperty=title"

Generated:

property(name="slug", sql="slug");
validatesUniquenessOf(property="slug");

beforeValidation("generateSlug");

private function generateSlug() {
    if (!Len(this.slug) && Len(this.title)) {
        this.slug = createSlug(this.title);
    }
}

private function createSlug(required string text) {
    return reReplace(
        lCase(trim(arguments.text)),
        "[^a-z0-9]+",
        "-",
        "all"
    );
}

Batch Operations

wheels generate property user "
    profile.bio:text
    profile.website:string
    profile.twitter:string
    profile.github:string
" --nested

Add Timestamped Properties

wheels generate property post "publishedAt:timestamp deletedAt:timestamp:nullable"

Integration with Existing Code

Preserve Existing Structure

The command intelligently adds properties without disrupting:

  • Existing properties
  • Current validations
  • Defined associations
  • Custom methods
  • Comments and formatting

Conflict Resolution

wheels generate property user email:string
> Property 'email' already exists. Options:
> 1. Skip this property
> 2. Update existing property
> 3. Add with different name
> Choice:

Best Practices

  1. Add properties incrementally
  2. Always generate migrations
  3. Include appropriate validations
  4. Use semantic property names
  5. Add indexes for query performance
  6. Consider default values carefully
  7. Document complex properties

Common Patterns

Soft Delete

wheels generate property model deletedAt:timestamp:nullable

Versioning

wheels generate property document "version:integer:default=1 versionedAt:timestamp"

Status Tracking

wheels generate property order "status:string:default=pending statusChangedAt:timestamp"

Audit Fields

wheels generate property model "createdBy:integer:belongsTo=user updatedBy:integer:belongsTo=user"

Testing

After adding properties:

# Run migration
wheels dbmigrate latest

# Generate property tests
wheels generate test model user

# Run tests
wheels test

See Also