// Mass assignment is open by default: with neither accessibleProperties() nor\n// protectedProperties(), every property can be set via new() / create() / update().\n// set(massAssignmentStrict=true) fail-closes that case (opt-in; not the default).\n\n// 1. Allow only `isActive` to be set through mass assignment (e.g. `updateAll()`, `new()`, `update()`).\nconfig() {\n\taccessibleProperties("isActive");\n}\n\n// 2. Allow a comma-delimited list of properties to be set through mass assignment.\n// Any property not in this list is silently ignored when set via mass assignment.\nconfig() {\n\taccessibleProperties("firstName,lastName,email");\n}\n
"},"hint":"Use this method to specify which properties can be set through mass assignment.\n\n","returntype":"void","slug":"model.accessibleProperties","parameters":[{"default":"","required":false,"hint":"Property name (or list of property names) that are allowed to be altered through mass assignment.","name":"properties","type":"string"}],"availableIn":["model"],"name":"accessibleProperties","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelconfiguration","category":"Miscellaneous Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a simple string column to an existing table\naddColumn(table="members", columnType="string", columnName="status", limit=50);\n\n// 2. Add a boolean column with a default value and no NULLs allowed\naddColumn(\n table="members",\n columnType="boolean",\n columnName="isActive",\n default=1,\n allowNull=false\n);\n\n// 3. Add a decimal column with precision and scale (e.g. for a price field)\naddColumn(\n table="products",\n columnType="decimal",\n columnName="price",\n precision=10,\n scale=2,\n default=0,\n allowNull=false\n);\n
"},"hint":"adds a column to existing table\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.addColumn","parameters":[{"required":true,"hint":"The Name of the table to add the column to","name":"table","type":"string"},{"required":true,"hint":"The type of the new column","name":"columnType","type":"string"},{"required":false,"hint":"The name of the new column","name":"columnName","type":"string"},{"required":false,"hint":"Modern alias for `columnName` (matches the plural form every TableDefinition column helper accepts). Pass one or the other — not both.","name":"columnNames","type":"string"},{"default":"","required":false,"hint":"The name of the column which this column should be inserted after","name":"afterColumn","type":"string"},{"default":"","required":false,"hint":"Name for new reference column, see documentation for references function, required if columnType is 'reference'","name":"referenceName","type":"string"},{"required":false,"hint":"Default value for this column","name":"default","type":"any"},{"required":false,"hint":"Whether to allow NULL values","name":"allowNull","type":"boolean"},{"required":false,"hint":"Character or integer size limit for column","name":"limit","type":"numeric"},{"required":false,"hint":"precision value for decimal columns, i.e. number of digits the column can hold","name":"precision","type":"numeric"},{"required":false,"hint":"scale value for decimal columns, i.e. number of digits that can be placed to the right of the decimal point (must be less than or equal to precision)","name":"scale","type":"numeric"}],"availableIn":["migration"],"name":"addColumn","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add an error to the `email` property.\nthis.addError(property="email", message="Sorry, you are not allowed to use that email. Try again, please.");\n\n// 2. Add a named error so you can distinguish it from other errors on the same property.\nthis.addError(property="email", message="That email address is already taken.", name="emailTaken");\n\n// 3. Check for the named error after adding it.\nthis.addError(property="username", message="Username is reserved.", name="reservedUsername");\nif (this.hasErrors(property="username", name="reservedUsername")) {\n\twriteOutput("A reserved-username error is present.");\n}\n
"},"hint":"Adds an error on a specific property.\n\n","returntype":"void","slug":"model.addError","parameters":[{"required":true,"hint":"The name of the property you want to add an error on.","name":"property","type":"string"},{"required":true,"hint":"The error message (such as \"Please enter a correct name in the form field\" for example).","name":"message","type":"string"},{"default":"","required":false,"hint":"A name to identify the error by (useful when you need to distinguish one error from another one set on the same object and you don't want to use the error message itself for that).","name":"name","type":"string"}],"availableIn":["model"],"name":"addError","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a general error on the object (not tied to any single property)\nuser = model("User").findByKey(params.userId);\nuser.addErrorToBase(message="Your account has been locked. Please contact support.");\n\n// 2. Add a named base error so it can be targeted or cleared later\norder = model("Order").findByKey(params.orderId);\norder.addErrorToBase(message="This order cannot be placed outside business hours.", name="businessHoursViolation");\nif (order.hasErrors(name="businessHoursViolation")) {\n // handle the named error\n}\n\n// 3. Use addErrorToBase inside a custom validation method on the model\nfunction validate() {\n if (this.totalAmount > creditLimit()) {\n this.addErrorToBase(message="The total amount exceeds your available credit limit.");\n }\n}\n
"},"hint":"Adds an error on the object as a whole (not tied to any specific property).\n\n","returntype":"void","slug":"model.addErrorToBase","parameters":[{"required":true,"hint":"The error message (such as \"Please enter a correct name in the form field\" for example).","name":"message","type":"string"},{"default":"","required":false,"hint":"A name to identify the error by (useful when you need to distinguish one error from another one set on the same object and you don't want to use the error message itself for that).","name":"name","type":"string"}],"availableIn":["model"],"name":"addErrorToBase","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a foreign key from orders.customerId to customers.id\naddForeignKey(\n table="orders",\n referenceTable="customers",\n column="customerId",\n referenceColumn="id"\n);\n\n// 2. Add a foreign key from comments.postId to posts.id\naddForeignKey(\n table="comments",\n referenceTable="posts",\n column="postId",\n referenceColumn="id"\n);\n\n// 3. Use addForeignKey in a migration's up() and remove it in down()\n// In your migration CFC:\n//\n// public void function up() {\n// addForeignKey(\n// table="order_items",\n// referenceTable="orders",\n// column="orderId",\n// referenceColumn="id"\n// );\n// }\n//\n// public void function down() {\n// dropForeignKey(table="order_items", keyName="FK_order_items_orders");\n// }\n
"},"hint":"Add a foreign key constraint to the database, using the reference name that was used to create it\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.addForeignKey","parameters":[{"required":true,"hint":"The table name to perform the operation on","name":"table","type":"string"},{"required":true,"hint":"The reference table name to perform the operation on","name":"referenceTable","type":"string"},{"required":false,"hint":"The column name to perform the operation on","name":"column","type":"string"},{"required":false,"hint":"Modern alias for `column` (consistent with the rest of the migrator surface).","name":"columnName","type":"string"},{"required":true,"hint":"The reference column name to perform the operation on","name":"referenceColumn","type":"string"}],"availableIn":["migration"],"name":"addForeignKey","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add the `js` format\naddFormat(extension="js", mimeType="text/javascript");\n\n// 2. Add the `ppt` and `pptx` formats\naddFormat(extension="ppt", mimeType="application/vnd.ms-powerpoint");\naddFormat(extension="pptx", mimeType="application/vnd.ms-powerpoint");\n\n// 3. Add a custom `csv` format so controllers can respond with `responds(formats="csv")`\naddFormat(extension="csv", mimeType="text/csv");\n
"},"hint":"Adds a new MIME type to your Wheels application for use with responding to multiple formats.\n\n","returntype":"void","slug":"controller.addFormat","parameters":[{"required":true,"hint":"File extension to add.","name":"extension","type":"string"},{"required":true,"hint":"Matching MIME type to associate with the file extension.","name":"mimeType","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"addFormat","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"configuration","category":"Miscellaneous Functions","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a basic index on a single column\naddIndex(table="users", columnNames="email");\n\n// 2. Add a unique index to enforce uniqueness on a column\naddIndex(table="members", columnNames="username", unique=true);\n\n// 3. Add a composite index on multiple columns\naddIndex(table="orders", columnNames="customerId,createdAt");\n\n// 4. Add an index with a custom index name\n// (defaults to tableName_firstColumnName, e.g. "posts_publishedAt")\naddIndex(table="posts", columnNames="publishedAt", indexName="idx_posts_published");\n
"},"hint":"Add database index on a table column\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.addIndex","parameters":[{"required":true,"hint":"The table name to perform the index operation on","name":"table","type":"string"},{"required":false,"hint":"One or more column names to index, comma separated","name":"columnNames","type":"string"},{"default":"false","required":false,"hint":"If true will create a unique index constraint","name":"unique","type":"boolean"},{"default":"","required":false,"hint":"The name of the index to add: Defaults to table name + underscore + first column name","name":"indexName","type":"string"}],"availableIn":["migration"],"name":"addIndex","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Insert a simple seed record into a settings table\naddRecord(\n table = "settings",\n name = "siteName",\n value = "My Wheels App"\n);\n\n// 2. Insert a record with multiple columns (extra keyword arguments become column/value pairs)\naddRecord(\n table = "people",\n id = 1,\n title = "Mr",\n firstName = "Bruce",\n lastName = "Wayne",\n email = "bruce@wayneenterprises.com",\n phone = "555-678-9099"\n);\n\n// 3. Seed an admin user role during a migration's up() function\ncomponent extends="wheels.migrator.Migration" {\n function up() {\n addRecord(\n table = "roles",\n id = 1,\n name = "admin",\n active = true\n );\n }\n function down() {\n removeRecord(table = "roles", where = "id = 1");\n }\n}\n
"},"hint":"Adds a record to a table\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.addRecord","parameters":[{"required":true,"hint":"The table name to add the record to","name":"table","type":"string"}],"availableIn":["migration"],"name":"addRecord","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a foreign key from comments.postId to posts.id using a reference name\n// Equivalent to: addForeignKey(table="comments", referenceTable="posts", column="postId", referenceColumn="id")\naddReference(table="comments", referenceName="post");\n\n// 2. Add a foreign key from order_items.orderId to orders.id\naddReference(table="order_items", referenceName="order");\n\n// 3. Use addReference in a migration's up() and undo it with dropReference() in down()\n// In your migration CFC:\n//\n// public void function up() {\n// addReference(table="comments", referenceName="post");\n// }\n//\n// public void function down() {\n// dropReference(table="comments", referenceName="post");\n// }\n
"},"hint":"Add a foreign key constraint to the database, using the reference name that was used to create it\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.addReference","parameters":[{"required":true,"hint":"The table name to perform the operation on","name":"table","type":"string"},{"required":false,"hint":"The reference table name to perform the operation on","name":"referenceName","type":"string"},{"required":false,"hint":"Alias for `referenceName` (consistent with the modern migrator surface — `columnName` / `columnNames` are accepted alongside the legacy form).","name":"columnName","type":"string"},{"required":false,"hint":"Plural alias for `referenceName`. When both `columnName` and `columnNames` are supplied, `columnNames` wins.","name":"columnNames","type":"string"}],"availableIn":["migration"],"name":"addReference","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Registers method(s) to run AFTER the database transaction commits (v4.2.0).\nThey run only when the OUTERMOST transaction commits; a rollback discards\nthem. With no transaction (transactionMode=\"none\"/\"false\") they fire\nimmediately after the write, since it is already committed.\n\n","returntype":"void","slug":"model.afterCommit","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"},{"default":"","required":false,"hint":"Restrict to one or more operations: create, update, delete (comma-delimited; blank = all).","name":"on","type":"string"}],"availableIn":["model"],"name":"afterCommit","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single method to run after an object is created\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n afterCreate("sendWelcomeEmail");\n }\n private function sendWelcomeEmail() {\n // send email to this.email\n }\n}\n\n// 2. Register multiple methods by passing a comma-delimited list\nafterCreate("updateCache,notifyAdmin");\n\n// 3. Register using the named `methods` argument\nafterCreate(methods="syncToExternalApi");\n
"},"hint":"Registers method(s) that should be called after a new object is created.\n\n","returntype":"void","slug":"model.afterCreate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterCreate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method after an object is deleted\n// In models/Order.cfc\nafterDelete("notifyWarehouse");\n\n// 2. Call multiple methods after an object is deleted (comma-separated list)\n// In models/User.cfc\nafterDelete("removeFromSearchIndex,clearCachedData");\n\n// 3. Register several after-delete callbacks individually for clarity\n// In models/Article.cfc\nafterDelete("logDeletion");\nafterDelete("cleanupAttachments");\n
"},"hint":"Registers method(s) that should be called after an object is deleted.\n\n","returntype":"void","slug":"model.afterDelete","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterDelete","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single callback method to run after records are fetched\n// In models/User.cfc\nconfig() {\n\tafterFind("setFetchedAt");\n}\n\n// The callback receives each row's columns as arguments; return the struct to modify the record.\nfunction setFetchedAt() {\n\targuments.fetchedAt = Now();\n\treturn arguments;\n}\n\n// 2. Format a column value after a find (works for both query rows and objects)\n// In models/Product.cfc\nconfig() {\n\tafterFind("formatPrice");\n}\n\nfunction formatPrice() {\n\tif (StructKeyExists(arguments, "price")) {\n\t\targuments.price = DollarFormat(arguments.price);\n\t}\n\treturn arguments;\n}\n\n// 3. Register multiple callback methods as a comma-delimited list\nconfig() {\n\tafterFind("setFetchedAt,formatPrice");\n}\n
"},"hint":"Registers method(s) that should be called after an existing object has been initialized (which is usually done with the findByKey or findOne method).\n\n","returntype":"void","slug":"model.afterFind","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterFind","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method after any object is initialized (whether new or fetched from the database)\nafterInitialization("fixObj");\n\n// 2. Call multiple methods after initialization by passing a comma-delimited list\nafterInitialization("setDefaults,fixObj");\n
"},"hint":"Registers method(s) that should be called after an object has been initialized.\n\n","returntype":"void","slug":"model.afterInitialization","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterInitialization","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method after a new object is initialized\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n afterNew("setDefaults");\n }\n private function setDefaults() {\n this.role = "member";\n this.active = true;\n }\n}\n\n// 2. Call multiple methods after a new object is initialized (comma-delimited list)\nafterNew("setDefaults,generateToken");\n\n// 3. Use the `method` argument alias instead of `methods`\nafterNew(method="setDefaults");\n
"},"hint":"Registers method(s) that should be called after a new object has been initialized (which is usually done with the new method).\n\n","returntype":"void","slug":"model.afterNew","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterNew","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Registers method(s) to run AFTER the database transaction rolls back (v4.2.0).\n\n","returntype":"void","slug":"model.afterRollback","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"},{"default":"","required":false,"hint":"Restrict to one or more operations: create, update, delete (comma-delimited; blank = all).","name":"on","type":"string"}],"availableIn":["model"],"name":"afterRollback","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single callback method to run after an object is saved (both create and update)\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n afterSave("sendWelcomeEmail");\n }\n\n private function sendWelcomeEmail() {\n // called automatically each time a User is saved\n }\n}\n\n// 2. Register multiple callback methods using a comma-delimited list\ncomponent extends="Model" {\n function config() {\n afterSave("updateSearchIndex,notifyAdmins");\n }\n}\n\n// 3. Register multiple callbacks by calling afterSave() more than once\ncomponent extends="Model" {\n function config() {\n afterSave("updateSearchIndex");\n afterSave("notifyAdmins");\n }\n}\n
"},"hint":"Registers method(s) that should be called after an object is saved.\n\n","returntype":"void","slug":"model.afterSave","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterSave","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single method to run after an object is updated\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n afterUpdate("clearCache");\n }\n private function clearCache() {\n // invalidate cached data for this user\n }\n}\n\n// 2. Register multiple methods by passing a comma-delimited list\nafterUpdate("clearCache,notifyAuditLog");\n\n// 3. Register using the named `methods` argument\nafterUpdate(methods="syncToSearchIndex");\n
"},"hint":"Registers method(s) that should be called after an existing object is updated.\n\n","returntype":"void","slug":"model.afterUpdate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterUpdate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method after an object is validated\nafterValidation("fixObj");\n\n// 2. Call multiple methods after an object is validated (comma-delimited list)\nafterValidation("sanitizeFields,logValidationResult");\n\n// 3. Use the singular `method` alias for clarity\nafterValidation(method="trimWhitespace");\n
"},"hint":"Registers method(s) that should be called after an object is validated.\n\n","returntype":"void","slug":"model.afterValidation","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterValidation","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method after a new object is validated on create\ncomponent extends="Model" {\n\tfunction config() {\n\t\tafterValidationOnCreate("assignDefaults");\n\t}\n\n\tprivate function assignDefaults() {\n\t\tif (!Len(this.role)) {\n\t\t\tthis.role = "member";\n\t\t}\n\t}\n}\n\n// 2. Call multiple methods after validation on create (comma-delimited list)\ncomponent extends="Model" {\n\tfunction config() {\n\t\tafterValidationOnCreate("sanitizeFields,logNewRecord");\n\t}\n}\n\n// 3. Use the singular `method` alias for clarity\ncomponent extends="Model" {\n\tfunction config() {\n\t\tafterValidationOnCreate(method="trimWhitespace");\n\t}\n}\n
"},"hint":"Registers method(s) that should be called after a new object is validated.\n\n","returntype":"void","slug":"model.afterValidationOnCreate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterValidationOnCreate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method after an existing object is validated on update\n// In models/User.cfc:\ncomponent extends="Model" {\n function config() {\n afterValidationOnUpdate("stampUpdatedBy");\n }\n\n private function stampUpdatedBy() {\n this.updatedBy = request.currentUserId;\n }\n}\n\n// 2. Register multiple methods to run after an existing object is validated on update\ncomponent extends="Model" {\n function config() {\n afterValidationOnUpdate("normalizeSlug,logValidation");\n }\n\n private function normalizeSlug() {\n this.slug = LCase(Replace(this.title, " ", "-", "all"));\n }\n\n private function logValidation() {\n // custom logging logic here\n }\n}\n
"},"hint":"Registers method(s) that should be called after an existing object is validated.\n\n","returntype":"void","slug":"model.afterValidationOnUpdate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"afterValidationOnUpdate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Collect all validation errors from associated objects on a post\npost = model("Post").findOne(where="id=1", include="comments");\nerrors = post.allAssociationErrors();\n// errors -> array of error structs from associated comments (and their associations, recursively)\n// Each struct contains keys: property, message, name\n\n// 2. Use allErrors() with includeAssociations=true instead (preferred shorthand)\n// allErrors() calls allAssociationErrors() internally when includeAssociations is true\npost = model("Post").findOne(where="id=1", include="comments");\nallErrors = post.allErrors(includeAssociations=true);\n// allErrors -> combined array of the post's own errors plus all associated errors\n\n// 3. Check if any associated model has errors before saving\norder = model("Order").findOne(where="id=1", include="lineItems");\nassociationErrors = order.allAssociationErrors();\nif (arrayLen(associationErrors)) {\n writeOutput("One or more line items have validation errors.");\n}\n
"},"hint":"Gets all associated errors recursively\n\n","returntype":"array","slug":"model.allAssociationErrors","parameters":[{"default":"[runtime expression]","required":false,"name":"seenErrors","type":"array"}],"availableIn":["model"],"name":"allAssociationErrors","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get an object, change some properties, and inspect all changes before saving\nmember = model("member").findByKey(params.memberId);\nmember.firstName = params.newFirstName;\nmember.email = params.newEmail;\nchanges = member.allChanges();\n// changes -> {\n// firstName: { changedFrom: "Jane", changedTo: "Janet" },\n// email: { changedFrom: "jane@example.com", changedTo: "janet@example.com" }\n// }\n\n// 2. Only call allChanges() when there are changes to process\npost = model("post").findByKey(params.id);\npost.title = params.title;\npost.body = params.body;\nif (post.hasChanged()) {\n changes = post.allChanges();\n for (prop in changes) {\n writeOutput("'#prop#' changed from '#changes[prop].changedFrom#' to '#changes[prop].changedTo#'");\n }\n}\n\n// 3. allChanges() returns an empty struct when nothing has changed\nuser = model("user").findByKey(params.userId);\nchanges = user.allChanges();\n// changes -> {} (empty struct — no unsaved changes)\n
"},"hint":"Returns a struct detailing all changes that have been made on the object but not yet saved to the database.\n\n","returntype":"struct","slug":"model.allChanges","parameters":[],"availableIn":["model"],"name":"allChanges","tags":{"categoryClass":"changefunctions","sectionClass":"modelobject","category":"Change Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all errors on a model object after a failed validation\nuser = model("User").new(username="", password="");\nuser.valid();\nerrors = user.allErrors();\n// errors ->\n// [\n// { message: "Username must not be blank.", name: "", property: "username" },\n// { message: "Password must not be blank.", name: "", property: "password" }\n// ]\n\n// 2. Check for errors and iterate over them\nif (user.hasErrors()) {\n\tfor (error in user.allErrors()) {\n\t\twriteOutput(error.property & ": " & error.message);\n\t}\n}\n\n// 3. Include errors from associated models (e.g. a user with associated profile)\nuser = model("User").findOne(where="id=1", include="profile");\nuser.valid();\nallErrors = user.allErrors(includeAssociations=true);\n// allErrors contains errors from both user and its associated profile model\n
"},"hint":"Returns an array of all the errors on the object.\n\n\nIt does this by storing instances of models that are associations, and not checking associations of those instances because they have already been checked.","returntype":"array","slug":"model.allErrors","parameters":[{"default":false,"required":false,"name":"includeAssociations","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"is a private argument not meant to be used by the user, the function uses this to ensure circular dependency avoidance.","name":"seenErrors","type":"array"}],"availableIn":["model"],"name":"allErrors","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Log a custom message during a migration's up() step\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tt = createTable(name="articles", force=true);\n\t\t\tt.string(columnNames="title", allowNull=false);\n\t\t\tt.text(columnNames="body");\n\t\t\tt.timestamps();\n\t\t\tt.create();\n\t\t\tannounce("Created articles table");\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (StructKeyExists(state, "exception")) {\n\t\t\ttransaction action="rollback";\n\t\t\tthrow(errorCode="1", detail=state.exception.detail, message=state.exception.message, type="any");\n\t\t} else {\n\t\t\ttransaction action="commit";\n\t\t}\n\t}\n}\n\n// 2. Announce multiple steps to provide granular feedback\nfunction up() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\taddColumn(table="users", columnType="string", columnName="apiKey", limit=64, allowNull=true);\n\t\t\tannounce("Added apiKey column to users");\n\n\t\t\taddIndex(table="users", columnNames="apiKey", unique=true);\n\t\t\tannounce("Added unique index on users.apiKey");\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (StructKeyExists(state, "exception")) {\n\t\t\ttransaction action="rollback";\n\t\t\tthrow(errorCode="1", detail=state.exception.detail, message=state.exception.message, type="any");\n\t\t} else {\n\t\t\ttransaction action="commit";\n\t\t}\n\t}\n}\n
"},"hint":"Used internally by Migrator to provide feedback to the GUI and CLI about completed DB operations\nOnly available in a migration CFC\n\n","returntype":"any","slug":"migration.announce","parameters":[{"required":true,"name":"message","type":"string"}],"availableIn":["migration","tabledefinition"],"name":"announce","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\n// 1. Basic API scope using the default path and name prefix "api"\nmapper()\n .api()\n // Route name: apiUsers\n // Example URL: /api/users\n .resources("users")\n .end()\n.end();\n\n// 2. Combine api() with version() for versioned API endpoints\nmapper()\n .api()\n .version(1)\n // Route name: apiV1Users\n // Example URL: /api/v1/users\n .resources("users")\n .end()\n\n .version(2)\n // Route name: apiV2Products\n // Example URL: /api/v2/products\n .resources("products")\n .end()\n .end()\n.end();\n\n// 3. Override the default path and name prefixes\nmapper()\n .api(path="public-api", name="publicApi")\n // Route name: publicApiOrders\n // Example URL: /public-api/orders\n .resources("orders")\n .end()\n.end();\n\n// 4. Use api() with a callback to avoid manual .end() calls\nmapper()\n .api(callback=function(m) {\n m.version(number=1, callback=function(m) {\n // Route name: apiV1Users\n // Example URL: /api/v1/users\n m.resources("users");\n });\n })\n.end();\n\n</cfscript>\n
"},"hint":"Scope routes under an API path prefix. Shorthand for .group(path=\"api\", name=\"api\", ...). Typically used in combination with version() to organize versioned API endpoints.\n\n","returntype":"struct","slug":"mapper.api","parameters":[{"default":"api","required":false,"hint":"URL path prefix for the API. Defaults to `\"api\"`.","name":"path","type":"string"},{"default":"api","required":false,"hint":"Name prefix for route names. Defaults to `\"api\"`.","name":"name","type":"string"},{"required":false,"hint":"Variable patterns to apply to all child routes.","name":"constraints","type":"struct"},{"required":false,"hint":"A callback function to define nested routes within this API scope.","name":"callback","type":"any"}],"availableIn":["mapper"],"name":"api","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Removes every entry from the application data cache. The framework's own caches (actions, pages,\npartials, queries) are left alone.\n\n","returntype":"void","slug":"controller.appCacheClear","parameters":[],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"appCacheClear","tags":{"categoryClass":"cachingfunctions","sectionClass":"globalhelpers","category":"Caching Functions","section":"Global Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Removes the entry for key. Returns true when there was an unexpired entry to remove.\n\n","returntype":"boolean","slug":"controller.appCacheDelete","parameters":[{"required":true,"hint":"A string, or a struct or array of values (struct key order doesn't matter).","name":"key","type":"any"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"appCacheDelete","tags":{"categoryClass":"cachingfunctions","sectionClass":"globalhelpers","category":"Caching Functions","section":"Global Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns true when an unexpired entry exists for key, even one holding false, 0 or \"\".\n\n","returntype":"boolean","slug":"controller.appCacheExists","parameters":[{"required":true,"hint":"A string, or a struct or array of values (struct key order doesn't matter).","name":"key","type":"any"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"appCacheExists","tags":{"categoryClass":"cachingfunctions","sectionClass":"globalhelpers","category":"Caching Functions","section":"Global Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns the value cached under key. On a miss, calls callback, caches what it returns for time\nand returns it. A cached false, 0 or \"\" counts as a hit, so callback isn't called again\nuntil the entry expires or is deleted. When callback returns nothing, nothing is cached and \"\"\nis returned; when it throws, nothing is cached and the error propagates. callback runs outside\nthe cache lock, so two requests that miss at the same moment may both call it (the later write\nwins). When the cache is full, the computed value is returned but not cached, so the next call\ncomputes it again. The cache lives in this server's memory and empties on an application reload\nor restart.\nKeys are shared by every user, session, tenant and host: nothing about the request is added. For\nper-user, per-role or per-tenant data, put that identity in the key, e.g. \"digest-\" & userId.\n\n","returntype":"any","slug":"controller.appCacheFetch","parameters":[{"required":true,"hint":"A string, or a struct or array of values (struct key order doesn't matter).","name":"key","type":"any"},{"required":true,"hint":"A function that computes the value.","name":"callback","type":"any"},{"default":"[runtime expression]","required":false,"hint":"How long to keep the value, in `cacheDatePart` units (minutes by default).","name":"time","type":"numeric"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"appCacheFetch","tags":{"categoryClass":"cachingfunctions","sectionClass":"globalhelpers","category":"Caching Functions","section":"Global Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns the value cached under key, or defaultValue when there is no unexpired entry. A cached\nfalse, 0 or \"\" is returned as it is. Complex values come back as a copy.\nKeys are shared by every user, session, tenant and host (see appCacheFetch()).\n\n","returntype":"any","slug":"controller.appCacheRead","parameters":[{"required":true,"hint":"A string, or a struct or array of values (struct key order doesn't matter).","name":"key","type":"any"},{"default":"","required":false,"hint":"What to return on a miss. The named argument `default` is also accepted.","name":"defaultValue","type":"any"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"appCacheRead","tags":{"categoryClass":"cachingfunctions","sectionClass":"globalhelpers","category":"Caching Functions","section":"Global Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Caches value under key for time, replacing any entry already there. Complex values are\nstored as a copy. Returns false when the value wasn't stored because the cache is full\n(maximumItemsToCache).\n\n","returntype":"boolean","slug":"controller.appCacheWrite","parameters":[{"required":true,"hint":"A string, or a struct or array of values (struct key order doesn't matter).","name":"key","type":"any"},{"required":true,"hint":"The value to cache.","name":"value","type":"any"},{"default":"[runtime expression]","required":false,"hint":"How long to keep the value, in `cacheDatePart` units (minutes by default).","name":"time","type":"numeric"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"appCacheWrite","tags":{"categoryClass":"cachingfunctions","sectionClass":"globalhelpers","category":"Caching Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all association definitions for a model and inspect them\ninfo = model("post").associationInfo();\n// info is a struct where each key is an association name, e.g.:\n// info.comments.type -> "hasMany"\n// info.comments.modelName -> "Comment"\n// info.comments.foreignKey -> "postId"\n// info.comments.dependent -> "delete"\n// info.author.type -> "belongsTo"\n// info.author.modelName -> "Author"\n\n// 2. Check whether a specific association is defined on the model\ninfo = model("user").associationInfo();\nif (structKeyExists(info, "profile")) {\n writeOutput("User has a profile association of type: " & info.profile.type);\n}\n\n// 3. Iterate over all associations to build a summary\ninfo = model("article").associationInfo();\nfor (assocName in info) {\n writeOutput(assocName & " -> " & info[assocName].type & " " & info[assocName].modelName);\n}\n
"},"hint":"Returns a struct containing all association definitions for this model.\nEach key is the association name, and the value is a struct with association metadata\nincluding type (belongsTo, hasMany, hasOne), modelName, foreignKey, joinKey, and dependent.\n\n","returntype":"struct","slug":"model.associationInfo","parameters":[],"availableIn":["model"],"name":"associationInfo","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all association names defined on a model\nnames = model("User").associationNames();\n// names -> "profile,posts,comments"\n\n// 2. Check whether a specific association exists on the model\nif (listFindNoCase(model("Post").associationNames(), "comments")) {\n // the Post model has a "comments" association\n}\n\n// 3. Iterate over each association name\nfor (assocName in listToArray(model("Order").associationNames())) {\n writeOutput(assocName);\n}\n
"},"hint":"Returns a list of association names defined on this model.\n\n","returntype":"string","slug":"model.associationNames","parameters":[],"availableIn":["model"],"name":"associationNames","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Embed the CSRF token in a manually-built form hidden field\ntoken = authenticityToken();\nwriteOutput('<input type="hidden" name="authenticityToken" value="' & token & '">');\n\n// 2. Pass the token as a request header for an AJAX call (e.g. in a JavaScript data island)\nwriteOutput('<meta name="csrf-token" content="' & authenticityToken() & '">');\n// JavaScript can then read this and send it as the X-CSRF-Token header with each POST request.\n\n// 3. Include the token in a JSON API response body so a client can replay it\ntokenValue = authenticityToken();\nwriteOutput(serializeJSON({authenticityToken = tokenValue}));\n
"},"hint":"Returns the raw CSRF authenticity token\n\n","returntype":"string","slug":"controller.authenticityToken","parameters":[],"availableIn":["controller"],"name":"authenticityToken","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Include CSRF token in a plain HTML form that POSTs data\n// (use this when you are not using startFormTag())\n<form action="#urlFor(route='posts')#" method="post">\n #authenticityTokenField()#\n <!--- other fields here --->\n</form>\n\n// 2. Not needed for GET forms — GET requests are not CSRF-protected\n<form action="#urlFor(route='posts')#" method="get">\n <!--- no token required --->\n</form>\n
"},"hint":"Returns a hidden form field containing a new authenticity token.\n\n","returntype":"string","slug":"controller.authenticityTokenField","parameters":[],"availableIn":["controller"],"name":"authenticityTokenField","tags":{"categoryClass":"generalformfunctions","sectionClass":"viewhelpers","category":"General Form Functions","section":"View Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Authorizes the current user for an action on a record by dispatching to the\nrecord's policy (app/policies/Policy.cfc). Throws\nWheels.NotAuthorized (HTTP 403) when the policy denies, and returns the\nrecord unchanged when it allows so the call can be inlined:\n\nfunction update() {\npost = authorize(model(\"Post\").findByKey(params.key));\npost.update(params.post);\n}\n\nA missing policy class throws Wheels.Policy.NotDefined in development and\ntesting (loud, Pundit-style, to catch typos) and silently denies in\nproduction — the same environment posture as tableName() (##3079). A\npolicy class that lacks a method for the action throws\nWheels.Policy.UnknownAction (a typo, not a deny). Reserved init and\nscope still deny as Wheels.NotAuthorized. Only boolean true grants.\n\n","returntype":"any","slug":"controller.authorize","parameters":[{"required":true,"hint":"The model instance (or model class / model name string) to authorize against.","name":"record","type":"any"},{"default":"","required":false,"hint":"The policy method to dispatch. Defaults to the current `params.action`, resolved at call time.","name":"action","type":"string"}],"availableIn":["controller"],"name":"authorize","tags":{"categoryClass":"authorizationfunctions","sectionClass":"controller","category":"Authorization Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Link both URLs and email addresses (default behavior)\nresult = autoLink("Download CFWheels from http://cfwheels.org/download");\n// result -> "Download CFWheels from <a href="http://cfwheels.org/download">http://cfwheels.org/download</a>"\n\n// 2. Link email addresses only\nresult = autoLink(text="Email us at info@cfwheels.org or visit http://cfwheels.org", link="emailAddresses");\n// result -> "Email us at <a href="mailto:info@cfwheels.org">info@cfwheels.org</a> or visit http://cfwheels.org"\n\n// 3. Link URLs only (skip email addresses)\nresult = autoLink(text="Visit http://cfwheels.org or contact info@cfwheels.org", link="URLs");\n// result -> "Visit <a href="http://cfwheels.org">http://cfwheels.org</a> or contact info@cfwheels.org"\n\n// 4. Disable auto-linking of relative URLs\nresult = autoLink(text="See /docs/guide for details or http://cfwheels.org for more.", relative=false);\n// result -> "See /docs/guide for details or <a href="http://cfwheels.org">http://cfwheels.org</a> for more."\n
"},"hint":"Turns all URLs and email addresses into links.\n\n","returntype":"string","slug":"controller.autoLink","parameters":[{"required":true,"hint":"The text to create links in.","name":"text","type":"string"},{"default":"all","required":false,"hint":"Whether to link URLs, email addresses or both. Possible values are: `all` (default), `URLs` and `emailAddresses`.","name":"link","type":"string"},{"default":true,"required":false,"hint":"Should we auto-link relative urls.","name":"relative","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"autoLink","tags":{"categoryClass":"linkfunctions","sectionClass":"viewhelpers","category":"Link Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Disable automatic validations for this model (useful when automatic validations are enabled globally but you want to opt out for a specific model).\ncomponent extends="Model" {\n\tfunction config() {\n\t\tautomaticValidations(false);\n\t}\n}\n\n// 2. Explicitly enable automatic validations for this model (useful when automatic validations are disabled globally but you want to opt in for a specific model).\ncomponent extends="Model" {\n\tfunction config() {\n\t\tautomaticValidations(true);\n\t}\n}\n
"},"hint":"Whether or not to enable default validations for this model.\n\n","returntype":"void","slug":"model.automaticValidations","parameters":[{"required":true,"hint":"Set to `true` or `false`.","name":"value","type":"boolean"}],"availableIn":["model"],"name":"automaticValidations","tags":{"categoryClass":"validationfunctions","sectionClass":"modelconfiguration","category":"Validation Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the average salary for all employees.\navgSalary = model("employee").average("salary");\n\n// 2. Get the average salary for employees in a given department.\navgSalary = model("employee").average(property="salary", where="departmentId=#params.key#");\n\n// 3. Make sure a numeric value is always returned if no records are found.\navgSalary = model("employee").average(property="salary", where="salary BETWEEN #params.min# AND #params.max#", ifNull=0);\n\n// 4. Average only distinct salary values (duplicates excluded).\navgSalary = model("employee").average(property="salary", distinct=true);\n\n// 5. Get the average salary grouped by department (returns a query).\navgByDept = model("employee").average(property="salary", group="departmentId");\n
"},"hint":"Calculates the average value for a given property.\nUses the SQL function AVG.\nIf no records can be found to perform the calculation on you can use the ifNull argument to decide what should be returned.\n\n","returntype":"any","slug":"model.average","parameters":[{"required":true,"hint":"Name of the property to calculate the average for.","name":"property","type":"string"},{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":false,"required":false,"hint":"When `true`, `AVG` will be performed only on each unique instance of a value, regardless of how many times the value occurs.","name":"distinct","type":"boolean"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"","required":false,"hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","name":"ifNull","type":"any"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"required":false,"hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"group","type":"string"}],"availableIn":["model"],"name":"average","tags":{"categoryClass":"statisticsfunctions","sectionClass":"modelclass","category":"Statistics Functions","section":"Model Class"}},{"extended":{"hasExtended":false,"docs":""},"hint":"","returntype":"string","slug":"controller.bcryptHash","parameters":[{"required":true,"name":"password","type":"string"},{"default":10,"required":false,"name":"cost","type":"numeric"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"bcryptHash","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":false,"docs":""},"hint":"Whether an existing bcrypt hash should be re-hashed because its cost\nfactor differs from the target, or because it is malformed.\nSelf-contained (regex cost parse) so it can ship on EVERY engine —\nincluding RustCFML, which provides bcryptHash/bcryptVerify as native\nbuiltins and therefore skips the main security.cfm include.","returntype":"boolean","slug":"controller.bcryptNeedsRehash","parameters":[{"required":true,"name":"hash","type":"string"},{"default":10,"required":false,"name":"cost","type":"numeric"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"bcryptNeedsRehash","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":false,"docs":""},"hint":"","returntype":"boolean","slug":"controller.bcryptVerify","parameters":[{"required":true,"name":"password","type":"string"},{"required":true,"name":"hash","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"bcryptVerify","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single callback method to run before a new object is created\n// Defined inside the model's config() function\nbeforeCreate("setDefaults");\n\n// 2. Register multiple callback methods to run in sequence before creation\nbeforeCreate("generateSlug,stampCreatedBy");\n\n// 3. Register callbacks using the named argument\nbeforeCreate(methods="generateToken,normalizeEmail");\n
"},"hint":"Registers method(s) that should be called before a new object is created.\n\n","returntype":"void","slug":"model.beforeCreate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeCreate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single method to run before an object is deleted\n// In models/Post.cfc\ncomponent extends="Model" {\n function config() {\n beforeDelete("cleanUpAttachments");\n }\n\n private function cleanUpAttachments() {\n // Remove associated files from disk before the record is deleted\n fileDelete(expandPath("/uploads/#this.id#"));\n }\n}\n\n// 2. Register multiple methods to run before deletion (comma-delimited list)\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n beforeDelete("revokeTokens,archiveActivity");\n }\n\n private function revokeTokens() {\n model("Token").deleteAll(where="userId=#this.id#");\n }\n\n private function archiveActivity() {\n model("ActivityLog").updateAll(\n properties="archivedAt=NOW()",\n where="userId=#this.id#"\n );\n }\n}\n\n// 3. Halt deletion by returning false from the callback\n// In models/Order.cfc\ncomponent extends="Model" {\n function config() {\n beforeDelete("preventIfShipped");\n }\n\n private function preventIfShipped() {\n // Returning false cancels the delete operation\n if (this.status eq "shipped") {\n return false;\n }\n }\n}\n
"},"hint":"Registers method(s) that should be called before an object is deleted.\n\n","returntype":"void","slug":"model.beforeDelete","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeDelete","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method before every save (create or update)\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n beforeSave("normalizeEmail");\n }\n\n private function normalizeEmail() {\n this.email = LCase(Trim(this.email));\n }\n}\n\n// 2. Register multiple callback methods as a comma-delimited list\ncomponent extends="Model" {\n function config() {\n beforeSave("stripWhitespace,generateSlug");\n }\n}\n\n// 3. Use the `method` argument alias to register a single callback\ncomponent extends="Model" {\n function config() {\n beforeSave(method="sanitizeContent");\n }\n}\n
"},"hint":"Registers method(s) that should be called before an object is saved.\n\n","returntype":"void","slug":"model.beforeSave","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeSave","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Call a single method before every update\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n beforeUpdate("stampUpdatedBy");\n }\n\n private function stampUpdatedBy() {\n this.updatedBy = session.userId;\n }\n}\n\n// 2. Register multiple callback methods as a comma-delimited list\ncomponent extends="Model" {\n function config() {\n beforeUpdate("validateOwnership,recalculateTotals");\n }\n}\n\n// 3. Use the `method` argument alias to register a single callback\ncomponent extends="Model" {\n function config() {\n beforeUpdate(method="fixObj");\n }\n}\n
"},"hint":"Registers method(s) that should be called before an existing object is updated.\n\n","returntype":"void","slug":"model.beforeUpdate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeUpdate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single method to run before any validation\n// In models/User.cfc\ncomponent extends="Model" {\n function config() {\n beforeValidation("normalizeEmail");\n validatesPresenceOf("email");\n }\n\n private function normalizeEmail() {\n this.email = LCase(Trim(this.email));\n }\n}\n\n// 2. Register multiple methods to run before validation using a comma-delimited list\n// In models/Article.cfc\ncomponent extends="Model" {\n function config() {\n beforeValidation("stripTags,setSlug");\n validatesPresenceOf(properties="title,slug");\n }\n\n private function stripTags() {\n this.title = ReReplace(this.title, "<[^>]*>", "", "all");\n }\n\n private function setSlug() {\n if (!Len(this.slug)) {\n this.slug = LCase(ReReplace(Trim(this.title), "\\s+", "-", "all"));\n }\n }\n}\n\n// 3. Register callbacks across multiple calls (they are stacked in order)\n// In models/Product.cfc\ncomponent extends="Model" {\n function config() {\n beforeValidation("trimFields");\n beforeValidation("setDefaults");\n }\n\n private function trimFields() {\n this.name = Trim(this.name);\n }\n\n private function setDefaults() {\n if (!Len(this.status)) {\n this.status = "draft";\n }\n }\n}\n
"},"hint":"Registers method(s) that should be called before an object is validated.\n\n","returntype":"void","slug":"model.beforeValidation","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeValidation","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single method to run before a new object is validated\n// In models/User.cfc config()\nbeforeValidationOnCreate("sanitizeEmail");\n\n// 2. Register multiple methods to run before a new object is validated\n// In models/Order.cfc config()\nbeforeValidationOnCreate("setDefaultStatus,generateTrackingNumber");\n\n// 3. Use the `method` argument alias instead of `methods`\n// In models/Post.cfc config()\nbeforeValidationOnCreate(method="normalizeSlug");\n
"},"hint":"Registers method(s) that should be called before a new object is validated.\n\n","returntype":"void","slug":"model.beforeValidationOnCreate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeValidationOnCreate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a single method to run before an existing object is validated on update\n// Called inside the model's config() function\nbeforeValidationOnUpdate("sanitizeFields");\n\n// 2. Register multiple methods as a comma-delimited list\nbeforeValidationOnUpdate("sanitizeFields,enforceBusinessRules");\n\n// 3. Use the `method` argument alias for a single callback\nbeforeValidationOnUpdate(method="normalizeEmail");\n
"},"hint":"Registers method(s) that should be called before an existing object is validated.\n\n","returntype":"void","slug":"model.beforeValidationOnUpdate","parameters":[{"default":"","required":false,"hint":"Method name or list of method names that should be called when this callback event occurs in an object's life cycle (can also be called with the `method` argument).","name":"methods","type":"string"}],"availableIn":["model"],"name":"beforeValidationOnUpdate","tags":{"categoryClass":"callbackfunctions","sectionClass":"modelconfiguration","category":"Callback Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Specify that instances of this model belong to an author.\n// (The table for this model should have a foreign key column, typically named `authorId`.)\nbelongsTo("author");\n\n// 2. Override naming conventions by specifying `modelName` and `foreignKey` explicitly.\nbelongsTo(name="bookWriter", modelName="author", foreignKey="authorId");\n\n// 3. Use a LEFT OUTER JOIN instead of the default INNER JOIN when including this association.\nbelongsTo(name="category", joinType="outer");\n\n// 4. Declare a polymorphic belongsTo association (e.g. a Comment that can belong to a Post or a Photo).\n// Wheels will look for `commentableId` and `commentableType` columns on the comments table.\nbelongsTo(name="commentable", polymorphic=true);\n
"},"hint":"Sets up a belongsTo association between this model and the specified one.\nUse this association when this model contains a foreign key referencing another model.\n\n","returntype":"void","slug":"model.belongsTo","parameters":[{"required":true,"hint":"Gives the association a name that you refer to when working with the association (in the `include` argument to `findAll`, to name one example).","name":"name","type":"string"},{"default":"","required":false,"hint":"Name of associated model (usually not needed if you follow Wheels conventions because the model name will be deduced from the `name` argument).","name":"modelName","type":"string"},{"default":"","required":false,"hint":"Foreign key property name (usually not needed if you follow Wheels conventions since the foreign key name will be deduced from the `name` argument).","name":"foreignKey","type":"string"},{"default":"","required":false,"hint":"Column name to join to if not the primary key (usually not needed if you follow Wheels conventions since the join key will be the table's primary key/keys).","name":"joinKey","type":"string"},{"default":"inner","required":false,"hint":"Use to set the join type when joining associated tables. Possible values are `inner` (for `INNER JOIN`) and `outer` (for `LEFT OUTER JOIN`).","name":"joinType","type":"string"},{"default":false,"required":false,"hint":"Set to `true` to declare a polymorphic `belongsTo` association. The foreign key defaults to `{name}Id` and a `{name}Type` column is used to store the owning model name at runtime.","name":"polymorphic","type":"boolean"},{"default":"","required":false,"hint":"The column that stores the owning model's name in a polymorphic association. Defaults to `{name}Type`. Pass it, with `foreignKey`, when the columns are named differently, e.g. `notable_type` / `notable_id` as `t.references(polymorphic = true)` writes them when `useUnderscoreReferenceColumns` is on.","name":"foreignType","type":"string"}],"availableIn":["model"],"name":"belongsTo","tags":{"categoryClass":"associationfunctions","sectionClass":"modelconfiguration","category":"Association Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single bigInteger column to a new table\nt = createTable(name='events');\n\tt.bigInteger(columnNames='externalId');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple bigInteger columns at once\nt = createTable(name='analytics');\n\tt.bigInteger(columnNames='pageViews,uniqueVisitors', default=0, allowNull=false);\n\tt.string(columnNames='path', limit=500, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a bigInteger column with a limit and default when altering an existing table\nt = changeTable(name='orders');\n\tt.bigInteger(columnNames='totalCents', default=0, allowNull=false);\nt.change();\n
"},"hint":"Adds integer columns to table definition.\n\n","returntype":"any","slug":"tabledefinition.bigInteger","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"limit","type":"numeric"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"},{"required":false,"name":"unsigned","type":"boolean"}],"availableIn":["tabledefinition"],"name":"bigInteger","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single binary column to a new table\nt = createTable(name='attachments');\n\tt.string(columnNames='filename', limit=255, allowNull=false);\n\tt.binary(columnNames='fileData');\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple binary columns at once\nt = createTable(name='media');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.binary(columnNames='thumbnail,fullImage', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a binary column with a default when altering an existing table\nt = changeTable(name='documents');\n\tt.binary(columnNames='rawContent', allowNull=true);\nt.change();\n
"},"hint":"Adds binary columns to table definition.\n\n","returntype":"any","slug":"tabledefinition.binary","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"}],"availableIn":["tabledefinition"],"name":"binary","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single boolean column to a new table\nt = createTable(name='products');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.boolean(columnNames='isActive', default=1, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple boolean columns at once\nt = createTable(name='users');\n\tt.string(columnNames='email', limit=255, allowNull=false);\n\tt.boolean(columnNames='isAdmin,isVerified,isActive', default=0, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a boolean column to an existing table\nt = changeTable(name='articles');\n\tt.boolean(columnNames='isPublished', default=0, allowNull=false);\nt.change();\n
"},"hint":"Adds boolean columns to table definition.\n\n","returntype":"any","slug":"tabledefinition.boolean","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"}],"availableIn":["tabledefinition"],"name":"boolean","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic submit button inside a form\n#startFormTag(action="create")#\n #buttonTag(content="Save changes", value="save")#\n#endFormTag()#\n<!--- Produces: <button type="submit" value="save">Save changes</button> --->\n\n// 2. Reset button to clear form fields\n#buttonTag(content="Clear form", type="reset")#\n<!--- Produces: <button type="reset" value="save">Clear form</button> --->\n\n// 3. Plain button (no form submission) with a CSS class and id\n#buttonTag(content="Open dialog", type="button", value="open", class="btn btn-secondary", id="openDialogBtn")#\n<!--- Produces: <button type="button" value="open" class="btn btn-secondary" id="openDialogBtn">Open dialog</button> --->\n\n// 4. Submit button wrapped in a paragraph using prepend and append\n#buttonTag(content="Submit", value="submit", prepend="<p>", append="</p>")#\n<!--- Produces: <p><button type="submit" value="submit">Submit</button></p> --->\n\n// 5. Image button (renders an img tag inside the button element)\n#buttonTag(content="", image="submit-icon.png", value="save")#\n<!--- Produces: <button type="submit" value="save"><img src="/images/submit-icon.png" alt="Submit Icon" /></button> --->\n
"},"hint":"Builds and returns a string containing a button form control.\n\n","returntype":"string","slug":"controller.buttonTag","parameters":[{"default":"Save changes","required":false,"hint":"Content to display inside the button.","name":"content","type":"string"},{"default":"submit","required":false,"hint":"The type for the button: `button`, `reset`, or `submit`.","name":"type","type":"string"},{"default":"save","required":false,"hint":"The value of the button when submitted.","name":"value","type":"string"},{"default":"","required":false,"hint":"File name of the image file to use in the button form control.","name":"image","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"buttonTag","tags":{"categoryClass":"generalformfunctions","sectionClass":"viewhelpers","category":"General Form Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic button that submits to a controller/action\n#buttonTo(text="Delete Account", controller="account", action="delete")#\n<!--- Outputs: <form action="/account/delete" method="post"><button type="submit">Delete Account</button></form> --->\n\n// 2. If you're already in the `account` controller, CFWheels will assume the current controller\n#buttonTo(text="Delete Account", action="delete")#\n<!--- Outputs: <form action="/account/delete" method="post"><button type="submit">Delete Account</button></form> --->\n\n// 3. Use `method` to send a DELETE request (a hidden `_method` field is added automatically)\n#buttonTo(text="Remove Post", controller="blog", action="delete", key=99, method="delete")#\n<!--- Outputs: <form action="/blog/delete/99" method="post"><input type="hidden" name="_method" value="delete" /><button type="submit">Remove Post</button></form> --->\n\n// 4. Use a named route configured in `config/routes.cfm`\n#buttonTo(text="Archive", route="archivePost", postId=12)#\n\n// 5. Show a "please wait" state by disabling the button on click — pass extra attributes to the button using the `input` prefix\n#buttonTo(text="Place Order", action="checkout", inputId="checkout-btn", inputClass="btn btn-primary", inputData-disable-with="Processing...")#\n\n// 6. Use an image instead of text for the button\n#buttonTo(image="icons/trash.png", action="destroy", key=params.id, method="delete")#\n
"},"hint":"Creates a form containing a single button that submits to the URL. Note: Pass any additional arguments by prefixing them with \"input\" like inputClass, inputRel, and inputId, and the generated tag will also include those values as HTML attributes.\nThe URL is built the same way as the linkTo function.\n\n","returntype":"string","slug":"controller.buttonTo","parameters":[{"default":"","required":false,"hint":"The text content of the button.","name":"text","type":"string"},{"default":"","required":false,"hint":"If you want to use an image for the button pass in the link to it here (relative from the `images` folder).","name":"image","type":"string"},{"default":"","required":false,"hint":"Name of a route that you have configured in `config/routes.cfm`.","name":"route","type":"string"},{"default":"","required":false,"hint":"Name of the controller to include in the URL.","name":"controller","type":"string"},{"default":"","required":false,"hint":"Name of the action to include in the URL.","name":"action","type":"string"},{"default":"","required":false,"hint":"Key(s) to include in the URL.","name":"key","type":"any"},{"default":"","required":false,"hint":"Any additional parameters to be set in the query string (example: `wheels=cool&x=y`). Please note that Wheels uses the `&` and `=` characters to split the parameters and encode them properly for you. However, if you need to pass in `&` or `=` as part of the value, then you need to encode them (and only them), example: `a=cats%26dogs%3Dtrouble!&b=1`.","name":"params","type":"string"},{"default":"","required":false,"hint":"Sets an anchor name to be appended to the path.","name":"anchor","type":"string"},{"required":false,"hint":"The type of `method` to use in the `form` tag (`delete`, `get`, `patch`, `post`, and `put` are the options).","name":"method","type":"string"},{"default":true,"required":false,"hint":"If `true`, returns only the relative URL (no protocol, host name or port).","name":"onlyPath","type":"boolean"},{"default":"","required":false,"hint":"Set this to override the current host.","name":"host","type":"string"},{"default":"","required":false,"hint":"Set this to override the current protocol.","name":"protocol","type":"string"},{"default":0,"required":false,"hint":"Set this to override the current port number.","name":"port","type":"numeric"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":true,"required":false,"hint":"Set to `false` to leave out the hidden authenticity token field. Do this for every form in cached markup that other visitors receive, so the cache never holds a session's token. Supply the token at request time instead: the `X-CSRF-Token` header (Turbo sends it from `csrfMetaTags()`; a `fetch()` must set it), or a script that copies the `csrf-token` meta tag into the form on submit.","name":"authenticityToken","type":"boolean"}],"availableIn":["controller"],"name":"buttonTo","tags":{"categoryClass":"linkfunctions","sectionClass":"viewhelpers","category":"Link Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Cache the `termsOfUse` action for the default 60 minutes.\ncaches("termsOfUse");\n\n// 2. Cache two actions for 30 minutes.\ncaches(actions="browseByUser,browseByTitle", time=30);\n\n// 3. Cache the `termsOfUse` and `codeOfConduct` actions, including their filters.\ncaches(actions="termsOfUse,codeOfConduct", static=true);\n\n// 4. Cache content separately based on region.\ncaches(action="home", appendToKey="request.region");\n
"},"hint":"Tells Wheels to cache one or more actions.\n\n","returntype":"void","slug":"controller.caches","parameters":[{"default":"","required":false,"hint":"Action(s) to cache. This argument is also aliased as `actions`.","name":"action","type":"string"},{"default":60,"required":false,"hint":"Minutes to cache the action(s) for.","name":"time","type":"numeric"},{"default":false,"required":false,"hint":"Set to `true` to tell Wheels that this is a static page and that it can skip running the controller filters (before and after filters set on actions). Please note that the `onSessionStart` and `onRequestStart` events still execute though.","name":"static","type":"boolean"},{"default":"","required":false,"hint":"List of variables to be evaluated at runtime and included in the cache key so that content can be cached separately.","name":"appendToKey","type":"string"}],"availableIn":["controller"],"name":"caches","tags":{"categoryClass":"configurationfunctions","sectionClass":"controller","category":"Configuration Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Inspect all registered callbacks for a model\ninfo = model("Order").callbackInfo();\n// info is a struct keyed by callback type, each containing an array of method names:\n// {\n// beforeSave: ["stampUpdatedAt"],\n// afterCreate: ["sendConfirmationEmail"],\n// afterSave: ["clearCacheEntries"],\n// beforeValidation: [],\n// beforeValidationOnCreate: [],\n// afterValidation: [],\n// afterFind: [],\n// ...\n// }\n\n// 2. Check whether a specific callback type has any registered methods\ninfo = model("User").callbackInfo();\nif (arrayLen(info.beforeDelete)) {\n writeOutput("User model has beforeDelete callbacks.");\n}\n\n// 3. Loop over all callback types and their methods for debugging\ninfo = model("Post").callbackInfo();\nfor (callbackType in info) {\n for (methodName in info[callbackType]) {\n writeOutput(callbackType & ": " & methodName);\n }\n}\n
"},"hint":"Returns a struct containing all callback definitions for this model, keyed by callback type\n(e.g., beforeSave, afterCreate). Each callback type contains an array of callback method names.\n\n","returntype":"struct","slug":"model.callbackInfo","parameters":[],"availableIn":["model"],"name":"callbackInfo","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Boolean policy check for conditionals and views (views run in the\ncontroller's variables scope, so can() is available in templates\nautomatically):\n\n##linkTo(text=\"Edit\", route=\"editPost\", key=post.id)##\n\nReturns false (deny) for a guest, for an empty record, and for a policy\nmethod that does not return boolean true. A missing method throws\nWheels.Policy.UnknownAction. A missing policy class still throws\nWheels.Policy.NotDefined in development/testing so typos fail loud; in\nproduction it returns false.\n\n","returntype":"boolean","slug":"controller.can","parameters":[{"required":true,"hint":"The policy method to check.","name":"action","type":"string"},{"default":"","required":false,"hint":"The model instance (or model class / model name string) to check against. Empty string denies.","name":"record","type":"any"}],"availableIn":["controller"],"name":"can","tags":{"categoryClass":"authorizationfunctions","sectionClass":"controller","category":"Authorization Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Capitalize the first character of a sentence\nresult = capitalize("wheels is a framework");\n// result -> "Wheels is a framework"\n\n// 2. Capitalize a lowercase word\nresult = capitalize("hello");\n// result -> "Hello"\n\n// 3. Returns an already-capitalized string unchanged\nresult = capitalize("CFWheels");\n// result -> "CFWheels"\n
"},"hint":"Capitalizes the first character of the supplied string.\n\n","returntype":"string","slug":"controller.capitalize","parameters":[{"required":true,"hint":"String to capitalize.","name":"text","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"capitalize","tags":{"categoryClass":"stringfunctions","sectionClass":"globalhelpers","category":"String Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Alter existing columns on a table (default behavior — modifies columns that already exist)\nt = changeTable(name='users');\n\tt.string(columnNames='email', limit=255, allowNull=false);\n\tt.boolean(columnNames='active', default=true, allowNull=false);\nt.change();\n\n// 2. Add new columns to an existing table using addColumns=true\nt = changeTable(name='products');\n\tt.string(columnNames='sku', limit=100, allowNull=false);\n\tt.decimal(columnNames='discountPrice', precision=10, scale=2, allowNull=true);\nt.change(addColumns=true);\n\n// 3. Add a foreign key reference column to an existing table\nt = changeTable(name='orders');\n\tt.references(columnNames='customer', allowNull=false);\nt.change(addColumns=true);\n
"},"hint":"alters existing table in the database\n\n","returntype":"void","slug":"tabledefinition.change","parameters":[{"default":"false","required":false,"name":"addColumns","type":"boolean"}],"availableIn":["tabledefinition"],"name":"change","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Change a string column's length limit\nchangeColumn(table="members", columnName="status", columnType="string", limit=50);\n\n// 2. Change a column type and set a default value\nchangeColumn(table="orders", columnName="quantity", columnType="integer", default=1);\n\n// 3. Change a decimal column with precision and scale\nchangeColumn(table="products", columnName="price", columnType="decimal", precision=10, scale=2, allowNull=false);\n\n// 4. Change a text column and explicitly allow NULL values\nchangeColumn(table="articles", columnName="summary", columnType="text", allowNull=true);\n
"},"hint":"changes a column definition\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.changeColumn","parameters":[{"required":true,"hint":"The Name of the table where the column is","name":"table","type":"string"},{"required":false,"hint":"The name of the column","name":"columnName","type":"string"},{"required":false,"hint":"Modern alias for `columnName` (matches the plural form every TableDefinition column helper accepts). Pass one or the other — not both.","name":"columnNames","type":"string"},{"required":true,"hint":"The type of the column","name":"columnType","type":"string"},{"default":"","required":false,"hint":"The name of the column which this column should be inserted after","name":"afterColumn","type":"string"},{"default":"","required":false,"hint":"Name for reference column, see documentation for references function, required if columnType is 'reference'","name":"referenceName","type":"string"},{"required":false,"hint":"Default value for this column","name":"default","type":"any"},{"required":false,"hint":"Whether to allow NULL values","name":"allowNull","type":"boolean"},{"required":false,"hint":"Character or integer size limit for column","name":"limit","type":"numeric"},{"required":false,"hint":"(For decimal type) the maximum number of digits allow","name":"precision","type":"numeric"},{"required":false,"hint":"(For decimal type) the number of digits to the right of the decimal point","name":"scale","type":"numeric"},{"default":"false","required":false,"hint":"if true, attempts to add columns and database will likely throw an error if column already exists","name":"addColumns","type":"boolean"}],"availableIn":["migration"],"name":"changeColumn","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the previous value of a changed property\nuser = model("User").findByKey(params.userId);\nuser.email = params.newEmail;\n\n// Returns the original email address before it was changed\noldEmail = user.changedFrom("email");\n// oldEmail -> "original@example.com"\n\n// 2. Use the dynamic shorthand method (equivalent to the above)\noldEmail = user.emailChangedFrom();\n\n// 3. Check if a property changed before accessing the previous value\nuser = model("User").findByKey(params.userId);\nuser.firstName = params.firstName;\n\nif (user.hasChanged("firstName")) {\n\toldName = user.changedFrom("firstName");\n\t// oldName -> "Jane"\n}\n// Returns empty string if property has not changed or no previous value exists\n
"},"hint":"Returns the previous value of a property that has changed.\nReturns an empty string if no previous value exists.\nWheels will keep a note of the previous property value until the object is saved to the database.\n\n","returntype":"string","slug":"model.changedFrom","parameters":[{"required":true,"hint":"Name of property to get the previous value for.","name":"property","type":"string"}],"availableIn":["model"],"name":"changedFrom","tags":{"categoryClass":"changefunctions","sectionClass":"modelobject","category":"Change Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Find a member, change some properties, then inspect which ones have changed\nmember = model("member").findByKey(params.memberId);\nmember.firstName = params.newFirstName;\nmember.email = params.newEmail;\nchanged = member.changedProperties();\n// changed -> "firstName,email"\n\n// 2. Only save when there are actually unsaved changes\nuser = model("User").findByKey(params.userId);\nuser.lastName = params.lastName;\nif (Len(user.changedProperties())) {\n user.save();\n}\n\n// 3. Use changedProperties() alongside changedFrom() to build an audit log entry\npost = model("Post").findByKey(params.postId);\npost.title = params.title;\npost.body = params.body;\nchangedList = post.changedProperties();\nfor (prop in ListToArray(changedList)) {\n writeOutput("Property '#prop#' was '#post.changedFrom(prop)#', now '#post[prop]#'.");\n}\n
"},"hint":"Returns a list of the object properties that have been changed but not yet saved to the database.\n\n","returntype":"string","slug":"model.changedProperties","parameters":[],"availableIn":["model"],"name":"changedProperties","tags":{"categoryClass":"changefunctions","sectionClass":"modelobject","category":"Change Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a new string column to an existing table\nt = changeTable(name="employees");\nt.string(columnNames="fullName", default="", allowNull=true, limit=255);\nt.change();\n\n// 2. Modify multiple columns at once (change type and nullability)\nt = changeTable(name="products");\nt.integer(columnNames="stock", default=0, allowNull=false);\nt.boolean(columnNames="active", default=true, allowNull=false);\nt.change();\n\n// 3. Add a new column using addColumns=true so the migration fails gracefully if the column already exists\nt = changeTable(name="orders");\nt.datetime(columnNames="shippedAt", allowNull=true);\nt.change(addColumns=true);\n
"},"hint":"Creates a table definition object to store modifications to table properties\nOnly available in a migration CFC\n\n","returntype":"TableDefinition","slug":"migration.changeTable","parameters":[{"required":true,"hint":"Name of the table to set change properties on","name":"name","type":"string"}],"availableIn":["migration"],"name":"changeTable","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Generate a 'script' tag that creates an EventSource for a channel.\nConvenience view helper for quickly wiring up SSE in templates.","returntype":"string","slug":"controller.channelSSETag","parameters":[{"required":true,"hint":"The channel name.","name":"channel","type":"string"},{"default":"","required":false,"hint":"Named route for the SSE endpoint.","name":"route","type":"string"},{"default":"","required":false,"hint":"Controller name (used with action if no route).","name":"controller","type":"string"},{"default":"stream","required":false,"hint":"Action name (default \"stream\").","name":"action","type":"string"},{"default":"","required":false,"hint":"Comma-delimited list of event types.","name":"events","type":"string"}],"availableIn":["controller"],"name":"channelSSETag","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single char column to a new table\nt = createTable(name='countries');\n\tt.char(columnNames='code', limit=2, allowNull=false);\n\tt.string(columnNames='name', limit=100, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple char columns at once\nt = createTable(name='products');\n\tt.char(columnNames='sku,barcode', limit=12, allowNull=false);\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a char column with a default value when altering an existing table\nt = changeTable(name='orders');\n\tt.char(columnNames='statusCode', limit=1, default='N', allowNull=false);\nt.change();\n
"},"hint":"adds char columns to table definition\n\n","returntype":"any","slug":"tabledefinition.char","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"limit","type":"any"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"}],"availableIn":["tabledefinition"],"name":"char","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic check box bound to a boolean model property\n#checkBox(objectName="photo", property="isPublic", label="Display this photo publicly.")#\n\n// 2. Custom checked and unchecked values (e.g. "yes" / "no" instead of 1 / 0)\n#checkBox(objectName="user", property="agreedToTerms", checkedValue="yes", uncheckedValue="no", label="I agree to the terms of service.")#\n\n// 3. Check boxes for a nested association (photos belonging to a user)\n<cfloop from="1" to="#ArrayLen(user.photos)#" index="i">\n #checkBox(objectName="user", association="photos", position=i, property="isPublic", label="Make public: #user.photos[i].title#")#\n</cfloop>\n
"},"hint":"Builds and returns a string containing a check box form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.checkBox","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":1,"required":false,"hint":"Value of check box in its checked state.","name":"checkedValue","type":"string"},{"default":0,"required":false,"hint":"The value of the check box when it's on the unchecked state.","name":"uncheckedValue","type":"string"},{"default":"useDefaultLabel","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"checkBox","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage with a label and a pre-checked state\n<cfoutput>\n\t#checkBoxTag(name="subscribe", value="1", label="Subscribe to our newsletter", checked=true)#\n</cfoutput>\n\n// 2. Render an unchecked check box that also submits a value when unchecked\n<cfoutput>\n\t#checkBoxTag(name="agreeToTerms", value="1", uncheckedValue="0", label="I agree to the terms")#\n</cfoutput>\n\n// 3. Loop over a query to render one check box per option, checking those already selected\n// Controller\ntoppings = model("Topping").findAll(order="name");\nselectedIds = "2,5,9"; // e.g. previously saved topping IDs as a comma-delimited list\n\n// View\n<cfoutput query="toppings">\n\t#checkBoxTag(\n\t\tname = "toppingIds",\n\t\tvalue = toppings.id,\n\t\tlabel = toppings.name,\n\t\tchecked = listFindNoCase(selectedIds, toppings.id) GT 0\n\t)#\n</cfoutput>\n
"},"hint":"Builds and returns a string containing a check box form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.checkBoxTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":false,"required":false,"hint":"Whether or not the check box should be checked by default.","name":"checked","type":"boolean"},{"default":1,"required":false,"hint":"Value of check box in its checked state.","name":"value","type":"string"},{"default":"","required":false,"hint":"The value of the check box when it's on the unchecked state.","name":"uncheckedValue","type":"string"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"checkBoxTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Inspect all metadata for the User model\ninfo = model("User").classInfo();\n// info.modelName -> "User"\n// info.tableName -> "users"\n// info.primaryKeys -> "id"\n// info.propertyNames -> "id,firstName,lastName,email,createdAt,updatedAt"\n// info.properties -> struct of column/type metadata keyed by property name\n// info.calculatedProperties -> struct of SQL-expression properties keyed by property name\n// info.associations -> struct of association definitions (belongsTo, hasMany, etc.)\n// info.validations -> struct keyed by trigger (onSave, onCreate, onUpdate) with arrays of rules\n// info.enums -> struct of enum definitions keyed by property name\n// info.scopes -> struct of named scope definitions\n// info.callbacks -> struct of callback arrays keyed by callback type (beforeSave, afterCreate, etc.)\n// info.softDeletion -> false (true when the model has a deletedAt column)\n\n// 2. List all association names and their types\ninfo = model("Article").classInfo();\n\nfor (assocName in info.associations) {\n assoc = info.associations[assocName];\n writeOutput(assocName & " (" & assoc.type & ")");\n}\n\n// 3. Check soft-deletion and enumerate registered callbacks\ninfo = model("Post").classInfo();\n\nif (info.softDeletion) {\n writeOutput("Post uses soft deletion.");\n}\n\nfor (callbackType in info.callbacks) {\n methods = info.callbacks[callbackType];\n writeOutput(callbackType & ": " & arrayToList(methods));\n}\n\n// 4. Inspect calculated properties defined on the model\ninfo = model("Order").classInfo();\n\nfor (propName in info.calculatedProperties) {\n calcProp = info.calculatedProperties[propName];\n writeOutput(propName & " => " & calcProp.sql);\n}\n
"},"hint":"Returns a comprehensive struct of all model metadata suitable for code generation and introspection tools.\nIncludes model name, table name, primary keys, properties, associations, validations, enums, scopes, and callbacks.\n\n","returntype":"struct","slug":"model.classInfo","parameters":[],"availableIn":["model"],"name":"classInfo","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Clear all cached action metadata for the current controller.\nclearCachableActions();\n\n// 2. Clear the cached metadata for a single action.\nclearCachableActions(action="termsOfUse");\n\n// 3. Clear the cached metadata for a list of specific actions.\nclearCachableActions(action="browseByUser,browseByTitle");\n
"},"hint":"Clears cached action metadata for current controller.\n\n","returntype":"void","slug":"controller.clearCachableActions","parameters":[{"default":"","required":false,"hint":"Optional. A single action or list of actions to clear. If not provided, clears all cached actions of current controller.","name":"action","type":"string"}],"availableIn":["controller"],"name":"clearCachableActions","tags":{"categoryClass":"configurationfunctions","sectionClass":"controller","category":"Configuration Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Clear change tracking for a single property\n// Convert startTime to UTC in an afterFind callback, then tell Wheels to treat\n// the converted value as the "original" so it won't be flagged as changed or\n// saved unnecessarily.\nthis.startTime = dateConvert("Local2UTC", this.startTime);\nthis.clearChangeInformation(property="startTime");\n\n// 2. Clear change tracking for all properties at once\n// After manually adjusting values in an afterFind callback, reset Wheels'\n// internal state so none of the touched properties appear as dirty.\nthis.clearChangeInformation();\n\n// 3. Typical afterFind callback usage in a model\n// In User.cfc config():\n// afterFind("normalizeTimestamps");\n// The callback method:\nfunction normalizeTimestamps() {\n if (structKeyExists(this, "createdAt")) {\n this.createdAt = dateConvert("Local2UTC", this.createdAt);\n }\n if (structKeyExists(this, "updatedAt")) {\n this.updatedAt = dateConvert("Local2UTC", this.updatedAt);\n }\n // Mark both properties as clean so hasChanged() returns false\n // and save() won't push them back to the database.\n this.clearChangeInformation(property="createdAt");\n this.clearChangeInformation(property="updatedAt");\n}\n
"},"hint":"Clears all internal knowledge of the current state of the object, including what the last save\nchanged (savedChanges()).\n\n","returntype":"void","slug":"model.clearChangeInformation","parameters":[{"required":false,"hint":"string false Name of property to clear information for.","name":"property","type":"string"}],"availableIn":["model"],"name":"clearChangeInformation","tags":{"categoryClass":"changefunctions","sectionClass":"modelobject","category":"Change Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Clear all errors on the object\nthis.clearErrors();\n\n// 2. Clear all errors set on the `firstName` property\nthis.clearErrors(property="firstName");\n\n// 3. Clear only errors that were set with a specific error name\nthis.clearErrors(name="invalidFormat");\n\n// 4. Clear errors on a specific property that were also set with a specific name\nthis.clearErrors(property="email", name="duplicateEmail");\n
"},"hint":"Clears out all errors set on the object or only the ones set for a specific property or name.\n\n","returntype":"void","slug":"model.clearErrors","parameters":[{"default":"","required":false,"hint":"Specify a property name here if you want to clear all errors set on that property.","name":"property","type":"string"},{"default":"","required":false,"hint":"Specify an error name here if you want to clear all errors set with that error name.","name":"name","type":"string"}],"availableIn":["model"],"name":"clearErrors","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Close an SSE streaming connection.","returntype":"void","slug":"controller.closeSSEStream","parameters":[{"required":true,"hint":"The writer object returned by initSSEStream().","name":"writer","type":"any"}],"availableIn":["controller"],"name":"closeSSEStream","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\n// 1. Add a search route acting on the photos collection (GET /photos/search)\nmapper()\n .resources(name="photos", nested=true)\n .collection()\n .get("search")\n .end()\n .end()\n.end();\n\n// 2. Add multiple collection routes (GET /articles/featured, POST /articles/bulk-delete)\nmapper()\n .resources(name="articles", nested=true)\n .collection()\n .get("featured")\n .post("bulkDelete")\n .end()\n .end()\n.end();\n\n</cfscript>\n
"},"hint":"A collection route doesn't require an id because it acts on a collection of objects.\nphotos/search is an example of a collection route, because it acts on (and displays) a collection of objects.\n\n","returntype":"struct","slug":"mapper.collection","parameters":[],"availableIn":["mapper"],"name":"collection","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic color picker bound to a model object property\n#colorField(objectName="product", property="themeColor")#\n\n// 2. Color picker with a custom label and a CSS class\n#colorField(objectName="user", property="profileColor", label="Profile Color", class="color-picker")#\n\n// 3. Color pickers for nested properties on a hasMany association (e.g., palette swatches)\n<cfloop from="1" to="#ArrayLen(design.swatches)#" index="i">\n\t#colorField(objectName="design", association="swatches", position="#i#", property="hexValue", label="Swatch ##i#")#\n</cfloop>
"},"hint":"Builds and returns a string containing a color picker form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.colorField","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":"useDefaultLabel","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"colorField","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic color picker with a default value\n#colorFieldTag(name="brandColor", value="##FF5733")#\n\n// 2. Color picker with a label and a CSS class\n#colorFieldTag(name="themeColor", value="##336699", label="Theme Color", class="color-input")#\n\n// 3. Color picker with label placement and prepend/append wrappers\n#colorFieldTag(name="highlightColor", label="Highlight", labelPlacement="before", prepend="<div class=""field"">", append="</div>")#\n
"},"hint":"Builds and returns a string containing a color picker form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.colorFieldTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value to populate in tag's value attribute.","name":"value","type":"string"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"colorFieldTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a generic string column to a new table\nt = createTable(name='articles');\n\tt.column(columnName='title', columnType='string', limit=255, allowNull=false);\n\tt.column(columnName='body', columnType='text');\n\tt.timestamps();\nt.create();\n\n// 2. Add a column with a default value and precision/scale (for decimals)\nt = createTable(name='products');\n\tt.column(columnName='name', columnType='string', limit=100, allowNull=false);\n\tt.column(columnName='price', columnType='decimal', precision=10, scale=2, default='0.00', allowNull=false);\n\tt.column(columnName='stock', columnType='integer', default='0', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a custom column when altering an existing table\nt = changeTable(name='users');\n\tt.column(columnName='bio', columnType='text', allowNull=true);\nt.change();\n
"},"hint":"Adds a column to table definition.\n\n","returntype":"any","slug":"tabledefinition.column","parameters":[{"required":true,"name":"columnName","type":"string"},{"required":true,"name":"columnType","type":"string"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"},{"required":false,"name":"limit","type":"any"},{"required":false,"name":"precision","type":"numeric"},{"required":false,"name":"scale","type":"numeric"}],"availableIn":["tabledefinition"],"name":"column","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all column metadata for a property\ndata = model("User").columnDataForProperty("email");\n// Returns a struct like:\n// { column: "email", validationtype: "string", label: "Email" }\n\n// 2. Inspect metadata before using it\ndata = model("Product").columnDataForProperty("price");\nif (isStruct(data)) {\n writeOutput("Column: " & data.column);\n writeOutput("Validation type: " & data.validationtype);\n}\n\n// 3. Handle the false return when the property does not exist on the model\ndata = model("User").columnDataForProperty("nonExistentProp");\nif (!isStruct(data)) {\n writeOutput("Property not found on this model.");\n}\n
"},"hint":"Returns a struct with data for the named property.\n\n","returntype":"any","slug":"model.columnDataForProperty","parameters":[{"required":true,"hint":"Name of property to inspect.","name":"property","type":"string"}],"availableIn":["model"],"name":"columnDataForProperty","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the column name mapped to a model property\ncol = model("User").columnForProperty("firstName");\n// col -> "first_name"\n\n// 2. Check the column for a property before building a raw SQL fragment\ncol = model("Order").columnForProperty("placedAt");\nif (col != false) {\n writeOutput("Column in the database: " & col);\n}\n\n// 3. Returns false when the property does not exist on the model\ncol = model("User").columnForProperty("nonExistentProperty");\n// col -> false\n
"},"hint":"Returns the column name mapped for the named model property.\n\n","returntype":"any","slug":"model.columnForProperty","parameters":[{"required":true,"hint":"Name of property to inspect.","name":"property","type":"string"}],"availableIn":["model"],"name":"columnForProperty","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the list of column names for the User model\ncols = model("User").columnNames();\n// cols -> "id,firstName,lastName,email,createdAt,updatedAt,deletedAt"\n\n// 2. Check whether a specific column exists in the table\nif (listFindNoCase(model("User").columnNames(), "email")) {\n writeOutput("The users table has an email column.");\n}\n\n// 3. Iterate over every column name\nfor (col in listToArray(model("User").columnNames())) {\n writeOutput(col);\n}\n
"},"hint":"Returns a list of column names in the table mapped to this model.\nThe list is ordered according to the columns' ordinal positions in the database table.\n\n","returntype":"string","slug":"model.columnNames","parameters":[],"availableIn":["model"],"name":"columnNames","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all column names for the User model\ncols = model("User").columns();\n// cols -> ["id", "firstName", "lastName", "email", "createdAt", "updatedAt", "deletedAt"]\n\n// 2. Check whether a specific column exists in the table\ncols = model("User").columns();\nif (arrayFindNoCase(cols, "deletedAt")) {\n writeOutput("Soft-delete column is present");\n}\n\n// 3. Iterate over all columns and output their names\ncols = model("User").columns();\nfor (col in cols) {\n writeOutput(col);\n}\n
"},"hint":"Returns an array of columns names for the table associated with this class.\nDoes not include calculated properties that will be generated by the Wheels ORM.\n\n","returntype":"array","slug":"model.columns","parameters":[],"availableIn":["model"],"name":"columns","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check if two model objects are the same instance\nuser1 = model("User").findByKey(1);\nuser2 = model("User").findByKey(1);\nuser3 = user1;\n\nisSame = user1.compareTo(user2);\n// isSame -> false (two separate fetches produce distinct instances)\n\nisSame = user1.compareTo(user3);\n// isSame -> true (user3 is the same object reference as user1)\n\n// 2. Guard against processing the same object twice in a loop\nusers = model("User").findAll(returnAs="objects");\ncurrentUser = model("User").findByKey(session.userId);\n\nfor (u in users) {\n if (!u.compareTo(currentUser)) {\n // process all users except the currently logged-in one\n sendNotification(u);\n }\n}\n
"},"hint":"Pass in another model object to see if the two objects are the same.\n\n","returntype":"boolean","slug":"model.compareTo","parameters":[{"required":true,"name":"object","type":"component"}],"availableIn":["model"],"name":"compareTo","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelobject","category":"Miscellaneous Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\nmapper()\n // 1. Constrain a dynamic segment to digits only\n .constraints(id="[0-9]+")\n .resources(name="articles")\n .end()\n\n // 2. Constrain multiple segments — numeric id and lowercase-only slug\n .constraints(id="[0-9]+", slug="[a-z\\-]+")\n .get(name="article", to="articles##show")\n .get(name="articleBySlug", to="articles##showBySlug")\n .end()\n.end();\n\n</cfscript>\n
"},"hint":"Set variable patterns to use for matching.\n\n","returntype":"struct","slug":"mapper.constraints","parameters":[],"availableIn":["mapper"],"name":"constraints","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Store sidebar content for use in the layout\n<cfsavecontent variable="mySidebar">\n <nav>Recent Posts</nav>\n</cfsavecontent>\n<cfset contentFor(sidebar=mySidebar)>\n\n<!--- In your layout, output the stored section --->\n<cfoutput>\n #includeContent("sidebar")#\n #includeContent()#\n</cfoutput>\n\n// 2. Push content onto a stack — multiple calls append by default\n<cfsavecontent variable="firstScript">\n <script src="/js/base.js"></script>\n</cfsavecontent>\n<cfset contentFor(scripts=firstScript)>\n\n<cfsavecontent variable="secondScript">\n <script src="/js/page.js"></script>\n</cfsavecontent>\n<cfset contentFor(scripts=secondScript)>\n\n<!--- Both scripts are rendered in order --->\n<cfoutput>#includeContent("scripts")#</cfoutput>\n\n// 3. Prepend content to an existing section using position="first"\n<cfsavecontent variable="criticalScript">\n <script src="/js/critical.js"></script>\n</cfsavecontent>\n<cfset contentFor(position="first", scripts=criticalScript)>\n\n// 4. Overwrite an entire section with overwrite="all"\n<cfsavecontent variable="replacementSidebar">\n <nav>Admin Sidebar</nav>\n</cfsavecontent>\n<cfset contentFor(overwrite="all", sidebar=replacementSidebar)>\n\n// 5. Overwrite a specific position in the stack (position=1, overwrite=true)\n<cfsavecontent variable="updatedScript">\n <script src="/js/updated.js"></script>\n</cfsavecontent>\n<cfset contentFor(position=1, overwrite=true, scripts=updatedScript)>\n
"},"hint":"Used to store a section's output for rendering within a layout.\nThis content store acts as a stack, so you can store multiple pieces of content for a given section.\n\n","returntype":"void","slug":"controller.contentFor","parameters":[{"default":"last","required":false,"hint":"The position in the section's stack where you want the content placed. Valid values are `first`, `last`, or the numeric position.","name":"position","type":"any"},{"default":"false","required":false,"hint":"Whether or not to overwrite any of the content. Valid values are `false`, `true`, or `all`.","name":"overwrite","type":"any"}],"availableIn":["controller"],"name":"contentFor","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Include the view's generated content inside a layout file\n// In `app/views/layout.cfm`, place this where the page body should appear\n<!DOCTYPE html>\n<html>\n<head>\n <title>My App</title>\n</head>\n<body>\n #contentForLayout()#\n</body>\n</html>\n\n// 2. Combine with includeContent to render named sections alongside the body\n// In `app/views/layout.cfm`\n<html>\n<head>\n #includeContent("head")#\n</head>\n<body>\n #contentForLayout()#\n #includeContent("footer")#\n</body>\n</html>\n
"},"hint":"Includes content for the body section, which equates to the output generated by the view template run by the request.\n\n","returntype":"string","slug":"controller.contentForLayout","parameters":[],"availableIn":["controller"],"name":"contentForLayout","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Considered deprecated as this doesn't conform to RESTful routing principles; Try not to use this.\n\n","returntype":"struct","slug":"mapper.controller","parameters":[{"required":true,"name":"controller","type":"string"},{"default":"[runtime expression]","required":false,"name":"name","type":"string"},{"default":"[runtime expression]","required":false,"name":"path","type":"string"}],"availableIn":["mapper"],"name":"controller","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Create a controller object for testing (no params)\nusersController = controller("users");\n\n// 2. Create a controller object with simulated request params for testing\nparams = {controller = "users", action = "show", key = 1};\nusersController = controller(name = "users", params = params);\n\n// 3. Use with processAction to test an action end-to-end\nparams = {controller = "users", action = "index"};\nusersController = controller(name = "users", params = params);\nusersController.processAction();\nbody = usersController.response();\n
"},"hint":"Creates and returns a controller object with your own custom name and params.\nUsed primarily for testing purposes.\n\n","returntype":"any","slug":"controller.controller","parameters":[{"required":true,"hint":"Name of the controller to create.","name":"name","type":"string"},{"default":"[runtime expression]","required":false,"hint":"The params struct (combination of form and URL variables).","name":"params","type":"struct"}],"availableIn":["controller","model","migrator","migration","tabledefinition"],"name":"controller","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"globalhelpers","category":"Miscellaneous Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Count all rows in the authors table\nauthorCount = model("author").count();\n\n// 2. Count authors whose last name starts with "A"\nauthorOnACount = model("author").count(where="lastName LIKE 'A%'");\n\n// 3. Count authors who have written books with titles starting with "A" (requires a hasMany association from author to book)\nauthorWithBooksOnACount = model("author").count(include="books", where="books.title LIKE 'A%'");\n\n// 4. Count posts grouped by status, returning a query with one row per status\nstatusCounts = model("post").count(group="status");\n// statusCounts is a query with columns: count, status\n\n// 5. Count the number of comments on a specific post using a dynamic counter method\n// (requires a hasMany association from post to comment)\naPost = model("post").findByKey(params.postId);\ncommentCount = aPost.commentCount();\n
"},"hint":"Returns the number of rows that match the arguments (or all rows if no arguments are passed in).\nUses the SQL function COUNT.\nIf no records can be found to perform the calculation on, 0 is returned.\n\n","returntype":"any","slug":"model.count","parameters":[{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"required":false,"hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"group","type":"string"}],"availableIn":["model"],"name":"count","tags":{"categoryClass":"statisticsfunctions","sectionClass":"modelclass","category":"Statistics Functions","section":"Model Class"}},{"extended":{"hasExtended":false,"docs":""},"hint":"creates the table in the database\n\n","returntype":"void","slug":"tabledefinition.create","parameters":[],"availableIn":["tabledefinition"],"name":"create","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Create a new author and save it to the database\nnewAuthor = model("author").create(params.author);\n\n// 2. Create using named arguments\nnewAuthor = model("author").create(firstName="John", lastName="Doe");\n\n// 3. Merge named arguments with a properties struct\nnewAuthor = model("author").create(active=1, properties=params.author);\n\n// 4. Skip validation when creating (e.g. for seeding trusted data)\nnewAuthor = model("author").create(properties=params.author, validate=false);\n\n// 5. Create inside a transaction that is rolled back (useful for dry-run testing)\nnewAuthor = model("author").create(properties=params.author, transaction="rollback");\n\n// 6. Allow explicit createdAt / updatedAt values when importing legacy data\nnewAuthor = model("author").create(\n\tfirstName="Jane",\n\tlastName="Smith",\n\tcreatedAt="2020-01-15 08:00:00",\n\tallowExplicitTimestamps=true\n);\n\n// 7. Scoped create via a hasOne / hasMany association\n// (calls model("order").create(customerId=aCustomer.id, shipping=params.shipping) internally)\naCustomer = model("customer").findByKey(params.customerId);\nanOrder = aCustomer.createOrder(shipping=params.shipping);\n
"},"hint":"Creates a new object, saves it to the database (if the validation permits it), and returns it.\nIf the validation fails, the unsaved object (with errors added to it) is still returned.\nProperty names and values can be passed in either using named arguments or as a struct to the properties argument.\n\n","returntype":"any","slug":"model.create","parameters":[{"default":"[runtime expression]","required":false,"hint":"The properties you want to set on the object (can also be passed in as named arguments).","name":"properties","type":"struct"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":true,"required":false,"hint":"Set to `false` to skip validations for this operation.","name":"validate","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"default":true,"required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":false,"required":false,"hint":"Set this to `true` to allow explicit assignment of `createdAt` or `updatedAt` properties","name":"allowExplicitTimestamps","type":"boolean"}],"availableIn":["model"],"name":"create","tags":{"categoryClass":"createfunctions","sectionClass":"modelclass","category":"Create Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Create a blank migration file (uses timestamp prefix by default)\nresult = application.wheels.migrator.createMigration("CreateUsersTable");\n// result -> "The migration 20240815123045_CreateUsersTable.cfc file was created"\n\n// 2. Create a migration from a built-in template (e.g. create-table)\nresult = application.wheels.migrator.createMigration(\n\tmigrationName="CreatePostsTable",\n\ttemplateName="create-table"\n);\n\n// 3. Create a migration using a sequential numeric prefix instead of a timestamp\nresult = application.wheels.migrator.createMigration(\n\tmigrationName="AddIndexToUsers",\n\tmigrationPrefix="numeric"\n);\n// result -> "The migration 001_AddIndexToUsers.cfc file was created"\n
"},"hint":"Creates a migration file. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","returntype":"string","slug":"migrator.createMigration","parameters":[{"required":true,"name":"migrationName","type":"string"},{"default":"","required":false,"name":"templateName","type":"string"},{"default":"timestamp","required":false,"name":"migrationPrefix","type":"string"}],"availableIn":["migrator"],"name":"createMigration","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Create a users table with standard columns and timestamps\nt = createTable(name="users");\n\tt.string(columnNames="firstName,lastName", default="", allowNull=false, limit=50);\n\tt.string(columnNames="email", default="", allowNull=false, limit=255);\n\tt.string(columnNames="passwordHash", default="", allowNull=true, limit=500);\n\tt.boolean(columnNames="verified", default=false);\n\tt.integer(columnNames="roleId", default=0, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Create a table with a custom string primary key (disabling the auto integer id)\nt = createTable(name="tokens", id=false);\n\tt.primaryKey(name="id", allowNull=false, type="string", limit=36);\n\tt.string(columnNames="userId", allowNull=false, limit=36);\n\tt.datetime(columnNames="expiresAt", allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Create a join table with composite primary keys and force=true to recreate if it already exists\nt = createTable(name="userRoles", id=false, force=true);\n\tt.primaryKey(name="userId", allowNull=false, limit=11);\n\tt.primaryKey(name="roleId", allowNull=false, limit=11);\nt.create();\n
"},"hint":"Creates a table definition object to store table properties\nOnly available in a migration CFC\n\n","returntype":"TableDefinition","slug":"migration.createTable","parameters":[{"required":true,"hint":"The name of the table to create","name":"name","type":"string"},{"default":"false","required":false,"hint":"whether to drop the table before creating it","name":"force","type":"boolean"},{"default":"true","required":false,"hint":"Whether to create a default primarykey or not","name":"id","type":"boolean"},{"default":"id","required":false,"hint":"Name of the primary key field to create","name":"primaryKey","type":"string"}],"availableIn":["migration"],"name":"createTable","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Create a simple database view that joins users and roles\nv = createView(name="userRoles");\nv.selectStatement(sql="SELECT u.id, u.firstName, u.lastName, r.name AS roleName FROM users u INNER JOIN roles r ON u.roleId = r.id");\nv.create();\n\n// 2. Create a view for active (non-deleted) users using method chaining\ncreateView(name="activeUsers")\n .selectStatement(sql="SELECT id, firstName, lastName, email FROM users WHERE deletedAt IS NULL")\n .create();\n\n// 3. Full up/down migration using createView and dropView\ncomponent extends="wheels.migrator.Migration" {\n function up() {\n createView(name="publishedArticles")\n .selectStatement(sql="SELECT id, title, body, authorId, publishedAt FROM articles WHERE publishedAt IS NOT NULL")\n .create();\n }\n function down() {\n dropView(name="publishedArticles");\n }\n}\n
"},"hint":"Creates a view definition object to store view properties\nOnly available in a migration CFC\n\n","returntype":"ViewDefinition","slug":"migration.createView","parameters":[{"required":true,"hint":"Name of the view to change properties on","name":"name","type":"string"}],"availableIn":["migration"],"name":"createView","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Include CSRF meta tags in your layout's <head> section\n// so that JavaScript AJAX requests can read the token and send it\n// as a request header when POSTing data to your application.\n<head>\n <title>My App</title>\n #csrfMetaTags()#\n</head>\n\n// 2. Reading the token in JavaScript (e.g. with fetch) using the meta tags above\n// The rendered HTML will contain two meta tags like:\n// <meta name="csrf-param" content="authenticityToken">\n// <meta name="csrf-token" content="<generated-token>">\n//\n// In your JavaScript you can then do:\n// const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');\n// fetch('/posts', { method: 'POST', headers: { 'authenticityToken': token }, body: ... });\n
"},"hint":"Include this in your layouts' head sections to include meta tags containing the authenticity token for use by JavaScript AJAX requests needing to POST data to your application.\n\n","returntype":"string","slug":"controller.csrfMetaTags","parameters":[{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"csrfMetaTags","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Alternate CSS classes on table rows\n// Outputs "odd" on the first row, "even" on the second, "odd" on the third, etc.\n<table>\n\t<thead>\n\t\t<tr>\n\t\t\t<th>Name</th>\n\t\t\t<th>Phone</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t<cfoutput query="employees">\n\t\t\t<tr class="#cycle("odd,even")#">\n\t\t\t\t<td>#employees.name#</td>\n\t\t\t\t<td>#employees.phone#</td>\n\t\t\t</tr>\n\t\t</cfoutput>\n\t</tbody>\n</table>\n\n// 2. Use named cycles when running multiple cycles simultaneously\n// Cycle "row" and "highlight" advance independently\n<cfoutput query="employees">\n\t<cfset rowClass = cycle(values="even,odd", name="row")>\n\t<cfset hlClass = cycle(values="highlight,normal,normal", name="highlight")>\n\t<tr class="#rowClass# #hlClass#">\n\t\t<td>#employees.name#</td>\n\t</tr>\n</cfoutput>\n\n// 3. Reset a cycle so it starts over from the first value\n<cfoutput query="departments" group="departmentId">\n\t<div class="#cycle(values="even,odd", name="row")#">\n\t\t<ul>\n\t\t\t<cfoutput>\n\t\t\t\t<cfset rank = cycle(values="president,vice-president,director,manager,specialist,intern", name="position")>\n\t\t\t\t<li class="#rank#">#employees.name#</li>\n\t\t\t</cfoutput>\n\t\t</ul>\n\t</div>\n\t<cfset resetCycle("position")>\n</cfoutput>\n
"},"hint":"Cycles through list values every time it is called.\n\n","returntype":"string","slug":"controller.cycle","parameters":[{"required":true,"hint":"List of values to cycle through.","name":"values","type":"string"},{"default":"default","required":false,"hint":"Name to give the cycle. Useful when you use multiple cycles on a page.","name":"name","type":"string"}],"availableIn":["controller"],"name":"cycle","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Override the data source for a model (basic usage).\n// In models/User.cfc\nconfig() {\n\t// Tell Wheels to use the data source named `users_source` instead of\n\t// the default one whenever this model makes SQL calls.\n\tdataSource("users_source");\n}\n\n// 2. Override the data source with explicit credentials.\n// In models/LegacyOrder.cfc\nconfig() {\n\tdataSource(datasource="legacy_db", username="app_reader", password="s3cr3t");\n}\n
"},"hint":"Use this method to override the data source connection information for this model.\n\n","returntype":"void","slug":"model.dataSource","parameters":[{"required":true,"hint":"The data source name to connect to.","name":"datasource","type":"string"},{"default":"","required":false,"hint":"The username for the data source.","name":"username","type":"string"},{"default":"","required":false,"hint":"The password for the data source.","name":"password","type":"string"}],"availableIn":["model"],"name":"dataSource","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelconfiguration","category":"Miscellaneous Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single date column to a new table\nt = createTable(name='events');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.date(columnNames='eventDate', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple date columns at once\nt = createTable(name='subscriptions');\n\tt.string(columnNames='plan', limit=100, allowNull=false);\n\tt.date(columnNames='startDate,endDate', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a date column with a default value to an existing table\nt = changeTable(name='users');\n\tt.date(columnNames='birthDate', allowNull=true);\nt.change();\n
"},"hint":"Adds date columns to table definition.\n\n","returntype":"any","slug":"tabledefinition.date","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"}],"availableIn":["tabledefinition"],"name":"date","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic date field bound to a model object property\n#dateField(objectName="event", property="startDate")#\n\n// 2. Date field with a custom label, min/max constraints, and a CSS class\n#dateField(objectName="event", property="startDate", label="Start Date", min="2024-01-01", max="2024-12-31", class="date-picker")#\n\n// 3. Date fields for nested properties on a hasMany association (e.g., schedule items)\n<cfloop from="1" to="#ArrayLen(project.milestones)#" index="i">\n\t#dateField(objectName="project", association="milestones", position="#i#", property="dueDate", label="Due Date ##i#")#\n</cfloop>
"},"hint":"Builds and returns a string containing a date field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.dateField","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"required":false,"hint":"Minimum allowed date (YYYY-MM-DD format).","name":"min","type":"string"},{"required":false,"hint":"Maximum allowed date (YYYY-MM-DD format).","name":"max","type":"string"},{"required":false,"name":"step","type":"string"},{"default":"useDefaultLabel","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"dateField","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic date field with a name and label\n#dateFieldTag(name="startDate", label="Start Date")#\n\n// 2. Pre-filled date value with min/max constraints\n#dateFieldTag(name="eventDate", value="2024-06-15", min="2024-01-01", max="2024-12-31", label="Event Date")#\n\n// 3. Date field with extra HTML attributes passed through\n#dateFieldTag(name="dueDate", label="Due Date", class="form-control", id="due-date-input")#\n
"},"hint":"Builds and returns a string containing a date field form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.dateFieldTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value to populate in tag's value attribute.","name":"value","type":"string"},{"required":false,"hint":"Minimum allowed date (YYYY-MM-DD format).","name":"min","type":"string"},{"required":false,"hint":"Maximum allowed date (YYYY-MM-DD format).","name":"max","type":"string"},{"required":false,"name":"step","type":"string"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"dateFieldTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
<!--- Basic date select bound to a model object --->\n#dateSelect(objectName="user", property="dateOfBirth")#\n\n<!--- Show fields to select only month and year --->\n#dateSelect(objectName="order", property="expirationDate", order="month,year")#\n\n<!--- Display month as numbers and include a blank option --->\n#dateSelect(objectName="event", property="startDate", monthDisplay="numbers", includeBlank=true)#\n\n<!--- Restrict year range and use abbreviated month names --->\n#dateSelect(objectName="reservation", property="checkInDate", startYear=2024, endYear=2030, monthDisplay="abbreviations")#\n
"},"hint":"Builds and returns a string containing three select form controls for month, day, and year based on the supplied objectName and property.\n\n","returntype":"string","slug":"controller.dateSelect","parameters":[{"default":"","required":false,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"default":"","required":false,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a `hasMany` relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":"month,day,year","required":false,"hint":"Use to change the order of or exclude date `select` tags.","name":"order","type":"string"},{"default":" ","required":false,"hint":"Use to change the character that is displayed between the date `select` tags.","name":"separator","type":"string"},{"default":2021,"required":false,"hint":"First year in `select` list.","name":"startYear","type":"numeric"},{"default":2031,"required":false,"hint":"Last year in `select` list.","name":"endYear","type":"numeric"},{"default":"names","required":false,"hint":"Pass in names, numbers, or abbreviations to control display.","name":"monthDisplay","type":"string"},{"default":"January,February,March,April,May,June,July,August,September,October,November,December","required":false,"name":"monthNames","type":"string"},{"default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","required":false,"name":"monthAbbreviations","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the `select` form control. Pass `true` to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":false,"required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using `aroundLeft` or `aroundRight`.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The `class` name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"required":false,"hint":"Set to false to not combine the select parts into a single DateTime object.","name":"combine","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"dateSelect","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic date selection - the "Tag" version accepts `name` and `selected` directly instead of binding to a model object\n#dateSelectTags(name="dateStart", selected=params.dateStart)#\n\n// 2. Show only month and year fields (omit day)\n#dateSelectTags(name="expiration", selected=params.expiration, order="month,year")#\n\n// 3. Custom year range with a blank option and a label\n#dateSelectTags(name="birthdate", selected=params.birthdate, startYear=1920, endYear=2024, includeBlank=true, label="Date of Birth")#\n
"},"hint":"Builds and returns a string containing three select form controls (month, day, and year) based on a name and value.\n\n","returntype":"string","slug":"controller.dateSelectTags","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value of option that should be selected by default.","name":"selected","type":"string"},{"default":"month,day,year","required":false,"hint":"Use to change the order of or exclude date `select` tags.","name":"order","type":"string"},{"default":" ","required":false,"hint":"Use to change the character that is displayed between the date `select` tags.","name":"separator","type":"string"},{"default":2021,"required":false,"hint":"First year in `select` list.","name":"startYear","type":"numeric"},{"default":2031,"required":false,"hint":"Last year in `select` list.","name":"endYear","type":"numeric"},{"default":"names","required":false,"hint":"Pass in names, numbers, or abbreviations to control display.","name":"monthDisplay","type":"string"},{"default":"January,February,March,April,May,June,July,August,September,October,November,December","required":false,"hint":"[see:dateSelect].","name":"monthNames","type":"string"},{"default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","required":false,"hint":"[see:dateSelect].","name":"monthAbbreviations","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"required":false,"hint":"Set to false to not combine the select parts into a single DateTime object.","name":"combine","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":"[runtime expression]","required":false,"name":"$now","type":"date"}],"availableIn":["controller"],"name":"dateSelectTags","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single datetime column to a new table\nt = createTable(name='orders');\n\tt.string(columnNames='status', limit=50, allowNull=false);\n\tt.datetime(columnNames='placedAt', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple datetime columns at once\nt = createTable(name='appointments');\n\tt.string(columnNames='title', limit=255, allowNull=false);\n\tt.datetime(columnNames='startAt,endAt', allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a nullable datetime column with a default to an existing table\nt = changeTable(name='posts');\n\tt.datetime(columnNames='publishedAt', allowNull=true, default='NOW()');\nt.change();\n
"},"hint":"adds datetime columns to table definition\n\n","returntype":"any","slug":"tabledefinition.datetime","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"}],"availableIn":["tabledefinition"],"name":"datetime","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic date and time select for an article's published date\n#dateTimeSelect(objectName="article", property="publishedAt")#\n\n// 2. Show only month, day, hour, and minute (exclude year and second)\n#dateTimeSelect(objectName="appointment", property="dateTimeStart", dateOrder="month,day", timeOrder="hour,minute")#\n\n// 3. Use 12-hour time format with a blank option and a custom year range\n#dateTimeSelect(objectName="event", property="startsAt", twelveHour=true, includeBlank=true, startYear=2020, endYear=2030)#\n\n// 4. Display month as numbers, step minutes by 15, and add a label\n#dateTimeSelect(objectName="meeting", property="scheduledAt", monthDisplay="numbers", minuteStep=15, label="Scheduled Date & Time")#\n
"},"hint":"Builds and returns a string containing six select form controls (three for date selection and the remaining three for time selection) based on the supplied objectName and property.\n\n","returntype":"string","slug":"controller.dateTimeSelect","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"string"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":"month,day,year","required":false,"hint":"Use to change the order of or exclude date select tags.","name":"dateOrder","type":"string"},{"default":" ","required":false,"hint":"Use to change the character that is displayed between the date select tags.","name":"dateSeparator","type":"string"},{"default":2021,"required":false,"hint":"First year in select list.","name":"startYear","type":"numeric"},{"default":2031,"required":false,"hint":"Last year in select list.","name":"endYear","type":"numeric"},{"default":"names","required":false,"hint":"Pass in names, numbers, or abbreviations to control display.","name":"monthDisplay","type":"string"},{"default":"January,February,March,April,May,June,July,August,September,October,November,December","required":false,"name":"monthNames","type":"string"},{"default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","required":false,"name":"monthAbbreviations","type":"string"},{"default":"hour,minute,second","required":false,"hint":"Use to change the order of or exclude time select tags.","name":"timeOrder","type":"string"},{"default":":","required":false,"hint":"Use to change the character that is displayed between the time select tags.","name":"timeSeparator","type":"string"},{"default":1,"required":false,"hint":"Pass in 10 to only show minute 10, 20, 30, etc.","name":"minuteStep","type":"numeric"},{"default":1,"required":false,"hint":"Pass in 10 to only show seconds 10, 20, 30, etc","name":"secondStep","type":"numeric"},{"default":" - ","required":false,"hint":"Use to change the character that is displayed between the first and second set of select tags.","name":"separator","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":false,"required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"required":false,"hint":"Set to false to not combine the select parts into a single DateTime object.","name":"combine","type":"boolean"},{"default":false,"required":false,"hint":"Whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","name":"twelveHour","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"dateTimeSelect","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage - the "Tag" version accepts `name` and `selected` directly instead of binding to a model object\n#dateTimeSelectTags(name="dateTimeStart", selected=params.dateTimeStart)#\n\n// 2. Show only month/day for the date portion and hour/minute for the time portion\n#dateTimeSelectTags(name="dateTimeStart", selected=params.dateTimeStart, dateOrder="month,day", timeOrder="hour,minute")#\n\n// 3. Custom year range, 15-minute steps, 12-hour format, and a label\n#dateTimeSelectTags(name="scheduledAt", selected=params.scheduledAt, startYear=2020, endYear=2030, minuteStep=15, twelveHour=true, label="Scheduled Date & Time")#\n
"},"hint":"Builds and returns a string containing six select form controls (three for date selection and the remaining three for time selection) based on a name.\n\n","returntype":"string","slug":"controller.dateTimeSelectTags","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value of option that should be selected by default.","name":"selected","type":"string"},{"default":"month,day,year","required":false,"hint":"Use to change the order of or exclude date select tags.","name":"dateOrder","type":"string"},{"default":" ","required":false,"hint":"Use to change the character that is displayed between the date select tags.","name":"dateSeparator","type":"string"},{"default":2021,"required":false,"hint":"First year in `select` list.","name":"startYear","type":"numeric"},{"default":2031,"required":false,"hint":"Last year in `select` list.","name":"endYear","type":"numeric"},{"default":"names","required":false,"hint":"Pass in names, numbers, or abbreviations to control display.","name":"monthDisplay","type":"string"},{"default":"January,February,March,April,May,June,July,August,September,October,November,December","required":false,"hint":"[see:dateSelect].","name":"monthNames","type":"string"},{"default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","required":false,"hint":"[see:dateSelect].","name":"monthAbbreviations","type":"string"},{"default":"hour,minute,second","required":false,"hint":"Use to change the order of or exclude time select tags.","name":"timeOrder","type":"string"},{"default":":","required":false,"hint":"Use to change the character that is displayed between the time select tags.","name":"timeSeparator","type":"string"},{"default":1,"required":false,"hint":"Pass in 10 to only show minute 10, 20, 30, etc.","name":"minuteStep","type":"numeric"},{"default":1,"required":false,"hint":"Pass in 10 to only show seconds 10, 20, 30, etc.","name":"secondStep","type":"numeric"},{"default":" - ","required":false,"hint":"Use to change the character that is displayed between the first and second set of select tags.","name":"separator","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"required":false,"hint":"Set to false to not combine the select parts into a single DateTime object.","name":"combine","type":"boolean"},{"default":false,"required":false,"hint":"whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","name":"twelveHour","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"dateTimeSelectTags","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage: render a day-of-month select for a standalone form (not bound to a model)\n#daySelectTag(name="day", selected=params.day)#\n\n// 2. Pre-select day 15 and include a blank prompt at the top\n#daySelectTag(name="birthDay", selected=15, includeBlank="-- Select Day --")#\n\n// 3. Wrap the control with a label and surrounding HTML via prepend/append\n#daySelectTag(name="day", selected=params.day, label="Day", prepend="<div class=""field"">", append="</div>")#\n
"},"hint":"Builds and returns a string containing a select form control for the days of the month based on the supplied name.\n\n","returntype":"string","slug":"controller.daySelectTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"The day that should be selected initially.","name":"selected","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":"[runtime expression]","required":false,"name":"$now","type":"date"}],"availableIn":["controller"],"name":"daySelectTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single decimal column to a new table\nt = createTable(name='products');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.decimal(columnNames='price', precision=10, scale=2, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple decimal columns at once\nt = createTable(name='measurements');\n\tt.string(columnNames='label', limit=100, allowNull=false);\n\tt.decimal(columnNames='length,width,height', precision=8, scale=4, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add a nullable decimal column with a default to an existing table\nt = changeTable(name='orders');\n\tt.decimal(columnNames='discount', precision=5, scale=2, allowNull=true, default='0.00');\nt.change();\n
"},"hint":"adds decimal columns to table definition\n\n","returntype":"any","slug":"tabledefinition.decimal","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"},{"required":false,"name":"precision","type":"numeric"},{"required":false,"name":"scale","type":"numeric"}],"availableIn":["tabledefinition"],"name":"decimal","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
"},"hint":"Create a route that matches a URL requiring an HTTP DELETE method. We recommend using this matcher to expose actions that delete database records.\n\n","returntype":"struct","slug":"mapper.delete","parameters":[{"required":false,"hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPost`).","name":"name","type":"string"},{"required":false,"hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPost` generates a pattern of `blog-post`).","name":"pattern","type":"string"},{"required":false,"hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","name":"to","type":"string"},{"required":false,"hint":"Map the route to a given controller. This must be passed along with the `action` argument.","name":"controller","type":"string"},{"required":false,"hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","name":"action","type":"string"},{"required":false,"hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","name":"package","type":"string"},{"required":false,"hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","name":"on","type":"string"},{"required":false,"hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","name":"redirect","type":"string"}],"availableIn":["mapper"],"name":"delete","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get a post object and then delete it from the database.\npost = model("Post").findByKey(33);\npost.delete();\n\n// 2. Permanently delete a record even if the model uses soft deletes.\nuser = model("User").findByKey(params.userId);\nuser.delete(softDelete=false);\n\n// 3. Delete a record without running callbacks (e.g. skip `beforeDelete` / `afterDelete`).\ncomment = model("Comment").findByKey(params.commentId);\ncomment.delete(callbacks=false);\n\n// 4. If you have a `hasMany` association setup from `post` to `comment`, you can do a scoped call. (The `deleteComment` method below will call `comment.delete()` internally.)\npost = model("Post").findByKey(params.postId);\ncomment = model("Comment").findByKey(params.commentId);\npost.deleteComment(comment);\n
"},"hint":"Deletes the object, which means the row is deleted from the database (unless prevented by a beforeDelete callback).\nReturns true on successful deletion of the row, false otherwise.\n\n","returntype":"boolean","slug":"model.delete","parameters":[{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"[runtime expression]","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"default":true,"required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":false,"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":true,"required":false,"hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","name":"softDelete","type":"boolean"}],"availableIn":["model"],"name":"delete","tags":{"categoryClass":"crudfunctions","sectionClass":"modelobject","category":"CRUD Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Delete all inactive users without instantiating them (skips callbacks and validations).\nrecordsDeleted = model("User").deleteAll(where="inactive=1");\n\n// 2. Delete all inactive users and run their beforeDelete / afterDelete callbacks.\nrecordsDeleted = model("User").deleteAll(where="inactive=1", instantiate=true);\n\n// 3. Permanently delete soft-deleted records (bypass the soft-delete column).\nrecordsDeleted = model("User").deleteAll(where="inactive=1", softDelete=false);\n\n// 4. If you have a `hasMany` association from `Post` to `Comment`, you can use a scoped call. (The `deleteAllComments` method below calls `model("Comment").deleteAll(where="postId=#post.id#")` internally.)\npost = model("Post").findByKey(params.postId);\nhowManyDeleted = post.deleteAllComments();\n
"},"hint":"Deletes all records that match the where argument.\nBy default, objects will not be instantiated and therefore callbacks and validations are not invoked.\nYou can change this behavior by passing in instantiate=true.\nReturns the number of records that were deleted.\n\n","returntype":"numeric","slug":"model.deleteAll","parameters":[{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":false,"required":false,"hint":"Whether or not to instantiate the object(s) first. When objects are not instantiated, any callbacks and validations set on them will be skipped.","name":"instantiate","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","name":"useIndex","type":"struct"},{"default":"[runtime expression]","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"default":true,"required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":false,"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":true,"required":false,"hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","name":"softDelete","type":"boolean"}],"availableIn":["model"],"name":"deleteAll","tags":{"categoryClass":"deletefunctions","sectionClass":"modelclass","category":"Delete Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Delete the user with the primary key value of 1.\nresult = model("User").deleteByKey(1);\n// result -> true (if the row was deleted), false otherwise\n\n// 2. Permanently delete a soft-deletable record (bypass soft delete).\nresult = model("User").deleteByKey(key=1, softDelete=false);\n\n// 3. Delete using a composite primary key (comma-separated values).\nresult = model("OrderItem").deleteByKey("42,7");\n\n// 4. Delete within a transaction that can be rolled back (useful for testing).\nresult = model("User").deleteByKey(key=1, transaction="rollback");\n
"},"hint":"Finds the record with the supplied key and deletes it.\nReturns true on successful deletion of the row, false otherwise.\n\n","returntype":"boolean","slug":"model.deleteByKey","parameters":[{"required":true,"hint":"Primary key value(s) of the record to fetch. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","name":"key","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"default":true,"required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":false,"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":true,"required":false,"hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","name":"softDelete","type":"boolean"}],"availableIn":["model"],"name":"deleteByKey","tags":{"categoryClass":"deletefunctions","sectionClass":"modelclass","category":"Delete Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Delete the user who signed up most recently.\nresult = model("User").deleteOne(order="signupDate DESC");\n\n// 2. Delete the oldest unpaid invoice for a given customer.\nresult = model("Invoice").deleteOne(\n\twhere="customerId=#params.customerId# AND status='unpaid'",\n\torder="createdAt ASC"\n);\n\n// 3. Permanently delete a soft-deletable record (bypass soft-delete behaviour).\nresult = model("User").deleteOne(\n\twhere="status='banned'",\n\torder="createdAt ASC",\n\tsoftDelete=false\n);\n\n// 4. If you have a `hasOne` association set up from `User` to `Profile` you can do a scoped call.\n// The `deleteProfile` method will call `model("Profile").deleteOne(where="userId=#aUser.id#")` internally.\naUser = model("User").findByKey(params.userId);\naUser.deleteProfile();\n
"},"hint":"Gets an object based on conditions and deletes it.\n\n","returntype":"boolean","slug":"model.deleteOne","parameters":[{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"order","type":"string"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"default":true,"required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":false,"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","name":"useIndex","type":"struct"},{"default":true,"required":false,"hint":"Set to `false` to permanently delete a record, even if it has a soft delete column.","name":"softDelete","type":"boolean"}],"availableIn":["model"],"name":"deleteOne","tags":{"categoryClass":"deletefunctions","sectionClass":"modelclass","category":"Delete Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Deobfuscate a URL parameter to get the original numeric ID\n// (Wheels automatically obfuscates numeric URL params when obfuscateUrls is enabled)\noriginalId = deobfuscateParam("b7ab9a50");\n// originalId -> "35"\n\n// 2. Round-trip: obfuscate a value, then deobfuscate it back\nobfuscated = obfuscateParam("100");\noriginal = deobfuscateParam(obfuscated);\n// original -> "100"\n\n// 3. Non-obfuscated values (e.g. already plain integers) are returned as-is\npassthrough = deobfuscateParam("42");\n// passthrough -> "42"\n
"},"hint":"Deobfuscates a value.\n\n","returntype":"string","slug":"controller.deobfuscateParam","parameters":[{"required":true,"hint":"The value to deobfuscate.","name":"param","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"deobfuscateParam","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"globalhelpers","category":"Miscellaneous Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Compare two dates about a month apart\nrightNow = Now();\naWhileAgo = DateAdd("d", -30, rightNow);\nwriteOutput(distanceOfTimeInWords(aWhileAgo, rightNow));\n// -> "about 1 month"\n\n// 2. Show a short gap with seconds included\njustNow = Now();\nfiveSecondsAgo = DateAdd("s", -5, justNow);\nwriteOutput(distanceOfTimeInWords(fiveSecondsAgo, justNow, includeSeconds=true));\n// -> "less than 5 seconds"\n\n// 3. Show various time ranges\nnow = Now();\nwriteOutput(distanceOfTimeInWords(DateAdd("n", -2, now), now));\n// -> "2 minutes"\n\nwriteOutput(distanceOfTimeInWords(DateAdd("h", -3, now), now));\n// -> "about 3 hours"\n\nwriteOutput(distanceOfTimeInWords(DateAdd("d", -5, now), now));\n// -> "5 days"\n\nwriteOutput(distanceOfTimeInWords(DateAdd("yyyy", -2, now), now));\n// -> "over 2 years"\n
"},"hint":"Pass in two dates to this method, and it will return a string describing the difference between them.\n\n","returntype":"string","slug":"controller.distanceOfTimeInWords","parameters":[{"required":true,"hint":"Date to compare from.","name":"fromTime","type":"date"},{"required":true,"hint":"Date to compare to.","name":"toTime","type":"date"},{"default":false,"required":false,"hint":"Whether or not to include the number of seconds in the returned string.","name":"includeSeconds","type":"boolean"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"distanceOfTimeInWords","tags":{"categoryClass":"datefunctions","sectionClass":"globalhelpers","category":"Date Functions","section":"Global Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns a comprehensive health report on the migrator state. Pure\nread — no mutation. Used by wheels migrate doctor to surface\norphans, gaps, and pending migrations in one pass.\nResult struct:\n- healthy: boolean — true iff no orphans AND no pending\n- currentVersion: string — highest applied version (may be orphan)\n- orphans: array — DB versions with no matching file\n- pending: array — local files not yet applied\n- summary: struct with .total, .applied, .pending, .orphan counts\n- message: human-readable one-paragraph summary\nSee issue #2780 / PR #2798 for the orphan detection foundation.\n\n","returntype":"struct","slug":"migrator.doctor","parameters":[],"availableIn":["migrator"],"name":"doctor","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Reverse a table creation by dropping the table\n// Called automatically when rolling back this migration\nfunction down() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tdropTable("employees");\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, "exception")) {\n\t\t\ttransaction action="rollback";\n\t\t\tthrow(\n\t\t\t\terrorCode = "1",\n\t\t\t\tdetail = state.exception.detail,\n\t\t\t\tmessage = state.exception.message,\n\t\t\t\ttype = "any"\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action="commit";\n\t\t}\n\t}\n}\n\n// 2. Reverse an addColumn() call by removing the column\nfunction down() {\n\tvar state = {};\n\ttransaction {\n\t\ttry {\n\t\t\tremoveColumn(table="users", columnName="biography");\n\t\t} catch (any e) {\n\t\t\tstate.exception = e;\n\t\t}\n\n\t\tif (structKeyExists(state, "exception")) {\n\t\t\ttransaction action="rollback";\n\t\t\tthrow(\n\t\t\t\terrorCode = "1",\n\t\t\t\tdetail = state.exception.detail,\n\t\t\t\tmessage = state.exception.message,\n\t\t\t\ttype = "any"\n\t\t\t);\n\t\t} else {\n\t\t\ttransaction action="commit";\n\t\t}\n\t}\n}\n\n// 3. Paired up() and down() inside a full migration component\ncomponent extends="[extends]" hint="Add status column to orders" {\n\n\tfunction up() {\n\t\tvar state = {};\n\t\ttransaction {\n\t\t\ttry {\n\t\t\t\taddColumn(table="orders", columnType="string", columnName="status", limit=50, default="pending");\n\t\t\t} catch (any e) {\n\t\t\t\tstate.exception = e;\n\t\t\t}\n\n\t\t\tif (structKeyExists(state, "exception")) {\n\t\t\t\ttransaction action="rollback";\n\t\t\t\tthrow(\n\t\t\t\t\terrorCode = "1",\n\t\t\t\t\tdetail = state.exception.detail,\n\t\t\t\t\tmessage = state.exception.message,\n\t\t\t\t\ttype = "any"\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\ttransaction action="commit";\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction down() {\n\t\tvar state = {};\n\t\ttransaction {\n\t\t\ttry {\n\t\t\t\tremoveColumn(table="orders", columnName="status");\n\t\t\t} catch (any e) {\n\t\t\t\tstate.exception = e;\n\t\t\t}\n\n\t\t\tif (structKeyExists(state, "exception")) {\n\t\t\t\ttransaction action="rollback";\n\t\t\t\tthrow(\n\t\t\t\t\terrorCode = "1",\n\t\t\t\t\tdetail = state.exception.detail,\n\t\t\t\t\tmessage = state.exception.message,\n\t\t\t\t\ttype = "any"\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\ttransaction action="commit";\n\t\t\t}\n\t\t}\n\t}\n\n}\n
"},"hint":"Migrates down: will be executed when migrating your schema backward\nAlong with up(), these are the two main functions in any migration file\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.down","parameters":[],"availableIn":["migration"],"name":"down","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Drop a foreign key constraint by its explicit name\n// In the down() function, remove a foreign key added in up()\ndropForeignKey(table="orders", keyName="FK_orders_customers");\n\n// 2. Drop a foreign key that was created via addReference()\n// addReference() creates keys named FK_<table>_<pluralizedReference>\n// So addReference(table="comments", referenceName="post") creates "FK_comments_posts"\ndropForeignKey(table="comments", keyName="FK_comments_posts");\n\n// 3. Use inside a migration's down() to reverse an addForeignKey() call\n// up() called: addForeignKey(table="profiles", referenceTable="users", column="userId", referenceColumn="id")\n// down() reverses it:\ndropForeignKey(table="profiles", keyName="FK_profiles_users");\n
"},"hint":"Drops a foreign key constraint from the database\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.dropForeignKey","parameters":[{"required":true,"hint":"The table name to perform the operation on","name":"table","type":"string"},{"required":true,"hint":"the name of the key to drop","name":"keyName","type":"string"}],"availableIn":["migration"],"name":"dropForeignKey","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Drop the foreign key from comments.postId back to posts.id\n// Removes the constraint named FK_comments_posts\ndropReference(table="comments", referenceName="post");\n\n// 2. Drop a foreign key from order_items back to orders\n// Removes the constraint named FK_order_items_orders\ndropReference(table="order_items", referenceName="order");\n\n// 3. Use dropReference in the down() of a migration that added a reference in up()\n// In your migration CFC:\n//\n// public void function up() {\n// addReference(table="comments", referenceName="post");\n// }\n//\n// public void function down() {\n// dropReference(table="comments", referenceName="post");\n// }\n
"},"hint":"Drop a foreign key constraint from the database, using the reference name that was used to create it\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.dropReference","parameters":[{"required":true,"hint":"The table name to perform the operation on","name":"table","type":"string"},{"required":false,"hint":"the name of the reference to drop","name":"referenceName","type":"string"},{"required":false,"hint":"Alias for `referenceName` (consistent with the modern migrator surface — `columnName` / `columnNames` are accepted alongside the legacy form).","name":"columnName","type":"string"},{"required":false,"hint":"Plural alias for `referenceName`. When both `columnName` and `columnNames` are supplied, `columnNames` wins.","name":"columnNames","type":"string"}],"availableIn":["migration"],"name":"dropReference","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Drop a table in the down() migration (reversing a createTable in up())\ncomponent extends="wheels.migrator.Migration" hint="Add products table" {\n\n\tfunction up() {\n\t\tt = createTable(name="products");\n\t\tt.string(columnNames="name", allowNull=false);\n\t\tt.decimal(columnNames="price", precision=10, scale=2);\n\t\tt.boolean(columnNames="active", default=1);\n\t\tt.timestamps();\n\t\tt.create();\n\t}\n\n\tfunction down() {\n\t\tdropTable("products");\n\t}\n\n}\n\n// 2. Drop multiple tables in a single down() migration\ncomponent extends="wheels.migrator.Migration" hint="Add orders and line items tables" {\n\n\tfunction up() {\n\t\tt = createTable(name="lineItems");\n\t\tt.integer(columnNames="orderId");\n\t\tt.integer(columnNames="productId");\n\t\tt.integer(columnNames="quantity");\n\t\tt.timestamps();\n\t\tt.create();\n\n\t\tt = createTable(name="orders");\n\t\tt.integer(columnNames="userId");\n\t\tt.string(columnNames="status");\n\t\tt.timestamps();\n\t\tt.create();\n\t}\n\n\tfunction down() {\n\t\tdropTable("lineItems");\n\t\tdropTable("orders");\n\t}\n\n}\n
"},"hint":"Drops a table from the database\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.dropTable","parameters":[{"required":false,"hint":"Name of the table to drop","name":"name","type":"string"},{"required":false,"hint":"Alias for `name` (the form `wheels destroy` generated before 4.1.1). Pass one or the other — not both.","name":"tableName","type":"string"}],"availableIn":["migration"],"name":"dropTable","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Drop a view in the down() migration (reversing a createView in up())\ncomponent extends="wheels.migrator.Migration" hint="Add active users view" {\n\n\tfunction up() {\n\t\tcreateView(name="activeUsers")\n\t\t\t.selectStatement(sql="SELECT id, firstName, lastName, email FROM users WHERE deletedAt IS NULL")\n\t\t\t.create();\n\t}\n\n\tfunction down() {\n\t\tdropView(name="activeUsers");\n\t}\n\n}\n\n// 2. Drop multiple views in a single down() migration\ncomponent extends="wheels.migrator.Migration" hint="Add reporting views" {\n\n\tfunction up() {\n\t\tcreateView(name="publishedArticles")\n\t\t\t.selectStatement(sql="SELECT id, title, authorId, publishedAt FROM articles WHERE publishedAt IS NOT NULL")\n\t\t\t.create();\n\n\t\tcreateView(name="activeAuthors")\n\t\t\t.selectStatement(sql="SELECT id, firstName, lastName FROM users WHERE deletedAt IS NULL")\n\t\t\t.create();\n\t}\n\n\tfunction down() {\n\t\tdropView(name="publishedArticles");\n\t\tdropView(name="activeAuthors");\n\t}\n\n}\n
"},"hint":"drops a view from the database\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.dropView","parameters":[{"required":true,"hint":"Name of the view to drop","name":"name","type":"string"}],"availableIn":["migration"],"name":"dropView","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic email field bound to an object property\n#emailField(objectName="user", property="emailAddress")#\n\n// 2. Email field with a custom label and a CSS class\n#emailField(label="Email Address", objectName="user", property="emailAddress", class="form-control")#\n\n// 3. Nested email field for a contacts association (hasMany)\n<cfloop from="1" to="#ArrayLen(account.contacts)#" index="i">\n\t#emailField(label="Contact Email ##i#", objectName="account", association="contacts", position=i, property="email")#\n</cfloop>\n
"},"hint":"Builds and returns a string containing an email field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.emailField","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":"useDefaultLabel","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"emailField","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic email field with a name and pre-filled value\n#emailFieldTag(name="userEmail", value="hello@example.com")#\n\n// 2. Email field with a label\n#emailFieldTag(label="Email Address", name="userEmail", value=params.userEmail)#\n\n// 3. Email field with a CSS class and placeholder passed as extra HTML attributes\n#emailFieldTag(name="contactEmail", value="", class="form-control", placeholder="you@example.com")#\n
"},"hint":"Builds and returns a string containing an email field form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.emailFieldTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value to populate in tag's value attribute.","name":"value","type":"string"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"emailFieldTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"One-line session-auth wiring for config/services.cfm.\nThe auth subsystem ships complete (Authenticator strategy registry +\nSessionStrategy with login/logout/currentUser and SID rotation) but\nwiring it by hand spans two files: map the singletons here, then\nregister the strategy in app/events/onapplicationstart.cfm.\nenableSession() collapses that into one idempotent call:\n// config/services.cfm\nenableSession(sessionKey = \"wheels.auth\");\nThe DI container is available in services.cfm (it is NOT available in\nconfig/app.cfm — services.cfm is loaded after the container is built).\nManual wiring keeps working; this helper is the convenience path.","returntype":"any","slug":"controller.enableSession","parameters":[{"default":"wheels.auth","required":false,"name":"sessionKey","type":"string"},{"default":"","required":false,"name":"onLogin","type":"any"},{"default":"","required":false,"name":"onLogout","type":"any"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"enableSession","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\nmapper()\n .namespace("admin")\n .resources("products")\n .end() // Ends the `namespace` block.\n\n .scope(package="public")\n .resources(name="products", nested=true)\n .resources("variations")\n .end() // Ends the nested `resources` block.\n .end() // Ends the `scope` block.\n.end(); // Ends the `mapper` block.\n\n</cfscript>\n
"},"hint":"Call this to end a nested routing block or the entire route configuration. This method is chained on a sequence of routing mapper method calls started by mapper().\n\n","returntype":"struct","slug":"mapper.end","parameters":[],"availableIn":["mapper"],"name":"end","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Close a form opened with startFormTag\n#startFormTag(action="create")#\n <!--- your form controls --->\n#endFormTag()#\n\n// 2. Append a note after the closing form tag\n#startFormTag(action="update", method="post")#\n <!--- your form controls --->\n#endFormTag(append="<p>All fields are required.</p>")#\n\n// 3. Wrap the closing tag with surrounding markup using prepend and append\n#startFormTag(route="userSearch")#\n <!--- your form controls --->\n#endFormTag(prepend="</div>", append="</section>")#\n
"},"hint":"Builds and returns a string containing the closing form tag.\n\n","returntype":"string","slug":"controller.endFormTag","parameters":[{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"endFormTag","tags":{"categoryClass":"generalformfunctions","sectionClass":"viewhelpers","category":"General Form Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Map a `status` property to a comma-delimited list of allowed string values.\n// Wheels auto-validates that `status` is one of the listed values,\n// creates `isDraft()`, `isPublished()`, and `isArchived()` checker methods,\n// and registers `draft()`, `published()`, and `archived()` query scopes.\ncomponent extends="Model" {\n\tfunction config() {\n\t\tenum(property="status", values="draft,published,archived");\n\t}\n}\n\n// 2. Map a `priority` property using a struct so that the stored database value\n// differs from the human-readable name (0, 1, 2 are stored; low/medium/high are the names).\n// Generated methods: `isLow()`, `isMedium()`, `isHigh()`.\n// Generated scopes: `model("Task").low()`, `model("Task").medium()`, `model("Task").high()`.\ncomponent extends="Model" {\n\tfunction config() {\n\t\tenum(property="priority", values={low: 0, medium: 1, high: 2});\n\t}\n}\n\n// 3. Using the generated checker methods and scopes at runtime.\n// `isPublished()` returns true/false; `published()` scopes a finder to that status.\npost = model("Post").findByKey(key=42);\nif (post.isPublished()) {\n\twriteOutput("This post is live.");\n}\n\n// Find all published posts using the auto-generated scope.\npublishedPosts = model("Post").published().findAll();\n
"},"hint":"Maps a property to a set of named values (like Rails enums).\nGenerates boolean checker methods (is()), scopes for each value,\nand validates that the property value is one of the allowed values.\n\n","returntype":"void","slug":"model.enum","parameters":[{"required":true,"hint":"The name of the model property to map as an enum.","name":"property","type":"string"},{"required":true,"hint":"Either a comma-delimited list of string values (e.g. `\"draft,published,archived\"`) or a struct mapping names to stored values (e.g. `{low: 0, medium: 1, high: 2}`).","name":"values","type":"any"}],"availableIn":["model"],"name":"enum","tags":{"categoryClass":"enumfunctions","sectionClass":"modelconfiguration","category":"Enum Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Inspect all enum definitions on the Order model\ninfo = model("Order").enumInfo();\n// info -> {\n// status: {\n// property: "status",\n// names: "draft,published,archived",\n// values: {draft: "draft", published: "published", archived: "archived"}\n// }\n// }\n\n// 2. List all enum-mapped properties\ninfo = model("Order").enumInfo();\nfor (propName in info) {\n writeOutput(propName & ": " & info[propName].names);\n}\n// status: draft,published,archived\n// priority: low,medium,high\n\n// 3. Use enum metadata to build a select list for a form\ninfo = model("Order").enumInfo();\nstatusEnum = info["status"];\nfor (enumName in listToArray(statusEnum.names)) {\n storedValue = statusEnum.values[enumName];\n writeOutput(enumName & " -> " & storedValue);\n}\n// draft -> draft\n// published -> published\n// archived -> archived\n
"},"hint":"Returns a struct containing all enum definitions for this model.\nEach key is the property name, and the value contains values (name-to-stored-value mapping) and names (list of enum names).\n\n","returntype":"struct","slug":"model.enumInfo","parameters":[],"availableIn":["model"],"name":"enumInfo","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Read a required environment variable\ndbUrl = env("DATABASE_URL");\n// dbUrl -> "postgres://user:pass@localhost/myapp" (or "" if not set)\n\n// 2. Provide a default when the variable may be absent\nsmtpHost = env("SMTP_HOST", "localhost");\n// smtpHost -> "localhost" when SMTP_HOST is not defined in .env or system env\n\n// 3. Guard application startup based on an environment variable\nappSecret = env("APP_SECRET_KEY");\nif (!Len(appSecret)) {\n\tthrow(type="App.ConfigError", message="APP_SECRET_KEY must be set.");\n}\n
"},"hint":"Returns the value of an environment variable. Checks application.env (loaded from .env files) first, then falls back to system environment variables (server.system.environment). Returns the default if the variable is not found in either location.\n\n\nnamed argument default is also accepted for backwards compatibility\nwith pre-rename callers.","returntype":"any","slug":"controller.env","parameters":[{"required":true,"hint":"The environment variable name to look up.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value to return if the variable is not found. The legacy","name":"defaultValue","type":"any"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"env","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"configuration","category":"Miscellaneous Functions","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check the total number of errors on an object\nif (author.errorCount() GTE 10) {\n // Too many errors — bail out early\n}\n\n// 2. Check how many errors are associated with a specific property\nif (author.errorCount(property="email") gt 0) {\n // The email property has at least one error\n}\n\n// 3. Count errors that were set with a specific error name\ncount = author.errorCount(name="invalidFormat");\n// count -> 2 (two errors share the "invalidFormat" name)\n
"},"hint":"Returns the number of errors this object has associated with it.\nSpecify property or name if you wish to count only specific errors.\n\n","returntype":"numeric","slug":"model.errorCount","parameters":[{"default":"","required":false,"hint":"Specify a property name here if you want to count only errors set on a specific property.","name":"property","type":"string"},{"default":"","required":false,"hint":"Specify an error name here if you want to count only errors set with a specific error name.","name":"name","type":"string"}],"availableIn":["model"],"name":"errorCount","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Display the first error message (if any) on the email property\n#errorMessageOn(objectName="user", property="email")#\n// -> <span class="error-message">Email is not a valid email address.</span>\n// -> (empty string when no error exists on that property)\n\n// 2. Prepend and append custom text around the error message\n#errorMessageOn(objectName="user", property="username", prependText="Problem:", appendText="Please try again.")#\n// -> <span class="error-message">Problem: Username has already been taken. Please try again.</span>\n\n// 3. Wrap the message in a div with a custom CSS class instead of the default span\n#errorMessageOn(objectName="post", property="title", wrapperElement="div", class="field-error")#\n// -> <div class="field-error">Title can't be blank.</div>\n
"},"hint":"Returns the error message, if one exists, on the object's property.\nIf multiple error messages exist, the first one is returned.\n\n","returntype":"string","slug":"controller.errorMessageOn","parameters":[{"required":true,"hint":"The variable name of the object to display the error message for.","name":"objectName","type":"string"},{"required":true,"hint":"The name of the property to display the error message for.","name":"property","type":"string"},{"default":"","required":false,"hint":"String to prepend to the error message.","name":"prependText","type":"string"},{"default":"","required":false,"hint":"String to append to the error message.","name":"appendText","type":"string"},{"default":"span","required":false,"hint":"HTML element to wrap the error message in.","name":"wrapperElement","type":"string"},{"default":"error-message","required":false,"hint":"CSS `class` to set on the wrapper element.","name":"class","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"}],"availableIn":["controller"],"name":"errorMessageOn","tags":{"categoryClass":"errorfunctions","sectionClass":"viewhelpers","category":"Error Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Display all error messages for a user object\n#errorMessagesFor(objectName="user")#\n// -> <ul class="error-messages"><li>Email is not a valid email address.</li><li>Username can't be blank.</li></ul>\n// -> (empty string when the object has no errors)\n\n// 2. Use a custom CSS class on the wrapping ul element\n#errorMessagesFor(objectName="user", class="form-errors")#\n// -> <ul class="form-errors"><li>Email is not a valid email address.</li></ul>\n\n// 3. Suppress duplicate error messages\n#errorMessagesFor(objectName="user", showDuplicates=false)#\n// -> <ul class="error-messages"><li>can't be blank.</li></ul>\n// (only one "can't be blank." entry even if multiple fields have the same message)\n\n// 4. Include errors from associated objects as well\n#errorMessagesFor(objectName="order", includeAssociations=true)#\n// -> <ul class="error-messages"><li>Name can't be blank.</li><li>Line items quantity must be greater than zero.</li></ul>\n
"},"hint":"Builds and returns a list (ul tag with a default class of error-messages) containing all the error messages for all the properties of the object.\nReturns an empty string if no errors exist.\n\n","returntype":"string","slug":"controller.errorMessagesFor","parameters":[{"required":true,"hint":"The variable name of the object to display error messages for.","name":"objectName","type":"string"},{"default":"error-messages","required":false,"hint":"CSS `class` to set on the `ul` element.","name":"class","type":"string"},{"default":true,"required":false,"hint":"Whether or not to show duplicate error messages.","name":"showDuplicates","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"},{"default":true,"required":false,"name":"includeAssociations","type":"boolean"}],"availableIn":["controller"],"name":"errorMessagesFor","tags":{"categoryClass":"errorfunctions","sectionClass":"viewhelpers","category":"Error Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all errors associated with the emailAddress property\nerrors = user.errorsOn("emailAddress");\n// errors -> [{property: "emailAddress", message: "is invalid", name: ""}, ...]\n\n// 2. Get only errors on emailAddress that were set with a specific error name\nerrors = user.errorsOn(property="emailAddress", name="formatCheck");\n// errors -> [{property: "emailAddress", message: "must be a valid email", name: "formatCheck"}]\n\n// 3. Check errors on a property and loop over them\nerrors = user.errorsOn("username");\nfor (error in errors) {\n writeOutput(error.message);\n}\n
"},"hint":"Returns an array of all errors associated with the supplied property (and error name if passed in).\n\n","returntype":"array","slug":"model.errorsOn","parameters":[{"required":true,"hint":"Specify the property name to return errors for here.","name":"property","type":"string"},{"default":"","required":false,"hint":"If you want to return only errors on the property set with a specific error name you can specify it here.","name":"name","type":"string"}],"availableIn":["model"],"name":"errorsOn","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all general (base) errors for a model object after validation\nuser = model("User").new(params.user);\nuser.valid();\nerrors = user.errorsOnBase();\n// errors -> [{property: "", message: "Account has been suspended", name: ""}]\n\n// 2. Filter base errors by a specific error name\nuser.addErrorToBase(message="Account has been suspended", name="suspended");\nuser.addErrorToBase(message="Please accept the terms", name="terms");\nsuspendedErrors = user.errorsOnBase(name="suspended");\n// suspendedErrors -> [{property: "", message: "Account has been suspended", name: "suspended"}]\n\n// 3. Check for base errors and display them\nerrors = user.errorsOnBase();\nif (arrayLen(errors)) {\n for (e in errors) {\n writeOutput(e.message);\n }\n}\n
"},"hint":"Returns an array of all errors associated with the object as a whole (not related to any specific property).\n\n","returntype":"array","slug":"model.errorsOnBase","parameters":[{"default":"","required":false,"hint":"Specify an error name here to only return errors for that error name.","name":"name","type":"string"}],"availableIn":["model"],"name":"errorsOnBase","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Escapes the LIKE wildcards in a string so it can be used as a literal search term in a\nLIKE comparison that declares ESCAPE '\\'. The escape character \\ is escaped first, then\n% and _; `\n","returntype":"string","slug":"controller.escapeForLike","parameters":[{"required":true,"hint":"String whose `LIKE` wildcards should be treated as literals.","name":"value","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"escapeForLike","tags":{"categoryClass":"stringfunctions","sectionClass":"globalhelpers","category":"String Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Extract text around a matching phrase with a custom radius\nresult = excerpt(text="CFWheels is a Rails-like MVC framework for Adobe ColdFusion and Lucee", phrase="framework", radius=5);\n// result -> "...MVC framework for Ad..."\n\n// 2. Use the default radius of 100 characters\nresult = excerpt(text="CFWheels is a powerful MVC framework built for ColdFusion developers who want to move fast.", phrase="powerful");\n// result -> "CFWheels is a powerful MVC framework built for ColdFusion developers who want to move fast."\n\n// 3. Customize the excerpt string used to indicate truncated text\nresult = excerpt(text="The quick brown fox jumps over the lazy dog", phrase="fox", radius=5, excerptString=" [...]");\n// result -> " [...]brown fox jumps [...]"\n
"},"hint":"Extracts an excerpt from text that matches the first instance of a given phrase.\n\n","returntype":"string","slug":"controller.excerpt","parameters":[{"required":true,"hint":"The text to extract an excerpt from.","name":"text","type":"string"},{"required":true,"hint":"The phrase to extract.","name":"phrase","type":"string"},{"default":100,"required":false,"hint":"Number of characters to extract surrounding the phrase.","name":"radius","type":"numeric"},{"default":"...","required":false,"hint":"String to replace first and / or last characters with.","name":"excerptString","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"excerpt","tags":{"categoryClass":"stringfunctions","sectionClass":"globalhelpers","category":"String Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Run a raw SQL statement during a migration\nexecute(sql = "UPDATE users SET active = 1 WHERE active IS NULL");\n\n// 2. Create a database view with raw SQL\nexecute(sql = "CREATE VIEW active_users AS SELECT * FROM users WHERE active = 1");\n\n// 3. Use execute() inside up() and down() to apply and reverse a custom SQL change\ncomponent extends="wheels.migrator.Migration" {\n function up() {\n execute(sql = "ALTER TABLE orders ADD COLUMN notes TEXT");\n }\n function down() {\n execute(sql = "ALTER TABLE orders DROP COLUMN notes");\n }\n}\n
"},"hint":"Executes a raw sql query\nOnly available in a migration CFC\n\n","returntype":"void","slug":"migration.execute","parameters":[{"required":true,"hint":"Arbitrary SQL String","name":"sql","type":"string"}],"availableIn":["migration"],"name":"execute","tags":{"categoryClass":"migrationfunctions","sectionClass":"migrator","category":"Migration Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check if any record exists in the table\nanyUsers = model("User").exists();\n\n// 2. Check if a record with a specific primary key exists\nresult = model("User").exists(key=params.key);\n\n// 3. Check if a record matching a WHERE condition exists\njoeExists = model("User").exists(where="firstName = 'Joe'");\n\n// 4. Use the result in a conditional\nif (model("User").exists(key=params.userId)) {\n\t// record was found, proceed\n}\n\n// 5. Include soft-deleted records in the check\ndeletedExists = model("User").exists(where="email='old@example.com'", includeSoftDeletes=true);\n\n// 6. If you have a `belongsTo` association from `Comment` to `Post`, you can do a scoped call. (The `hasPost` method below calls `model("Post").exists(comment.postId)` internally.)\ncomment = model("Comment").findByKey(params.commentId);\ncommentHasAPost = comment.hasPost();\n\n// 7. If you have a `hasOne` association from `User` to `Profile`, you can do a scoped call. (The `hasProfile` method below calls `model("Profile").exists(where="userId=#user.id#")` internally.)\nuser = model("User").findByKey(params.userId);\nuserHasProfile = user.hasProfile();\n\n// 8. If you have a `hasMany` association from `Post` to `Comment`, you can do a scoped call. (The `hasComments` method below calls `model("Comment").exists(where="postId=#post.id#")` internally.)\npost = model("Post").findByKey(params.postId);\npostHasComments = post.hasComments();\n
"},"hint":"Checks if a record exists in the table.\nYou can pass in either a primary key value to the key argument or a string to the where argument.\nIf you don't pass in either of those, it will simply check if any record exists in the table.\n\n","returntype":"boolean","slug":"model.exists","parameters":[{"required":false,"hint":"Primary key value(s) of the record. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","name":"key","type":"any"},{"required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"}],"availableIn":["model"],"name":"exists","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic file upload field bound to an object and property\n#fileField(objectName="photo", property="imageFile")#\n\n// 2. Provide a custom label for the file field\n#fileField(label="Profile Photo", objectName="user", property="avatar")#\n\n// 3. Display file upload fields for a hasMany association using nested properties\n<fieldset>\n\t<legend>Screenshots</legend>\n\t<cfloop from="1" to="#ArrayLen(site.screenshots)#" index="i">\n\t\t#fileField(label="File ##i#", objectName="site", association="screenshots", position=i, property="file")#\n\t\t#textField(label="Caption ##i#", objectName="site", association="screenshots", position=i, property="caption")#\n\t</cfloop>\n</fieldset>\n
"},"hint":"Builds and returns a string containing a file field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.fileField","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":"useDefaultLabel","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"fileField","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic file upload field with a label\n#fileFieldTag(name="photo", label="Profile Photo")#\n\n// 2. File upload field with a CSS class and no label\n#fileFieldTag(name="attachment", class="upload-input")#\n\n// 3. File upload field with label placement and wrapper HTML\n#fileFieldTag(name="resume", label="Upload Resume", labelPlacement="before", prepend="<div class='field'>", append="</div>")#\n
"},"hint":"Builds and returns a string containing a file form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.fileFieldTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"fileFieldTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the entire filter chain for the current controller\nmyFilterChain = filterChain();\n// myFilterChain -> array of structs, each with keys: through, type, only, except, arguments\n// e.g. [{ through: "checkLogin", type: "before", only: "", except: "" }, ...]\n\n// 2. Get only the before-filters\nbeforeFilters = filterChain(type="before");\nfor (f in beforeFilters) {\n writeOutput(f.through);\n}\n\n// 3. Get only the after-filters\nafterFilters = filterChain(type="after");\nwriteOutput(arrayLen(afterFilters));\n
"},"hint":"Returns an array of all the filters set on current controller in the order in which they will be executed.\n\n","returntype":"array","slug":"controller.filterChain","parameters":[{"default":"all","required":false,"hint":"Use this argument to return only before or after filters.","name":"type","type":"string"}],"availableIn":["controller"],"name":"filterChain","tags":{"categoryClass":"configurationfunctions","sectionClass":"controller","category":"Configuration Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Run `restrictAccess` before every action in this controller (declared inside config()).\nfilters("restrictAccess");\n\n// 2. Run two before-filters on every action except `home` and `login`.\nfilters(through="isLoggedIn, checkIPAddress", except="home, login");\n\n// 3. Run `auditLog` after only the `create`, `update`, and `delete` actions.\nfilters(through="auditLog", type="after", only="create, update, delete");\n\n// 4. Prepend a filter so it runs before any already-registered filters.\nfilters(through="maintenanceCheck", placement="prepend");\n\n// Note: filter functions must be declared as `private` in the controller\n// to prevent them from being routed as public actions.\n// Example controller setup:\n// component extends="Controller" {\n// function config() {\n// filters("restrictAccess");\n// }\n// private function restrictAccess() {\n// if (!isLoggedIn()) {\n// redirectTo(route="login");\n// }\n// }\n// }\n
"},"hint":"Tells Wheels to run a function before an action is run or after an action has been run.\n\n","returntype":"void","slug":"controller.filters","parameters":[{"required":true,"hint":"Function(s) to execute before or after the action(s).","name":"through","type":"string"},{"default":"before","required":false,"hint":"Whether to run the function(s) before or after the action(s).","name":"type","type":"string"},{"default":"","required":false,"hint":"Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should only be run on these actions.","name":"only","type":"string"},{"default":"","required":false,"hint":"Pass in a list of action names (or one action name) to tell Wheels that the filter function(s) should be run on all actions except the specified ones.","name":"except","type":"string"},{"default":"append","required":false,"hint":"Pass in `prepend` to prepend the function(s) to the filter chain instead of appending.","name":"placement","type":"string"}],"availableIn":["controller"],"name":"filters","tags":{"categoryClass":"configurationfunctions","sectionClass":"controller","category":"Configuration Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all users ordered by last name\nusers = model("user").findAll(order="lastName ASC");\n\n// 2. Get only 5 users in a random order\nfiveRandomUsers = model("user").findAll(maxRows=5, order="random");\n\n// 3. Include a belongsTo association and filter with a WHERE clause\narticles = model("article").findAll(include="author", where="published=1", order="createdAt DESC");\n\n// 4. Include a hasMany association in the opposite direction\nbobsArticles = model("author").findAll(include="articles", where="firstName='Bob'");\n\n// 5. Use pagination (records 26-50) with a nested include (song belongsTo album, album belongsTo artist)\nsongs = model("song").findAll(include="album(artist)", page=2, perPage=25);\n\n// 6. Return results as an array of model objects instead of a query\nactiveUsers = model("user").findAll(where="active=1", order="lastName ASC", returnAs="objects");\nfor (user in activeUsers) {\n\twriteOutput(user.firstName & " " & user.lastName);\n}\n\n// 7. Return results as an array of structs\nuserStructs = model("user").findAll(where="active=1", returnAs="structs");\n\n// 8. Use a dynamic finder to get all books released in a certain year\n// (same as model("book").findAll(where="releaseYear=#params.year#"))\nbooks = model("book").findAllByReleaseYear(params.year);\n\n// 9. Use a dynamic finder with multiple criteria\n// (same as model("book").findAll(where="releaseYear=#params.year# AND type='#params.type#'"))\nbooks = model("book").findAllByReleaseYearAndType("#params.year#,#params.type#");\n\n// 10. Use a scoped call via a hasMany association (calls findAll internally with a where clause)\npost = model("post").findByKey(params.postId);\ncomments = post.comments();\n\n// 11. Use GROUP BY with a calculated property (generates HAVING instead of WHERE)\n// Order model has a calculated property: property(name="totalAmount", sql="SUM(amount)")\nids = model("order").findAll(group="productId", where="totalAmount > 1000", select="productId");\n\n// 12. Include soft-deleted records\nallUsers = model("user").findAll(includeSoftDeletes=true, order="lastName ASC");\n\n// 13. Cache the query results for 10 minutes\ncachedUsers = model("user").findAll(where="active=1", cache=10);\n\n// 14. Return the generated SQL string instead of running the query\nsql = model("user").findAll(where="active=1", order="lastName ASC", returnAs="sql");\n// sql -> "SELECT ... FROM users WHERE active = 1 ORDER BY last_name ASC"\n\n// 15. Use index hints (MySQL and SQL Server only)\nindexes = {\n\tauthor="idx_authors_name",\n\tpost="idx_posts_created"\n};\nposts = model("author").findAll(\n\twhere="firstName LIKE '#params.q#%' OR subject LIKE '#params.q#%'",\n\tinclude="posts",\n\tuseIndex=indexes\n);\n
"},"hint":"Returns records from the database table mapped to this model according to the arguments passed in (use the where argument to decide which records to get, use the order argument to set the order in which those records should be returned, and so on).\nThe records will be returned as either a cfquery result set, an array of objects, or an array of structs (depending on what the returnAs argument is set to).\n\n","returntype":"any","slug":"model.findAll","parameters":[{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"order","type":"string"},{"default":"","required":false,"hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"group","type":"string"},{"default":"","required":false,"hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","name":"select","type":"string"},{"default":"","required":false,"hint":"List of calculated property names (declared via `property(name=\"...\", sql=\"...\", select=false)`) to additively opt into this finder's `SELECT` clause. Unlike `select`, this does not replace the default column list — the named calculated properties are merged on top of all default columns, so the rest of the record is still returned. Useful for pulling a `select=false` computed property back in on a single finder without spelling out every other column. Unknown names throw `Wheels.CalculatedPropertyNotFound` in `development`/`testing` and are ignored in `production`.","name":"includeCalculated","type":"string"},{"default":"false","required":false,"hint":"Whether to add the `DISTINCT` keyword to your `SELECT` clause. Wheels will, when necessary, add this automatically (when using pagination and a `hasMany` association is used in the `include` argument, to name one example).","name":"distinct","type":"boolean"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":"-1","required":false,"hint":"Maximum number of records to retrieve. Passed on to the `maxRows` `cfquery` attribute. The default, `-1`, means that all records will be retrieved.","name":"maxRows","type":"numeric"},{"default":"0","required":false,"hint":"If you want to paginate records, you can do so by specifying a page number here. For example, getting records 11-20 would be page number 2 when `perPage` is kept at the default setting (10 records per page). The default, 0, means that records won't be paginated and that the `perPage` and `count` arguments will be ignored.","name":"page","type":"numeric"},{"default":10,"required":false,"hint":"When using pagination, you can specify how many records you want to fetch per page here. This argument is only used when the `page` argument has been passed in.","name":"perPage","type":"numeric"},{"default":"0","required":false,"hint":"When using pagination and you know in advance how many records you want to paginate through, you can pass in that value here. Doing so will prevent Wheels from running a `COUNT` query to get this value. This argument is only used when the `page` argument has been passed in.","name":"count","type":"numeric"},{"default":"query","required":false,"hint":"Handle to use for the query. This is used when you're paginating multiple queries and need to reference them individually in the `paginationLinks()` function. It's also used to set the name of the query in the debug output (which otherwise defaults to `userFindAllQuery` for example).","name":"handle","type":"string"},{"default":"","required":false,"hint":"If you want to cache the query, you can do so by specifying the number of minutes you want to cache the query for here. If you set it to `true`, the default cache time will be used (60 minutes).","name":"cache","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"query","required":false,"hint":"Set to `objects` to return an array of objects, set to `structs` (or its alias `array`) to return an array of structs, set to `query` to return a query result set, or set to 'sql' to return the executed SQL query as a string.","name":"returnAs","type":"string"},{"default":true,"required":false,"hint":"When `returnAs` is set to `objects`, you can set this argument to `false` to prevent returning objects fetched from associations specified in the `include` argument. This is useful when you only need to include associations for use in the `WHERE` clause only and want to avoid the performance hit that comes with object creation.","name":"returnIncluded","type":"boolean"},{"default":"true","required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","name":"useIndex","type":"struct"},{"default":"[runtime expression]","required":false,"hint":"Override the default datasource","name":"dataSource","type":"string"},{"default":"0","required":false,"name":"$limit","type":"numeric"},{"default":"0","required":false,"name":"$offset","type":"numeric"},{"default":"false","required":false,"name":"$forUpdate","type":"boolean"},{"default":"true","required":false,"name":"$useRequestCache","type":"boolean"}],"availableIn":["model"],"name":"findAll","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get a comma-delimited list of all primary key values for the Artist model\nprimaryKeyList = model("artist").findAllKeys();\n// primaryKeyList -> "1,2,3,4,5"\n\n// 2. Get keys for active artists only, enclosed in single quotes, separated by a pipe\nprimaryKeyList = model("artist").findAllKeys(quoted=true, delimiter="|", where="active=1");\n// primaryKeyList -> "'1'|'3'|'5'"\n\n// 3. Use the result directly in a SQL IN clause for a subsequent query\nkeyList = model("artist").findAllKeys(quoted=true, where="genreId=7");\nalbums = model("album").findAll(where="artistId IN (#keyList#)");\n
"},"hint":"Returns all primary key values in a list.\nIn addition to quoted and delimiter you can pass in any argument that findAll() accepts.\n\n","returntype":"string","slug":"model.findAllKeys","parameters":[{"default":"false","required":false,"hint":"Set to `true` to enclose each value in single-quotation marks.","name":"quoted","type":"boolean"},{"default":",","required":false,"hint":"The delimiter character to separate the list items with.","name":"delimiter","type":"string"}],"availableIn":["model"],"name":"findAllKeys","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the author with the primary key value `99` as an object\nauth = model("author").findByKey(99);\n\n// 2. Get an author based on a form/URL value and handle the not-found case\nauth = model("author").findByKey(params.key);\nif (!isObject(auth)) {\n flashInsert(message="Author #params.key# was not found");\n redirectTo(back=true);\n}\n\n// 3. Fetch only selected columns for a record\nuser = model("user").findByKey(key=params.id, select="id,firstName,email");\n\n// 4. Include a belongsTo association when fetching by key\norder = model("order").findByKey(key=params.orderId, include="customer");\n\n// 5. Cache the lookup for 10 minutes and include soft-deleted records\nproduct = model("product").findByKey(key=params.id, cache=10, includeSoftDeletes=true);\n\n// 6. Use a scoped call via a belongsTo association (calls `model("post").findByKey(comment.postId)` internally)\ncomment = model("comment").findByKey(params.commentId);\npost = comment.post();\n
"},"hint":"Fetches the requested record by primary key and returns it as an object.\nReturns false if no record is found.\nYou can override this behavior to return a cfquery result set instead, similar to what's described in the documentation for findOne().\n\n","returntype":"any","slug":"model.findByKey","parameters":[{"required":true,"hint":"Primary key value(s) of the record. Separate with comma if passing in multiple primary key values. Accepts a string, list, or a numeric value.","name":"key","type":"any"},{"default":"","required":false,"hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","name":"select","type":"string"},{"default":"","required":false,"hint":"List of calculated property names (declared via `property(name=\"...\", sql=\"...\", select=false)`) to additively opt into this finder's `SELECT` clause. Unlike `select`, this does not replace the default column list — the named calculated properties are merged on top of all default columns, so the rest of the record is still returned. Useful for pulling a `select=false` computed property back in on a single finder without spelling out every other column. Unknown names throw `Wheels.CalculatedPropertyNotFound` in `development`/`testing` and are ignored in `production`.","name":"includeCalculated","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":"query","required":false,"hint":"Handle to use for the query. This is used to set the name of the query in the debug output (which otherwise defaults to `userFindOneQuery` for example).","name":"handle","type":"string"},{"default":"","required":false,"hint":"If you want to cache the query, you can do so by specifying the number of minutes you want to cache the query for here. If you set it to `true`, the default cache time will be used (60 minutes).","name":"cache","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"object","required":false,"hint":"Set to `objects` to return an array of objects, set to `structs` (or its alias `array`) to return an array of structs, set to `query` to return a query result set, or set to 'sql' to return the executed SQL query as a string.","name":"returnAs","type":"string"},{"default":"true","required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"Override the default datasource","name":"dataSource","type":"string"}],"availableIn":["model"],"name":"findByKey","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Send a newsletter email to every subscriber one at a time\nmodel("Subscriber").findEach(callback = function(subscriber) {\n sendEmail(\n to = subscriber.email,\n subject = "Monthly Newsletter",\n template = "/emails/newsletter",\n subscriber = subscriber\n );\n});\n\n// 2. Process users as structs and write a report entry for each one\nmodel("User").findEach(\n where = "active = 1",\n order = "lastName ASC",\n returnAs = "struct",\n callback = function(user) {\n writeLog("Processing user: #user.firstName# #user.lastName#");\n }\n);\n\n// 3. Archive old orders in smaller batches to reduce memory pressure\nmodel("Order").findEach(\n where = "createdAt < '#DateFormat(DateAdd('yyyy', -2, Now()), 'yyyy-mm-dd')#'",\n batchSize = 250,\n callback = function(order) {\n order.archived = true;\n order.save();\n }\n);\n
"},"hint":"Processes large result sets one record at a time without loading everything into memory.\nInternally paginates through records and invokes the callback for each individual record.\nThe callback receives a model object (when returnAs is \"object\") or a struct representing one row.\n\n","returntype":"void","slug":"model.findEach","parameters":[{"default":1000,"required":false,"hint":"Number of records to load per internal database query. Defaults to 1000.","name":"batchSize","type":"numeric"},{"required":true,"hint":"A function/closure to call for each record. Receives a single argument: the record (object or struct).","name":"callback","type":"any"},{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"order","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":"","required":false,"hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","name":"select","type":"string"},{"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":"object","required":false,"hint":"Whether each record is an \"object\" (default) or \"struct\".","name":"returnAs","type":"string"}],"availableIn":["model"],"name":"findEach","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the first user record (ordered by primary key ascending)\nuser = model("User").findFirst();\n// Returns the model object with the lowest primary key value, or false if no records exist.\n\n// 2. Get the first user ordered by a specific property\nuser = model("User").findFirst(property="createdAt");\n// Returns the oldest user (lowest createdAt value).\n\n// 3. Get the first active user ordered by last name, then first name\nuser = model("User").findFirst(properties="lastName,firstName", where="active = 1");\n// Equivalent to: ORDER BY lastName ASC, firstName ASC with a WHERE clause applied.\n// Returns a model object, or false if no matching record is found.\n
"},"hint":"Fetches the first record ordered by primary key value.\nUse the property argument to order by something else.\nReturns a model object.\n\n","returntype":"any","slug":"model.findFirst","parameters":[{"default":"[runtime expression]","required":false,"hint":"Name of the property to order by. This argument is also aliased as `properties`.","name":"property","type":"string"},{"default":"ASC","required":false,"name":"$sort","type":"string"}],"availableIn":["model"],"name":"findFirst","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Process all users in batches of 500 (default), logging each batch\nmodel("User").findInBatches(callback=function(batch) {\n\twriteOutput("Processing " & batch.recordCount & " users");\n});\n\n// 2. Process active orders in batches of 200, filtered with a WHERE clause\nmodel("Order").findInBatches(\n\tbatchSize=200,\n\twhere="status='active'",\n\torder="createdAt ASC",\n\tcallback=function(batch) {\n\t\t// batch is a cfquery result set by default\n\t\tfor (local.i = 1; local.i <= batch.recordCount; local.i++) {\n\t\t\twriteOutput(batch.orderId[local.i] & ": " & batch.total[local.i]);\n\t\t}\n\t}\n);\n\n// 3. Receive each batch as an array of model objects instead of a query\nmodel("User").findInBatches(\n\tbatchSize=100,\n\treturnAs="objects",\n\twhere="active=1",\n\tcallback=function(batch) {\n\t\tfor (user in batch) {\n\t\t\tuser.sendNewsletter();\n\t\t}\n\t}\n);\n\n// 4. Receive each batch as an array of structs\nmodel("Product").findInBatches(\n\tbatchSize=250,\n\treturnAs="structs",\n\tselect="id,name,price",\n\tcallback=function(batch) {\n\t\tfor (product in batch) {\n\t\t\twriteOutput(product.name & " costs " & product.price);\n\t\t}\n\t}\n);\n\n// 5. Include soft-deleted records while processing in batches\nmodel("User").findInBatches(\n\tincludeSoftDeletes=true,\n\tcallback=function(batch) {\n\t\twriteOutput("Batch has " & batch.recordCount & " records (including deleted)");\n\t}\n);\n
"},"hint":"Processes large result sets in batches without loading everything into memory at once.\nThe callback receives a query result set (or array of objects/structs) for each batch.\n\n","returntype":"void","slug":"model.findInBatches","parameters":[{"default":500,"required":false,"hint":"Number of records per batch. Defaults to 500.","name":"batchSize","type":"numeric"},{"required":true,"hint":"A function/closure to call for each batch. Receives a single argument: the batch (query, array of objects, or array of structs depending on `returnAs`).","name":"callback","type":"any"},{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"order","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":"","required":false,"hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","name":"select","type":"string"},{"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":"query","required":false,"hint":"Set to \"query\" (default), \"objects\", or \"structs\" for the batch format.","name":"returnAs","type":"string"}],"availableIn":["model"],"name":"findInBatches","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the last user record (ordered by primary key descending)\nlastUser = model("User").findLastOne();\n// Returns a User object for the record with the highest primary key, or false if none exist.\n\n// 2. Get the most recently created post by ordering on a different property\nlatestPost = model("Post").findLastOne(property="createdAt");\n// Returns the Post object with the latest createdAt value.\n\n// 3. Get the last active product, using a where clause alongside the property order\nlastActive = model("Product").findLastOne(property="updatedAt", where="isActive = 1");\n// Returns the most recently updated active product, or false if none exist.\n
"},"hint":"Fetches the last record ordered by primary key value.\nUse the property argument to order by something else.\nReturns a model object. Formerly known as findLast.\n\n","returntype":"any","slug":"model.findLastOne","parameters":[{"required":false,"hint":"Name of the property to order by. This argument is also aliased as `properties`.","name":"property","type":"string"}],"availableIn":["model"],"name":"findLastOne","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the most recent order as an object from the database\norder = model("Order").findOne(order="datePurchased DESC");\n\n// 2. Use a where clause to find the first user with a specific email address\nuser = model("User").findOne(where="email='someone@example.com'");\n\n// 3. Use a dynamic finder to get the first person with the last name Smith.\n// Equivalent to: model("User").findOne(where="lastName='Smith'")\nperson = model("User").findOneByLastName("Smith");\n\n// 4. Use a dynamic finder to match on two columns.\n// Equivalent to: model("User").findOne(where="email='someone@example.com' AND password='mypass'")\nuser = model("User").findOneByEmailAndPassword("someone@example.com", "mypass");\n\n// 5. Return false when no matching record is found (the default returnAs="object" behavior)\nuser = model("User").findOne(where="email='unknown@example.com'");\nif (!isObject(user)) {\n writeOutput("No user found.");\n}\n\n// 6. Return as a query result set instead of an object\nuserQuery = model("User").findOne(where="role='admin'", returnAs="query");\n\n// 7. Use a scoped call via a hasOne association from User to Profile.\n// The profile() method calls model("Profile").findOne(where="userId=#user.id#") internally.\nuser = model("User").findByKey(params.userId);\nprofile = user.profile();\n\n// 8. Use a scoped call via a hasMany association from Post to Comment.\n// The findOneComment() method calls model("Comment").findOne(where="postId=#post.id#") internally.\npost = model("Post").findByKey(params.postId);\ncomment = post.findOneComment(where="approved=1");\n
"},"hint":"Fetches the first record found based on the WHERE and ORDER BY clauses.\nWith the default settings (i.e. the returnAs argument set to object), a model object will be returned if the record is found and the boolean value false if not.\nInstead of using the where argument, you can create cleaner code by making use of a concept called Dynamic Finders.\n\n","returntype":"any","slug":"model.findOne","parameters":[{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Maps to the `ORDER` BY clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"order","type":"string"},{"default":"","required":false,"hint":"Determines how the `SELECT` clause for the query used to return data will look. You can pass in a list of the properties (which map to columns) that you want returned from your table(s). If you don't set this argument at all, Wheels will select all properties from your table(s). If you specify a table name (e.g. `users.email`) or alias a column (e.g. `fn AS firstName`) in the list, then the entire list will be passed through unchanged and used in the `SELECT` clause of the query. By default, all column names in tables joined via the `include` argument will be prepended with the singular version of the included table name.","name":"select","type":"string"},{"default":"","required":false,"hint":"List of calculated property names (declared via `property(name=\"...\", sql=\"...\", select=false)`) to additively opt into this finder's `SELECT` clause. Unlike `select`, this does not replace the default column list — the named calculated properties are merged on top of all default columns, so the rest of the record is still returned. Useful for pulling a `select=false` computed property back in on a single finder without spelling out every other column. Unknown names throw `Wheels.CalculatedPropertyNotFound` in `development`/`testing` and are ignored in `production`.","name":"includeCalculated","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":"query","required":false,"hint":"Handle to use for the query. This is used to set the name of the query in the debug output (which otherwise defaults to `userFindOneQuery` for example).","name":"handle","type":"string"},{"default":"","required":false,"hint":"If you want to cache the query, you can do so by specifying the number of minutes you want to cache the query for here. If you set it to `true`, the default cache time will be used (60 minutes).","name":"cache","type":"any"},{"default":false,"required":false,"hint":"Set to `true` to force Wheels to query the database even though an identical query for this model may have been run in the same request. (The default in Wheels is to get the second query from the model's request-level cache.)","name":"reload","type":"boolean"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"object","required":false,"hint":"Set to `objects` to return an array of objects, set to `structs` (or its alias `array`) to return an array of structs, set to `query` to return a query result set, or set to 'sql' to return the executed SQL query as a string.","name":"returnAs","type":"string"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"If you want to specify table index hints, pass in a structure of index names using your model names as the structure keys. Eg: `{user=\"idx_users\", post=\"idx_posts\"}`. This feature is only supported by MySQL and SQL Server.","name":"useIndex","type":"struct"},{"default":"[runtime expression]","required":false,"hint":"Override the default datasource","name":"dataSource","type":"string"}],"availableIn":["model"],"name":"findOne","tags":{"categoryClass":"readfunctions","sectionClass":"modelclass","category":"Read Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: Basic usage — show a "First" link at the top of a\n// paginated list; renders a disabled span when already on page 1\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nposts = model("Post").findAll(page=params.page, perPage=10, order="createdAt DESC");\n\n// View code\n<cfoutput>\n #firstPageLink()#\n #previousPageLink()#\n #pageNumberLinks()#\n #nextPageLink()#\n #lastPageLink()#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n<cfoutput>\n #firstPageLink(\n text="«« First",\n class="page-link",\n disabledClass="page-link disabled"\n )#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the first page\n\n// View code\n<cfoutput>\n #firstPageLink(showDisabled=false)#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/3)\n\n// Route setup in app/config/routes.cfm\nmapper()\n .get(name="paginatedArticles", pattern="articles/page/[page]", to="articles##index")\n .get(name="articles", pattern="articles", to="articles##index")\n.end();\n\n// Controller code\nparam name="params.page" type="integer" default="1";\narticles = model("Article").findAll(page=params.page, perPage=20, order="title");\n\n// View code\n<cfoutput>\n #firstPageLink(route="paginatedArticles", pageNumberAsParam=false)#\n</cfoutput>\n
"},"hint":"Creates a link to the first page, or a disabled span when already on the first page.\n\n","returntype":"string","slug":"controller.firstPageLink","parameters":[{"default":"First","required":false,"hint":"The text for the link.","name":"text","type":"string"},{"default":"query","required":false,"hint":"The handle given to the query that the pagination should be displayed for.","name":"handle","type":"string"},{"default":"page","required":false,"hint":"The name of the param that holds the current page number.","name":"name","type":"string"},{"default":"","required":false,"hint":"CSS class for the link element.","name":"class","type":"string"},{"default":"disabled","required":false,"hint":"CSS class for the disabled span element.","name":"disabledClass","type":"string"},{"default":true,"required":false,"hint":"Whether to render a disabled span when already on the first page.","name":"showDisabled","type":"boolean"},{"default":true,"required":false,"hint":"Decides whether to link the page number as a param or as part of a route.","name":"pageNumberAsParam","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"firstPageLink","tags":{"categoryClass":"paginationfunctions","sectionClass":"viewhelpers","category":"Pagination Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the current value of a specific key in the Flash\nnotice = flash("notice");\n// notice -> "Your profile was updated successfully."\n\n// 2. Get the entire Flash as a struct when no key is passed\nflashContents = flash();\n// flashContents -> {notice: "Record saved.", error: "Something went wrong."}\n\n// 3. Check for a key before reading it to avoid an empty-string fallback\nif (flashKeyExists("error")) {\n errorMessage = flash("error");\n}\n
"},"hint":"Returns the value of a specific key in the Flash (or the entire Flash as a struct if no key is passed in).\n\n","returntype":"any","slug":"controller.flash","parameters":[{"required":false,"hint":"The key to get the value for.","name":"key","type":"string"}],"availableIn":["controller"],"name":"flash","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Clear all flash data\nflashClear();\n\n// 2. Insert some messages, then clear them all before redirecting\nflashInsert(notice="Record saved.");\nflashInsert(warning="Check your settings.");\n// Oops — wipe everything and start fresh\nflashClear();\n// flash() is now an empty struct: {}\n\n// 3. Clear flash conditionally inside a controller action\nfunction checkout() {\n if (!isLoggedIn()) {\n flashClear();\n flashInsert(error="You must be logged in to check out.");\n redirectTo(action="login");\n }\n}\n
"},"hint":"Deletes everything from the Flash.\n\n","returntype":"void","slug":"controller.flashClear","parameters":[],"availableIn":["controller"],"name":"flashClear","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check how many keys are currently in the Flash\ncount = flashCount();\n// count -> 0 (Flash is empty), or a positive integer when keys exist\n\n// 2. Only render a Flash notice section when there is something to show\nif (flashCount()) {\n writeOutput("You have " & flashCount() & " flash message(s).");\n}\n\n// 3. Use alongside flashIsEmpty() — flashCount() powers the isEmpty check\nflashInsert(notice="Saved successfully", warning="Check your email");\ncount = flashCount();\n// count -> 2\n
"},"hint":"Returns how many keys exist in the Flash.\n\n","returntype":"numeric","slug":"controller.flashCount","parameters":[],"availableIn":["controller"],"name":"flashCount","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Delete a key from the Flash\nflashDelete(key="errorMessage");\n\n// 2. Check the return value — true if the key existed, false if it did not\nwasPresent = flashDelete(key="notice");\n// wasPresent -> true (key existed and was removed)\n// wasPresent -> false (key did not exist in the Flash)\n\n// 3. Conditionally act on whether the key was actually removed\nif (flashDelete(key="warning")) {\n // key existed; it has now been removed from the Flash\n} else {\n // key was not present; nothing was changed\n}\n
"},"hint":"Deletes a specific key from the Flash.\nReturns true if the key exists.\n\n","returntype":"any","slug":"controller.flashDelete","parameters":[{"required":true,"hint":"The key to delete","name":"key","type":"string"}],"availableIn":["controller"],"name":"flashDelete","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Insert a single key / value into the Flash\nflashInsert(notice="Your profile has been updated.");\n\n// 2. Insert multiple keys at once\nflashInsert(success="Account created.", hint="Check your email to confirm.");\n\n// 3. Read back a Flash value in the next action or view\n// (After a redirect, in the destination action or its view:)\nmsg = flash("notice");\n// msg -> "Your profile has been updated."\n
"},"hint":"Inserts a new key / value into the Flash.\n\n","returntype":"void","slug":"controller.flashInsert","parameters":[],"availableIn":["controller"],"name":"flashInsert","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check whether the Flash is empty before rendering a notice area\nif (!flashIsEmpty()) {\n writeOutput(flash("notice"));\n}\n\n// 2. Insert a message and confirm the Flash is no longer empty\nflashInsert(notice="Record saved successfully.");\nempty = flashIsEmpty();\n// empty -> false\n\n// 3. After clearing the Flash, confirm it is empty again\nflashClear();\nempty = flashIsEmpty();\n// empty -> true\n
"},"hint":"Returns whether or not the Flash is empty.\n\n","returntype":"boolean","slug":"controller.flashIsEmpty","parameters":[],"availableIn":["controller"],"name":"flashIsEmpty","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Keep the entire Flash for the next request\nflashKeep();\n\n// 2. Keep the "error" key in the Flash for the next request\nflashKeep("error");\n\n// 3. Keep both the "error" and "success" keys in the Flash for the next request\nflashKeep("error,success");\n
"},"hint":"Make the entire Flash or specific key in it stick around for one more request.\n\n","returntype":"void","slug":"controller.flashKeep","parameters":[{"default":"","required":false,"name":"key","type":"string"}],"availableIn":["controller"],"name":"flashKeep","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check for an "error" key before reading it\nif (flashKeyExists("error")) {\n errorMessage = flash("error");\n}\n\n// 2. Conditionally display a success notice\nif (flashKeyExists("success")) {\n writeOutput(flash("success"));\n}\n\n// 3. Guard before deleting a specific flash key\nif (flashKeyExists("notice")) {\n flashDelete("notice");\n}\n
"},"hint":"Checks if a specific key exists in the Flash.\n\n","returntype":"boolean","slug":"controller.flashKeyExists","parameters":[{"required":true,"hint":"The key to check.","name":"key","type":"string"}],"availableIn":["controller"],"name":"flashKeyExists","tags":{"categoryClass":"flashfunctions","sectionClass":"controller","category":"Flash Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Display all Flash messages in a view\n// In the controller action:\nflashInsert(success="Your post was successfully submitted.");\nflashInsert(alert="Don't forget to tweet about this post!");\nflashInsert(error="This is an error message.");\n\n// In the layout or view:\nwriteOutput(flashMessages());\n\n// Generates (keys sorted alphabetically):\n// <div class="flash-messages">\n// <p class="alert-message">Don't forget to tweet about this post!</p>\n// <p class="error-message">This is an error message.</p>\n// <p class="success-message">Your post was successfully submitted.</p>\n// </div>\n\n\n// 2. Show only a single Flash key using the `key` alias\nwriteOutput(flashMessages(key="success"));\n\n// Generates:\n// <div class="flash-messages">\n// <p class="success-message">Your post was successfully submitted.</p>\n// </div>\n\n\n// 3. Show a specific set of keys in a defined order using `keys`\nwriteOutput(flashMessages(keys="success,alert"));\n\n// Generates (in the order supplied, not alphabetically):\n// <div class="flash-messages">\n// <p class="success-message">Your post was successfully submitted.</p>\n// <p class="alert-message">Don't forget to tweet about this post!</p>\n// </div>\n\n\n// 4. Always render the container div, even when the Flash is empty\nwriteOutput(flashMessages(includeEmptyContainer=true));\n\n// Generates:\n// <div class="flash-messages"></div>\n\n\n// 5. Use a custom CSS class on the outer container\nwriteOutput(flashMessages(class="notifications"));\n\n// Generates:\n// <div class="notifications">\n// <p class="alert-message">Don't forget to tweet about this post!</p>\n// <p class="error-message">This is an error message.</p>\n// <p class="success-message">Your post was successfully submitted.</p>\n// </div>\n
"},"hint":"Displays a marked-up listing of messages that exist in the Flash.\n\n","returntype":"string","slug":"controller.flashMessages","parameters":[{"required":false,"hint":"The key (or list of keys) to show the value for. You can also use the `key` argument instead for better readability when accessing a single key.","name":"keys","type":"string"},{"default":"flash-messages","required":false,"hint":"HTML `class` to set on the `div` element that contains the messages.","name":"class","type":"string"},{"default":"false","required":false,"hint":"Includes the `div` container even if the Flash is empty.","name":"includeEmptyContainer","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"}],"availableIn":["controller"],"name":"flashMessages","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single float column to a new table\nt.float("price");\n\n// 2. Add a float column with a default value\nt.float(columnNames="rating", default="0.0");\n\n// 3. Add multiple float columns at once\nt.float("latitude,longitude");\n\n// 4. Add a float column that does not allow NULL values\nt.float(columnNames="score", allowNull=false);\n\n// 5. Use float() within a createTable migration\nt = createTable("measurements");\nt.float("temperature");\nt.float(columnNames="humidity,pressure", default="0.0");\nt.timestamps();\nt.create();\n
"},"hint":"adds float columns to table definition\n\n","returntype":"any","slug":"tabledefinition.float","parameters":[{"required":false,"name":"columnNames","type":"string"},{"default":"","required":false,"name":"default","type":"any"},{"default":"true","required":false,"name":"allowNull","type":"boolean"}],"availableIn":["tabledefinition"],"name":"float","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Clears the per-request finder cache that cacheQueriesDuringRequest fills, namespaced under the\nreserved request.wheels\n\nmodel(\"X\").forgetCachedQueries()`.\noutside a model.","returntype":"any","slug":"controller.forgetCachedQueries","parameters":[{"default":"","required":false,"hint":"Clear only this model's slot. Defaults to the calling model's own name when invoked as","name":"modelName","type":"string"},{"default":false,"required":false,"hint":"Clear every model's cached queries for the request. Required (true) to wipe everything from","name":"all","type":"boolean"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"forgetCachedQueries","tags":{"categoryClass":"generalfunctions","sectionClass":"miscellaneousfunctions","category":"General Functions","section":"Miscellaneous Functions"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Removes a row from wheels_migrator_versions without running\ndown(). Only orphan versions (those with no matching local file)\ncan be forgotten — for legitimate rollbacks, use migrate down.\nReturns: {success, removed, message}\n\n","returntype":"struct","slug":"migrator.forgetVersion","parameters":[{"required":true,"hint":"The version string to forget (digits only after sanitisation).","name":"version","type":"string"}],"availableIn":["migrator"],"name":"forgetVersion","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Generate a UUID and store it in a variable\nnewId = generateUUID();\n// newId -> "550e8400-e29b-41d4-a716-446655440000" (36-character UUID)\n\n// 2. Use generateUUID() to assign a unique identifier before saving a record\npost = model("Post").new(title="Hello World");\npost.externalId = generateUUID();\npost.save();\n\n// 3. Generate a UUID compatible with SQL Server's uniqueidentifier column\n// Useful when inserting records that need a GUID primary key\ntoken = generateUUID();\n// token -> "a1b2c3d4-e5f6-7890-abcd-ef1234567890"\n
"},"hint":"Generates a 36-character UUID compatible with SQL Server's uniqueidentifier.\n\n","returntype":"string","slug":"controller.generateUUID","parameters":[],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"generateUUID","tags":{"categoryClass":"uuidfunctions","sectionClass":"globalhelpers","category":"UUID Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the current value of a global Wheels setting\nsetting = get("tableNamePrefix");\n// setting -> "" (or whatever prefix has been configured)\n\n// 2. Get the current value of a different global setting\ndsName = get("dataSourceName");\n// dsName -> "myAppDB"\n\n// 3. Get the default for a specific function argument\n// (useful for inspecting function-level defaults set via set())\nmsg = get(functionName="validatesConfirmationOf", name="message");\n// msg -> "[property] should match confirmation"\n
"},"hint":"Returns the current setting for the supplied Wheels setting or the current default for the supplied Wheels function argument.\n\n","returntype":"any","slug":"controller.get","parameters":[{"required":true,"hint":"Variable name to get setting for.","name":"name","type":"string"},{"default":"","required":false,"hint":"Function name to get setting for.","name":"functionName","type":"string"}],"availableIn":["controller","model","migrator","migration","tabledefinition"],"name":"get","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"configuration","category":"Miscellaneous Functions","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\nmapper()\n // 1. Basic GET route using the `to` shorthand (controller##action)\n // Route name: post\n // Example URL: /posts/my-post-title\n // Controller: Posts\n // Action: show\n .get(name="post", pattern="posts/[slug]", to="posts##show")\n\n // 2. Route using separate `controller` and `action` arguments\n // Route name: posts\n // Example URL: /posts\n // Controller: Posts\n // Action: index\n .get(name="posts", controller="posts", action="index")\n\n // 3. Custom URL pattern that differs from the route name\n // Route name: authors\n // Example URL: /the-scribes\n // Controller: Authors\n // Action: index\n .get(name="authors", pattern="the-scribes", to="authors##index")\n\n // 4. Package (subfolder) scoping — keeps the package out of the URL\n // Route name: commerceCart\n // Example URL: /cart\n // Controller: commerce.Carts\n // Action: show\n .get(name="cart", to="carts##show", package="commerce")\n\n // 5. Multi-line format for readability, with package scoping\n // Route name: extranetEditProfile\n // Example URL: /profile/edit\n // Controller: extranet.Profiles\n // Action: edit\n .get(\n name="editProfile",\n pattern="profile/edit",\n to="profiles##edit",\n package="extranet"\n )\n\n // 6. Permanent redirect — useful for renamed or moved URLs\n // Example URL: /old-about -> 302 redirect to /about\n .get(name="oldAbout", pattern="old-about", redirect="/about")\n\n // 7. GET routes scoped inside a nested resource\n .resources(name="users", nested=true)\n // Route name: activatedUsers\n // Example URL: /users/activated\n // Controller: Users\n // Action: activated\n .get(name="activated", to="users##activated", on="collection")\n\n // Route name: preferencesUser\n // Example URL: /users/391/preferences\n // Controller: Preferences\n // Action: index\n .get(name="preferences", to="preferences##index", on="member")\n .end()\n.end();\n\n</cfscript>\n
"},"hint":"Create a route that matches a URL requiring an HTTP GET method. We recommend only using this matcher to expose actions that display data. See post, patch, delete, and put for matchers that are appropriate for actions that change data in your database.\n\n","returntype":"struct","slug":"mapper.get","parameters":[{"required":false,"hint":"Camel-case name of route to reference when build links and form actions (e.g., `blogPost`).","name":"name","type":"string"},{"required":false,"hint":"Overrides the URL pattern that will match the route. The default value is a dasherized version of `name` (e.g., a `name` of `blogPost` generates a pattern of `blog-post`).","name":"pattern","type":"string"},{"required":false,"hint":"Set `controller##action` combination to map the route to. You may use either this argument or a combination of `controller` and `action`.","name":"to","type":"string"},{"required":false,"hint":"Map the route to a given controller. This must be passed along with the `action` argument.","name":"controller","type":"string"},{"required":false,"hint":"Map the route to a given action within the `controller`. This must be passed along with the `controller` argument.","name":"action","type":"string"},{"required":false,"hint":"Indicates a subfolder that the controller will be referenced from (but not added to the URL pattern). For example, if you set this to `admin`, the controller will be located at `admin/YourController.cfc`, but the URL path will not contain `admin/`.","name":"package","type":"string"},{"required":false,"hint":"If this route is within a nested resource, you can set this argument to `member` or `collection`. A `member` route contains a reference to the resource's `key`, while a `collection` route does not.","name":"on","type":"string"},{"required":false,"hint":"Redirect via 302 to this URL when this route is matched. Has precedence over controller/action. Use either an absolute link like `/about/`, or a full canonical link.","name":"redirect","type":"string"}],"availableIn":["mapper"],"name":"get","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get all available migrations and find the latest version\nmigrations = application.wheels.migrator.getAvailableMigrations();\n\nif (arrayLen(migrations)) {\n latestVersion = migrations[arrayLen(migrations)].version;\n} else {\n latestVersion = 0;\n}\n\n// 2. List pending (not yet run) migrations\nmigrations = application.wheels.migrator.getAvailableMigrations();\n\nfor (migration in migrations) {\n if (migration.status != "migrated") {\n writeOutput(migration.version & " - " & migration.name);\n }\n}\n\n// 3. Use a custom migrations path\nmigrations = application.wheels.migrator.getAvailableMigrations(path=expandPath("/app/db/migrate/"));\n
"},"hint":"Searches db/migrate folder for migrations. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n\n$getVersionsPreviouslyMigrated). Callers that already hold the list\n(doctor, info, migrateTo) pass it through to avoid re-running the\ntracking-table probe chain; when empty it is computed here.","returntype":"array","slug":"migrator.getAvailableMigrations","parameters":[{"default":"[runtime expression]","required":false,"hint":"Path to Migration Files: defaults to /app/migrator/migrations/","name":"path","type":"string"},{"default":"","required":false,"hint":"Optional precomputed applied-versions list (from","name":"previousMigrationList","type":"string"}],"availableIn":["migrator"],"name":"getAvailableMigrations","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get current database version\ncurrentVersion = application.wheels.migrator.getCurrentMigrationVersion();\n// currentVersion -> "20240315120000" (timestamp-style version string, or "0" if no migrations have run)\n\n// 2. Display version status in a maintenance view\ncurrentVersion = application.wheels.migrator.getCurrentMigrationVersion();\nif (currentVersion == "0") {\n writeOutput("No migrations have been applied yet.");\n} else {\n writeOutput("Database is at version: " & currentVersion);\n}\n
"},"hint":"Returns current database version. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","returntype":"string","slug":"migrator.getCurrentMigrationVersion","parameters":[],"availableIn":["migrator"],"name":"getCurrentMigrationVersion","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Assert that exactly one email was sent during the action (in a test)\nprocessSignup();\nemails = getEmails();\nassert("arrayLen(emails) eq 1");\nassert("emails[1].to eq 'newuser@example.com'");\nassert("emails[1].subject eq 'Welcome!'");\n\n// 2. Inspect all emails sent during a request\nemails = getEmails();\nfor (email in emails) {\n\twriteOutput(email.to & " — " & email.subject);\n}\n\n// 3. Return an empty array when no emails were sent\nemails = getEmails();\n// emails -> []\n
"},"hint":"Primarily used for testing to get information about emails sent during the request.\n\n","returntype":"array","slug":"controller.getEmails","parameters":[],"availableIn":["controller"],"name":"getEmails","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Assert that exactly one file was sent during the action (in a test)\nprocessDownload();\nfiles = getFiles();\nassert("arrayLen(files) eq 1");\nassert("files[1].name eq 'report.pdf'");\n\n// 2. Inspect all files sent during a request\nfiles = getFiles();\nfor (file in files) {\n\twriteOutput(file.name & " — " & file.type);\n}\n\n// 3. Return an empty array when no files were sent\nfiles = getFiles();\n// files -> []\n
"},"hint":"Primarily used for testing to get information about files sent during the request.\n\n","returntype":"array","slug":"controller.getFiles","parameters":[],"availableIn":["controller"],"name":"getFiles","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Assert that a redirect was performed to a specific URL (in a test)\nprocessDelete();\nredirect = getRedirect();\nassert("structCount(redirect) gt 0");\nassert("redirect.url eq '/users'");\n\n// 2. Inspect the full redirect struct after an action runs\nsubmitLogin();\nredirect = getRedirect();\n// redirect.url -> "/dashboard"\n// redirect.statusCode -> 302\n// redirect.addToken -> false\n\n// 3. Confirm no redirect was performed (action rendered a view instead)\nshowProfile();\nredirect = getRedirect();\n// redirect -> {}\n
"},"hint":"Primarily used for testing to establish whether the current request has performed a redirect.\n\n","returntype":"struct","slug":"controller.getRedirect","parameters":[],"availableIn":["controller"],"name":"getRedirect","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":false,"docs":""},"hint":"","returntype":"any","slug":"mapper.getRoutes","parameters":[],"availableIn":["mapper"],"name":"getRoutes","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
// 1. Use the table name prefix when running a custom query inside a model method\nfunction getDisabledUsers() {\n\tlocal.q = queryExecute(\n\t\t"SELECT * FROM #this.getTableNamePrefix()#users WHERE disabled = 1",\n\t\t[],\n\t\t{datasource: get("dataSourceName")}\n\t);\n\treturn local.q;\n}\n\n// 2. Log the configured prefix to verify model setup\nprefix = model("User").getTableNamePrefix();\n// prefix -> "app_" (or "" if none is set)\n
"},"hint":"Returns the table name prefix set for the table.\n\n","returntype":"string","slug":"model.getTableNamePrefix","parameters":[],"availableIn":["model"],"name":"getTableNamePrefix","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\n// 1. Group routes under a shared path prefix (open/close style)\nmapper()\n .group(path="admin")\n // Route URL: /admin/dashboard\n .get(name="dashboard", to="dashboard##index")\n // Route URL: /admin/reports\n .get(name="reports", to="reports##index")\n .end()\n.end();\n\n// 2. Group with both a path prefix and a name prefix\nmapper()\n .group(path="account", name="account")\n // Route name: accountSettings\n // Example URL: /account/settings\n .get(name="settings", to="settings##show")\n\n // Route name: accountBilling\n // Example URL: /account/billing\n .get(name="billing", to="billing##show")\n .end()\n.end();\n\n// 3. Group with regex constraints applied to all child routes\nmapper()\n .group(path="products", constraints={id: "\\d+"})\n // Only matches numeric :id segments\n .get(name="productShow", pattern="[id]", to="products##show")\n .put(name="productUpdate", pattern="[id]", to="products##update")\n .end()\n.end();\n\n// 4. Group using a callback function (auto-closes the group)\nmapper()\n .group(\n path = "reports",\n name = "report",\n callback = function(mapper) {\n // Route name: reportSales\n // Example URL: /reports/sales\n mapper.get(name="sales", to="reports##sales");\n\n // Route name: reportExpenses\n // Example URL: /reports/expenses\n mapper.get(name="expenses", to="reports##expenses");\n }\n )\n.end();\n\n</cfscript>\n
"},"hint":"Group routes together with shared attributes like path prefix, name prefix, and constraints without implying a controller package or namespace. Unlike namespace() (which maps to a subfolder and URL prefix) or package() (which maps to a subfolder), group() is a pure organizational grouping mechanism.\n\n","returntype":"struct","slug":"mapper.group","parameters":[{"required":false,"hint":"Name to prepend to child route names for use when building links, forms, and other URLs.","name":"name","type":"string"},{"required":false,"hint":"URL path prefix to apply to all child routes.","name":"path","type":"string"},{"required":false,"hint":"Variable patterns (regex constraints) to apply to all child routes.","name":"constraints","type":"struct"},{"required":false,"hint":"A callback function to define nested routes within this group. If provided, the group is automatically closed when the callback completes.","name":"callback","type":"any"}],"availableIn":["mapper"],"name":"group","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Safely output user-supplied text in a view template\nwriteOutput(h(user.name));\n// If user.name is "<script>alert('xss')</script>", outputs the\n// HTML-encoded form: <script>alert(&##x27;xss&##x27;)</script>\n\n// 2. Encode a variable inline in a cfoutput block\n// Instead of: <cfoutput>##user.bio##</cfoutput>\n// Use: <cfoutput>##h(user.bio)##</cfoutput>\nencodedBio = h(user.bio);\n\n// 3. Encode a non-string value (converted to string automatically)\nrating = 4.5;\nwriteOutput(h(rating));\n// rating -> "4.5"\n
"},"hint":"Encodes a value for safe HTML output. Use in templates to prevent XSS:\n#h(user.name)# instead of #user.name#.\n\n","returntype":"string","slug":"controller.h","parameters":[{"required":true,"hint":"The value to encode for HTML output. Converted to string if not already.","name":"value","type":"any"}],"availableIn":["controller"],"name":"h","tags":{"categoryClass":"sanitizationfunctions","sectionClass":"viewhelpers","category":"Sanitization Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check if a specific property has changed before saving\nmember = model("member").findByKey(params.memberId);\nmember.email = params.newEmail;\n\nif (member.hasChanged("email")) {\n // Send a confirmation email before committing the change\n sendEmailChangeNotification(member);\n}\n\n// 2. Check if any property has changed (no argument)\nuser = model("User").findByKey(params.userId);\nuser.setProperties(params.user);\n\nif (user.hasChanged()) {\n // At least one property differs from the persisted state\n user.save();\n}\n\n// 3. Use the dynamic shorthand — automatically generated per property\norder = model("Order").findByKey(params.orderId);\norder.status = "shipped";\n\nif (order.statusHasChanged()) {\n // Equivalent to: order.hasChanged("status")\n notifyCustomer(order);\n}\n\n// 4. New (unsaved) objects always return true — no persisted record exists yet\nnewPost = model("Post").new(title="Hello");\nwriteOutput(newPost.hasChanged()); // -> true\n
"},"hint":"Returns true if the specified property (or any if none was passed in) has been changed but not yet saved to the database.\nWill also return true if the object is new and no record for it exists in the database.\n\n","returntype":"boolean","slug":"model.hasChanged","parameters":[{"default":"","required":false,"hint":"Name of property to check for change.","name":"property","type":"string"}],"availableIn":["model"],"name":"hasChanged","tags":{"categoryClass":"changefunctions","sectionClass":"modelobject","category":"Change Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check if a post object has any errors at all\nif (post.hasErrors()) {\n // Redirect user back to the form to correct errors\n}\n\n// 2. Check if a specific property has errors\nif (post.hasErrors(property="title")) {\n // The title field has at least one error\n}\n\n// 3. Check if any errors were set with a specific name\nif (post.hasErrors(name="uniquenessViolation")) {\n // Handle uniqueness error specifically\n}\n
"},"hint":"Returns true if the object has any errors.\nYou can also limit to only check a specific property or name for errors.\n\n","returntype":"boolean","slug":"model.hasErrors","parameters":[{"default":"","required":false,"hint":"Name of the property to check if there are any errors set on.","name":"property","type":"string"},{"default":"","required":false,"hint":"Error name to check if there are any errors set with.","name":"name","type":"string"}],"availableIn":["model"],"name":"hasErrors","tags":{"categoryClass":"errorfunctions","sectionClass":"modelobject","category":"Error Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage – a Post has many comments (foreign key `postId` lives on the `comments` table)\n// In models/Post.cfc config()\nhasMany("comments");\n\n// 2. Set up a many-to-many shortcut so readers can access publications directly\n// In models/Reader.cfc config()\nhasMany(name="subscriptions", shortcut="publications");\n\n// 3. Automatically delete all associated comments (bypassing object instantiation) when the parent is deleted\n// In models/Post.cfc config()\nhasMany(name="comments", dependent="deleteAll");\n\n// 4. Instantiate and call each comment's beforeDelete callback when deleting dependents\n// In models/Post.cfc config()\nhasMany(name="comments", dependent="delete");\n\n// 5. Override the many-to-many shortcut chain when association names differ from model names\n// In models/Customer.cfc config()\nhasMany(name="subscriptions", shortcut="magazines", through="publication,subscriptions");\n// In models/Subscription.cfc config()\nbelongsTo("customer");\nbelongsTo("publication");\n// In models/Publication.cfc config()\nhasMany("subscriptions");\n\n// 6. Specify a custom foreign key when not following Wheels naming conventions\n// In models/Author.cfc config()\nhasMany(name="articles", foreignKey="writtenByAuthorId");\n\n// 7. Use an inner join instead of the default outer join when including the association\n// In models/Category.cfc config()\nhasMany(name="products", joinType="inner");\n\n// 8. Polymorphic hasMany – a model acts as a parent for a shared `comments` child model\n// In models/Photo.cfc config() (the `as` value matches the `polymorphic` interface name on the child)\nhasMany(name="comments", as="commentable");\n// In models/Comment.cfc config()\nbelongsTo(name="commentable", polymorphic=true);\n
"},"hint":"Sets up a hasMany association between this model and the specified one.\n\n","returntype":"void","slug":"model.hasMany","parameters":[{"required":true,"hint":"Gives the association a name that you refer to when working with the association (in the `include` argument to `findAll`, to name one example).","name":"name","type":"string"},{"default":"","required":false,"hint":"Name of associated model (usually not needed if you follow Wheels conventions because the model name will be deduced from the `name` argument).","name":"modelName","type":"string"},{"default":"","required":false,"hint":"Foreign key property name (usually not needed if you follow Wheels conventions since the foreign key name will be deduced from the `name` argument).","name":"foreignKey","type":"string"},{"default":"","required":false,"hint":"Column name to join to if not the primary key (usually not needed if you follow Wheels conventions since the join key will be the table's primary key/keys).","name":"joinKey","type":"string"},{"default":"outer","required":false,"hint":"Use to set the join type when joining associated tables. Possible values are `inner` (for `INNER JOIN`) and `outer` (for `LEFT OUTER JOIN`).","name":"joinType","type":"string"},{"default":false,"required":false,"hint":"Defines how to handle dependent model objects when you delete an object from this model. `delete` / `deleteAll` deletes the record(s) (`deleteAll` bypasses object instantiation). `remove` / `removeAll` sets the forein key field(s) to `NULL` (`removeAll` bypasses object instantiation).","name":"dependent","type":"string"},{"default":"","required":false,"hint":"Set this argument to create an additional dynamic method that gets the object(s) from the other side of a many-to-many association.","name":"shortcut","type":"string"},{"default":"[runtime expression]","required":false,"hint":"Set this argument if you need to override Wheels conventions when using the `shortcut` argument. Accepts a list of two association names representing the chain from the opposite side of the many-to-many relationship to this model.","name":"through","type":"string"},{"default":"","required":false,"hint":"Set this argument to declare a polymorphic `hasMany` association. The child model stores the parent type in a `{as}Type` column alongside the foreign key `{as}Id`.","name":"as","type":"string"},{"default":"","required":false,"hint":"The column that stores the owning model's name in a polymorphic association. Defaults to `{name}Type`. Pass it, with `foreignKey`, when the columns are named differently, e.g. `notable_type` / `notable_id` as `t.references(polymorphic = true)` writes them when `useUnderscoreReferenceColumns` is on.","name":"foreignType","type":"string"}],"availableIn":["model"],"name":"hasMany","tags":{"categoryClass":"associationfunctions","sectionClass":"modelconfiguration","category":"Association Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Show check boxes for associating authors with the current book\n<cfloop query="authors">\n #hasManyCheckBox(\n label=authors.fullName,\n objectName="book",\n association="bookAuthors",\n keys="#book.key()#,#authors.id#"\n )#\n</cfloop>\n\n// 2. Wrap each checkbox and label in a div using prepend/append\n<cfloop query="authors">\n #hasManyCheckBox(\n label=authors.fullName,\n labelPlacement="after",\n objectName="book",\n association="bookAuthors",\n keys="#book.key()#,#authors.id#",\n prepend="<div class=""author-option"">",\n append="</div>"\n )#\n</cfloop>\n\n// 3. Supply an explicit ID and custom error styling\n<cfloop query="tags">\n #hasManyCheckBox(\n label=tags.name,\n objectName="post",\n association="postTags",\n keys="#post.key()#,#tags.id#",\n id="tag-#tags.id#",\n errorElement="span",\n errorClass="field-error"\n )#\n</cfloop>\n
"},"hint":"Used as a shortcut to output the proper form elements for an association.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.hasManyCheckBox","parameters":[{"required":true,"hint":"Name of the variable containing the parent object to represent with this form field.","name":"objectName","type":"string"},{"required":true,"hint":"Name of the association set in the parent object to represent with this form field.","name":"association","type":"string"},{"required":true,"hint":"Keys of the join row for this form field: the parent key, then the other key (for example a post key and a tag id). For a composite-key join model, list them in the order of its primary key columns. A surrogate-`id` join model works too: the keys are matched on its `belongsTo` foreign keys. Either way, declare a `belongsTo` association on the join model for each key column.","name":"keys","type":"string"},{"required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using `aroundLeft` or `aroundRight`.","name":"labelPlacement","type":"string"},{"required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"required":false,"hint":"The `class` name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"required":false,"hint":"Optional. Explicit ID for the generated checkbox input. If not provided, an ID will be generated automatically.","name":"id","type":"string"}],"availableIn":["controller"],"name":"hasManyCheckBox","tags":{"categoryClass":"formassociationfunctions","sectionClass":"viewhelpers","category":"Form Association Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Show radio buttons for selecting a default address for the current author (loops over a query of addresses)\n<cfoutput>\n\t<cfloop query="addresses">\n\t\t#hasManyRadioButton(\n\t\t\tobjectName="author",\n\t\t\tassociation="addresses",\n\t\t\tproperty="isDefault",\n\t\t\tkeys="#author.key()#,#addresses.id#",\n\t\t\ttagValue="1",\n\t\t\tlabel=addresses.title\n\t\t)#\n\t</cfloop>\n</cfoutput>\n\n// 2. Same loop, but mark the radio button as checked when the property is blank (no default set yet)\n<cfoutput>\n\t<cfloop query="addresses">\n\t\t#hasManyRadioButton(\n\t\t\tobjectName="author",\n\t\t\tassociation="addresses",\n\t\t\tproperty="isDefault",\n\t\t\tkeys="#author.key()#,#addresses.id#",\n\t\t\ttagValue="1",\n\t\t\tcheckIfBlank=true,\n\t\t\tlabel=addresses.title\n\t\t)#\n\t</cfloop>\n</cfoutput>\n
"},"hint":"Used as a shortcut to output the proper form elements for an association.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.hasManyRadioButton","parameters":[{"required":true,"hint":"Name of the variable containing the parent object to represent with this form field.","name":"objectName","type":"string"},{"required":true,"hint":"Name of the association set in the parent object to represent with this form field.","name":"association","type":"string"},{"required":true,"hint":"Name of the property in the child object to represent with this form field.","name":"property","type":"string"},{"required":true,"hint":"Primary keys associated with this form field. Note that these keys should be listed in the order that they appear in the database table.","name":"keys","type":"string"},{"required":true,"hint":"The value of the radio button when selected.","name":"tagValue","type":"string"},{"default":false,"required":false,"hint":"Whether or not to check this form field as a default if there is a blank value set for the property.","name":"checkIfBlank","type":"boolean"},{"required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"hasManyRadioButton","tags":{"categoryClass":"formassociationfunctions","sectionClass":"viewhelpers","category":"Form Association Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Specify that instances of this model have one profile. (The associated model's table, not the current one, should have the foreign key column.)\nhasOne("profile");\n\n// 2. Same as above but setting `joinType` to `inner`, meaning this model should always have a matching record in the `profiles` table.\nhasOne(name="profile", joinType="inner");\n\n// 3. Automatically delete the associated `profile` record whenever this object is deleted.\nhasOne(name="profile", dependent="delete");\n\n// 4. Declare a polymorphic `hasOne` association so that multiple models can each have one image via a shared interface.\nhasOne(name="image", as="imageable");\n
"},"hint":"Sets up a hasOne association between this model and the specified one.\n\n","returntype":"void","slug":"model.hasOne","parameters":[{"required":true,"hint":"Gives the association a name that you refer to when working with the association (in the `include` argument to `findAll`, to name one example).","name":"name","type":"string"},{"default":"","required":false,"hint":"Name of associated model (usually not needed if you follow Wheels conventions because the model name will be deduced from the `name` argument).","name":"modelName","type":"string"},{"default":"","required":false,"hint":"Foreign key property name (usually not needed if you follow Wheels conventions since the foreign key name will be deduced from the `name` argument).","name":"foreignKey","type":"string"},{"default":"","required":false,"hint":"Column name to join to if not the primary key (usually not needed if you follow Wheels conventions since the join key will be the table's primary key/keys).","name":"joinKey","type":"string"},{"default":"outer","required":false,"hint":"Use to set the join type when joining associated tables. Possible values are `inner` (for `INNER JOIN`) and `outer` (for `LEFT OUTER JOIN`).","name":"joinType","type":"string"},{"default":false,"required":false,"hint":"Defines how to handle dependent model objects when you delete an object from this model. `delete` / `deleteAll` deletes the record(s) (`deleteAll` bypasses object instantiation). `remove` / `removeAll` sets the forein key field(s) to `NULL` (`removeAll` bypasses object instantiation).","name":"dependent","type":"string"},{"default":"","required":false,"hint":"Set this argument to declare a polymorphic `hasOne` association. The child model stores the parent type in a `{as}Type` column alongside the foreign key `{as}Id`.","name":"as","type":"string"},{"default":"","required":false,"hint":"The column that stores the owning model's name in a polymorphic association. Defaults to `{name}Type`. Pass it, with `foreignKey`, when the columns are named differently, e.g. `notable_type` / `notable_id` as `t.references(polymorphic = true)` writes them when `useUnderscoreReferenceColumns` is on.","name":"foreignType","type":"string"}],"availableIn":["model"],"name":"hasOne","tags":{"categoryClass":"associationfunctions","sectionClass":"modelconfiguration","category":"Association Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check whether a property exists on a new object after setting it\nemployee = model("Employee").new();\nemployee.firstName = "Jane";\nemployee.hasProperty("firstName"); // -> true\nemployee.hasProperty("salary"); // -> false (not set on this object)\n\n// 2. Use the equivalent dynamic method (has<PropertyName>)\nemployee.hasFirstName(); // -> true\nemployee.hasSalary(); // -> false\n\n// 3. Guard logic before accessing a property\nuser = model("User").findOne(where="email='jane@example.com'");\nif (user.hasProperty("avatarUrl")) {\n writeOutput(user.avatarUrl);\n}\n
"},"hint":"Returns true if the specified property name exists on the model.\n\n","returntype":"boolean","slug":"model.hasProperty","parameters":[{"required":true,"hint":"Name of property to inspect.","name":"property","type":"string"}],"availableIn":["model"],"name":"hasProperty","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelobject","category":"Miscellaneous Functions","section":"Model Object"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns true if the last successful save changed the specified property, or any property if\nnone is passed in. See savedChanges() for when that information is available.\n\n","returntype":"boolean","slug":"model.hasSavedChange","parameters":[{"default":"","required":false,"hint":"Name of property (or a list of properties) to check.","name":"property","type":"string"}],"availableIn":["model"],"name":"hasSavedChange","tags":{"categoryClass":"changefunctions","sectionClass":"modelobject","category":"Change Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Safely encode a user-supplied string inside an HTML attribute\nuserBio = "Say ""hello"" & <wave>";\nwriteOutput('<div title="#hAttr(userBio)#">Hover me</div>');\n<!--- Renders: <div title="Say "hello" & <wave>">Hover me</div> --->\n\n// 2. Use directly in a view template to prevent XSS in attribute values\nwriteOutput('<input type="text" placeholder="#hAttr(params.search)#">');\n
"},"hint":"Encodes a value for safe use inside an HTML attribute.\nUse when building attribute values manually:\n<div title=\"#hAttr(user.bio)#\">.\n\n","returntype":"string","slug":"controller.hAttr","parameters":[{"required":true,"hint":"The value to encode for HTML attribute context.","name":"value","type":"any"}],"availableIn":["controller"],"name":"hAttr","tags":{"categoryClass":"sanitizationfunctions","sectionClass":"viewhelpers","category":"Sanitization Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\nmapper()\n // 1. Register the default health check route at /health.\n // Responds with {"status":"ok","timestamp":"..."} — no controller needed.\n .health()\n\n .root(to="home##index")\n .wildcard()\n.end();\n\n// 2. Override the URL path and route name.\n// Accessible at /healthz instead of /health.\nmapper()\n .health(path="healthz", name="healthz")\n .root(to="home##index")\n.end();\n\n// 3. Delegate to a custom controller action for advanced health checks\n// (e.g. database ping, cache connectivity).\nmapper()\n .health(to="system##health")\n .root(to="home##index")\n.end();\n\n</cfscript>\n
"},"hint":"Register a health check route at /health (or a custom path). Returns a JSON response with status and timestamp by default, or delegates to a custom controller action.\nThis is useful for container orchestration (Kubernetes liveness/readiness probes), load balancer health checks, and monitoring tools.\n\n","returntype":"struct","slug":"mapper.health","parameters":[{"default":"wheels#health","required":false,"hint":"Set `controller##action` combination for a custom health check handler. If not provided, a default handler returns `{\"status\":\"ok\",\"timestamp\":\"...\"}`.","name":"to","type":"string"},{"default":"health","required":false,"hint":"Override the URL path. Defaults to `\"health\"`.","name":"path","type":"string"},{"default":"health","required":false,"hint":"Override the route name. Defaults to `\"health\"`.","name":"name","type":"string"}],"availableIn":["mapper"],"name":"health","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage: embed the user's id as a hidden field\n#hiddenField(objectName="user", property="id")#\n// -> <input type="hidden" id="user-id" name="user[id]" value="42">\n\n// 2. Carry a token value using a class attribute for JavaScript hooks\n#hiddenField(objectName="user", property="csrfToken", class="js-token")#\n// -> <input type="hidden" id="user-csrf-token" name="user[csrfToken]" class="js-token" value="abc123">\n\n// 3. Nested form — pass the parent's id through a hasMany association\n#hiddenField(objectName="order", property="id", association="lineItems", position="1")#\n// -> <input type="hidden" id="order-line-items-1-id" name="order[lineItems][1][id]" value="7">\n
"},"hint":"Builds and returns a string containing a hidden field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.hiddenField","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"}],"availableIn":["controller"],"name":"hiddenField","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage with a name and value\n#hiddenFieldTag(name="userId", value=user.id)#\n// -> <input type="hidden" name="userId" value="42">\n\n// 2. Embed a CSRF token in a standalone form\n#hiddenFieldTag(name="csrfToken", value=session.csrfToken)#\n// -> <input type="hidden" name="csrfToken" value="a1b2c3d4...">\n\n// 3. Pass extra HTML attributes via additional arguments\n#hiddenFieldTag(name="returnTo", value="/dashboard", id="returnToField")#\n// -> <input type="hidden" name="returnTo" value="/dashboard" id="returnToField">\n
"},"hint":"Builds and returns a string containing a hidden field form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.hiddenFieldTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value to populate in tag's value attribute.","name":"value","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"}],"availableIn":["controller"],"name":"hiddenFieldTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Highlight a single phrase in text\n// Outputs: You searched for: <span class="highlight">CFWheels</span> framework\nresult = highlight(text="You searched for: CFWheels framework", phrase="CFWheels");\n\n// 2. Highlight multiple phrases using a comma-delimited list\n// Outputs: <span class="highlight">Open</span> source <span class="highlight">CFML</span> framework\nresult = highlight(text="Open source CFML framework", phrase="Open,CFML");\n\n// 3. Highlight with a custom tag and CSS class\n// Outputs: Learn <strong class="match">ColdFusion</strong> today\nresult = highlight(text="Learn ColdFusion today", phrase="ColdFusion", tag="strong", class="match");\n
"},"hint":"Highlights the phrase(s) everywhere in the text if found by wrapping them in span tags.\n\n","returntype":"string","slug":"controller.highlight","parameters":[{"required":true,"hint":"Text to search in.","name":"text","type":"string"},{"required":false,"hint":"Phrase (or list of phrases) to highlight. This argument is also aliased as `phrases`.","name":"phrase","type":"string"},{"default":",","required":false,"hint":"Delimiter to use when passing in multiple phrases.","name":"delimiter","type":"string"},{"default":"span","required":false,"hint":"HTML tag to use to wrap the highlighted phrase(s).","name":"tag","type":"string"},{"default":"highlight","required":false,"hint":"Class to use in the tags wrapping highlighted phrase(s).","name":"class","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"}],"availableIn":["controller"],"name":"highlight","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage — render a select control for hours of the day\n#hourSelectTag(name="hourOfMeeting", selected=params.hourOfMeeting)#\n\n// 2. Show hours in 12-hour (AM/PM) format instead of 24-hour format\n#hourSelectTag(name="hourOfMeeting", selected=params.hourOfMeeting, twelveHour=true)#\n\n// 3. Include a blank option as a placeholder prompt and add a label\n#hourSelectTag(name="startHour", selected=params.startHour, includeBlank="-- Select Hour --", label="Start Hour")#\n
"},"hint":"Builds and returns a string containing one select form control for the hours of the day based on the supplied name.\n\n","returntype":"string","slug":"controller.hourSelectTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"The hour that should be selected initially.","name":"selected","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":false,"required":false,"hint":"whether to display the hours in 24 or 12 hour format. 12 hour format has AM/PM drop downs","name":"twelveHour","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":"[runtime expression]","required":false,"name":"$now","type":"date"}],"availableIn":["controller"],"name":"hourSelectTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Humanize a camelCase string\nresult = humanize("wheelsIsAFramework");\n// result -> "Wheels Is A Framework"\n\n// 2. Humanize a string and replace an abbreviation using the except argument\nresult = humanize("wheelsIsACfmlFramework", "CFML");\n// result -> "Wheels Is A CFML Framework"\n\n// 3. Humanize a multi-word property name from a model attribute\nresult = humanize("firstName");\n// result -> "First Name"\n
"},"hint":"Returns readable text by capitalizing and converting camel casing to multiple words.\n\n","returntype":"string","slug":"controller.humanize","parameters":[{"required":true,"hint":"Text to humanize.","name":"text","type":"string"},{"default":"","required":false,"hint":"A list of strings (space separated) to replace within the output.","name":"except","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"humanize","tags":{"categoryClass":"stringfunctions","sectionClass":"globalhelpers","category":"String Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic camelCase to hyphenated string\nresult = hyphenize("myBlogPost");\n// result -> "my-blog-post"\n\n// 2. Single word (no change)\nresult = hyphenize("hello");\n// result -> "hello"\n\n// 3. Used in URL slug generation\nslug = hyphenize("userProfileSettings");\n// slug -> "user-profile-settings"\n
"},"hint":"Converts camelCase strings to lowercase strings with hyphens as word delimiters instead. Example: myVariable becomes my-variable.\n\n","returntype":"string","slug":"controller.hyphenize","parameters":[{"required":true,"hint":"The string to hyphenize.","name":"string","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"hyphenize","tags":{"categoryClass":"stringfunctions","sectionClass":"globalhelpers","category":"String Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Ignore a single column in the model's config() method\n// In app/models/User.cfc\ncomponent extends="Model" {\n\tfunction config() {\n\t\tignoredColumns(columns=["legacyField"]);\n\t}\n}\n\n// 2. Ignore multiple columns so they are excluded from Wheels ORM property mapping\n// In app/models/Product.cfc\ncomponent extends="Model" {\n\tfunction config() {\n\t\tignoredColumns(columns=["internalCode", "deprecatedFlag", "tempCache"]);\n\t}\n}\n
"},"hint":"Use this method to specify which columns cannot be used by the wheels ORM.\n\n","returntype":"void","slug":"model.ignoredColumns","parameters":[{"default":"[runtime expression]","required":false,"hint":"Array of columns names that will be ignored.","name":"columns","type":"array"}],"availableIn":["model"],"name":"ignoredColumns","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelconfiguration","category":"Miscellaneous Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Output an img tag for a local image (width, height, and alt are auto-detected)\nwriteOutput(imageTag("logo.png"));\n\n// 2. Output an img tag for an image hosted on an external server\nwriteOutput(imageTag(source="https://example.com/images/logo.png", alt="Company Logo"));\n\n// 3. Output an img tag with additional HTML attributes\nwriteOutput(imageTag(source="logo.png", class="logo", id="mainLogo"));\n\n// 4. Output an img tag without requiring the file to exist locally (useful in development)\nwriteOutput(imageTag(source="placeholder.png", required=false));\n
"},"hint":"Returns an img tag.\nIf the image is stored in the local images folder, the tag will also set the width, height, and alt attributes for you.\nYou can pass any additional arguments (e.g. class, rel, id), and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.imageTag","parameters":[{"required":true,"hint":"The file name of the image if it's available in the local file system (i.e. ColdFusion will be able to access it). Provide the full URL if the image is on a remote server.","name":"source","type":"string"},{"default":true,"required":false,"name":"onlyPath","type":"boolean"},{"default":"","required":false,"name":"host","type":"string"},{"default":"","required":false,"name":"protocol","type":"string"},{"default":0,"required":false,"name":"port","type":"numeric"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"},{"default":true,"required":false,"name":"required","type":"boolean"}],"availableIn":["controller"],"name":"imageTag","tags":{"categoryClass":"assetfunctions","sectionClass":"viewhelpers","category":"Asset Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Output the main page body inside a layout (default section is "body")\n// In `app/views/layout.cfm`:\n<html>\n\t<head>\n\t\t<title>My Site</title>\n\t</head>\n\t<body>\n\t\t<cfoutput>\n\t\t\t#includeContent()#\n\t\t</cfoutput>\n\t</body>\n</html>\n\n// 2. Define a named section in a view, then render it in the layout\n// In `app/views/blog/show.cfm`:\ncontentFor(head='<meta name="description" content="Read our latest post">');\n\n// In `app/views/layout.cfm`:\n<html>\n\t<head>\n\t\t<title>My Site</title>\n\t\t<cfoutput>#includeContent("head")#</cfoutput>\n\t</head>\n\t<body>\n\t\t<cfoutput>#includeContent()#</cfoutput>\n\t</body>\n</html>\n\n// 3. Provide a default value when a section may not have been defined\n<cfoutput>\n\t#includeContent(name="sidebar", defaultValue="<p>No sidebar content.</p>")#\n</cfoutput>\n
"},"hint":"Used to output the content for a particular section in a layout.\n\n","returntype":"string","slug":"controller.includeContent","parameters":[{"default":"body","required":false,"hint":"Name of layout section to return content for.","name":"name","type":"string"},{"default":"","required":false,"hint":"What to display as a default if the section is not defined.","name":"defaultValue","type":"string"},{"required":false,"hint":"Opt-in HTML encode of the stored section. Default is omitted (no encode) so layouts that store HTML keep working.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"includeContent","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check whether a customer is already subscribed to a particular publication via a hasMany join\n// (Note: keys should be listed in the order they appear in the join table columns)\nif (includedInObject(objectName="customer", association="subscriptions", keys="#customer.key()#,#swimsuitEdition.id#")) {\n writeOutput("Already subscribed.");\n} else {\n writeOutput("Not yet subscribed.");\n}\n\n// 2. Use the return value to find the position of the associated object in the array\nposition = includedInObject(objectName="order", association="lineItems", keys="#lineItem.key()#");\n// Returns false when not found, or the 1-based index position when found\n// position -> 3 (the associated lineItem is at index 3 in order.lineItems)\n\n// 3. Guard against adding duplicate associations before creating a new join record\nif (!includedInObject(objectName="student", association="courses", keys="#course.key()#")) {\n student.courses = ArrayAppend(student.courses, course);\n}\n
"},"hint":"Used as a shortcut to check if the specified IDs are a part of the main form object.\nThis method should only be used for hasMany associations.\n\n","returntype":"boolean","slug":"controller.includedInObject","parameters":[{"required":true,"hint":"Name of the variable containing the parent object to represent with this form field.","name":"objectName","type":"string"},{"required":true,"hint":"Name of the association set in the parent object to represent with this form field.","name":"association","type":"string"},{"required":true,"hint":"Primary keys associated with this form field. Note that these keys should be listed in the order that they appear in the database table.","name":"keys","type":"string"}],"availableIn":["controller"],"name":"includedInObject","tags":{"categoryClass":"formassociationfunctions","sectionClass":"viewhelpers","category":"Form Association Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Include the default parent layout from within a child layout\n// (looks for `app/views/layout.cfm` by default)\n#includeLayout()#\n\n// 2. Include a specific parent layout by path\n// (looks for `app/views/layouts/application.cfm`)\n#includeLayout("/layouts/application.cfm")#\n\n// 3. Pass section content to the parent layout before including it\n// Capture sidebar markup to make it available in the parent layout\n<cfsavecontent variable="sidebar">\n <nav>\n #includePartial("categories")#\n </nav>\n</cfsavecontent>\n<cfset contentFor(sidebar=sidebar)>\n\n// Then pull in the parent layout that renders the sidebar via includeContent()\n#includeLayout("/layouts/application.cfm")#\n
"},"hint":"Includes the contents of another layout file.\nThis is usually used to include a parent layout from within a child layout.\n\n","returntype":"string","slug":"controller.includeLayout","parameters":[{"default":"layout","required":false,"hint":"Name of the layout file to include.","name":"name","type":"string"}],"availableIn":["controller"],"name":"includeLayout","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Include a partial from the current controller's view folder.\n// When in the "sessions" controller, Wheels looks for "app/views/sessions/_login.cfm".\n#includePartial("login")#\n\n// 2. Include a partial relative to the root views folder using a leading slash.\n// Wheels looks for "app/views/shared/_button.cfm".\n#includePartial(partial="/shared/button")#\n\n// 3. Pass a query to loop through records automatically.\n// Wheels loops through the result set and renders "app/views/posts/_post.cfm" for each row.\nposts = model("Post").findAll();\n#includePartial(posts)#\n\n// 4. Override the template when rendering a query.\n// Provide the template path via partial and pass the query separately.\nposts = model("Post").findAll();\n#includePartial(partial="/shared/post", query=posts)#\n\n// 5. Pass a single model object — Wheels renders the matching partial for its model type.\npost = model("Post").findByKey(params.key);\n#includePartial(post)#\n\n// 6. Override the template when rendering a single model object.\npost = model("Post").findByKey(params.key);\n#includePartial(partial="/shared/post", object=post)#\n\n// 7. Pass an array of model objects — Wheels iterates and renders the partial for each.\nposts = model("Post").findAll(returnAs="objects");\n#includePartial(posts)#\n\n// 8. Override the template when rendering an array of model objects.\nposts = model("Post").findAll(returnAs="objects");\n#includePartial(partial="/shared/post", objects=posts)#\n\n// 9. Cache the partial output for 30 minutes to reduce processing overhead.\n// The cache key is a hash of every argument, including the full contents (all rows)\n// of a "query" argument, so editing a row produces a new cache key automatically —\n// there is no need to clear the cache by hand. Partial caching only runs when the\n// "cachePartials" setting is on (on in production, off in development and testing).\n#includePartial(partial="sidebar", cache=30)#\n\n// 9b. Caching a partial that renders a query, plus viewer-specific output.\n// The query's rows are part of the key, so the cache refreshes when the data changes.\n// Pass any state the output depends on (here whether the viewer may edit) as an\n// argument so it becomes part of the key and each variant is cached separately.\nposts = model("Post").findAll();\n#includePartial(partial="post", query=posts, editable=canEditPosts, cache=30)#\n\n// 10. Group a query result set by a column before rendering.\n// Wheels splits the query into sub-queries grouped by "categoryId"\n// and passes each sub-query into "app/views/products/_product.cfm".\nproducts = model("Product").findAll(order="categoryId");\n#includePartial(partial="product", query=products, group="categoryId")#\n\n// 11. Insert a separator string between each rendered partial in a loop.\nposts = model("Post").findAll();\n#includePartial(partial="post", query=posts, spacer="<hr>")#\n
"},"hint":"Includes the specified partial file in the view.\nSimilar to using cfinclude but with the ability to cache the result and use Wheels-specific file look-up.\nBy default, Wheels will look for the file in the current controller's view folder.\nTo include a file relative from the base views folder, you can start the path supplied to partial with a forward slash.\n\n","returntype":"string","slug":"controller.includePartial","parameters":[{"required":true,"hint":"The name of the partial file to be used. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Do not include the partial filename's underscore and file extension. If you want to have Wheels display the partial for a single model object, array of model objects, or a query, pass a variable containing that data into this argument.","name":"partial","type":"any"},{"default":"","required":false,"hint":"If passing a query result set for the partial argument, use this to specify the field to group the query by. A new query will be passed into the partial template for you to iterate over.","name":"group","type":"string"},{"default":"","required":false,"hint":"Number of minutes to cache the content for. The cache key is a hash of every argument passed to the partial, including the full contents (all rows) of a `query` argument, so editing a row produces a new cache key automatically. Pass any viewer state the output depends on (for example `editable=true`) as an argument so it becomes part of the key. Partial caching runs only when the `cachePartials` setting is on — on in production, off in development and testing.","name":"cache","type":"any"},{"default":"","required":false,"hint":"The layout to wrap the content in. Prefix with a leading slash (`/`) if you need to build a path from the root `views` folder. Pass `false` to not load a layout at all.","name":"layout","type":"string"},{"default":"","required":false,"hint":"HTML or string to place between partials when called using a query.","name":"spacer","type":"string"},{"default":true,"required":false,"hint":"Name of controller function to load data from.","name":"dataFunction","type":"any"},{"default":true,"required":false,"name":"$prependWithUnderscore","type":"boolean"}],"availableIn":["controller"],"name":"includePartial","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"viewhelpers","category":"Miscellaneous Functions","section":"View Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Initialize a streaming SSE connection that bypasses the normal Wheels rendering pipeline.\nReturns a writer object that can be used with sendSSEEvent() and closeSSEStream().\nThis enables sending multiple events over a single connection.\nNote: This bypasses layouts and after-filters. Use for true streaming endpoints only.","returntype":"any","slug":"controller.initSSEStream","parameters":[],"availableIn":["controller"],"name":"initSSEStream","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":false,"docs":""},"hint":"Declare one or more services for injection into this controller.\nCall in config(). Services are resolved when the controller instance is created.","returntype":"void","slug":"controller.inject","parameters":[{"required":true,"hint":"Comma-delimited list of registered service names to inject.","name":"name","type":"string"}],"availableIn":["controller"],"name":"inject","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":false,"docs":""},"hint":"Return the list of declared service names for this controller.","returntype":"array","slug":"controller.injectedServices","parameters":[],"availableIn":["controller"],"name":"injectedServices","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
// 1. Register a singleton service in `config/services.cfm` (one instance per app lifetime)\ndi = injector();\ndi.map("emailService").to("app.lib.EmailService").asSingleton();\n\n// 2. Bind an interface name to a concrete implementation\ndi = injector();\ndi.bind("INotifier").to("app.lib.SlackNotifier").asSingleton();\n\n// 3. Register a request-scoped service (one instance per HTTP request)\ndi = injector();\ndi.map("currentUser").to("app.lib.CurrentUserResolver").asRequestScoped();\n\n// 4. Inspect or resolve at runtime\ndi = injector();\nif (di.containsInstance("emailService")) {\n mailer = di.getInstance("emailService");\n mailer.send(to="user@example.com", subject="Welcome");\n}\n
"},"hint":"Return a reference to the DI container for direct configuration.\n\n","returntype":"any","slug":"controller.injector","parameters":[],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"injector","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"globalhelpers","category":"Miscellaneous Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Insert multiple user records in a single batch\nnewUsers = [\n {firstName: "Alice", lastName: "Smith", email: "alice@example.com"},\n {firstName: "Bob", lastName: "Jones", email: "bob@example.com"},\n {firstName: "Carol", lastName: "White", email: "carol@example.com"}\n];\nresult = model("User").insertAll(records=newUsers);\n// result -> {insertedCount: 3}\n\n// 2. Insert records without automatic createdAt/updatedAt timestamps\nrows = [\n {username: "imported_1", score: 9800},\n {username: "imported_2", score: 7450}\n];\nresult = model("HighScore").insertAll(records=rows, timestamps=false);\n// result -> {insertedCount: 2}\n\n// 3. Insert a large dataset wrapped in a single transaction, using selective cfqueryparam\nproducts = [];\nfor (i = 1; i <= 2500; i++) {\n arrayAppend(products, {name: "Product #i#", price: RandRange(1, 999), stock: RandRange(0, 500)});\n}\n// Batches automatically in groups of 1000; all batches share one transaction.\nresult = model("Product").insertAll(\n records = products,\n transaction = "commit",\n parameterize = "price,stock"\n);\n// result -> {insertedCount: 2500}\n
"},"hint":"Inserts multiple records into the database in a single batch operation.\nAccepts an array of structs where each struct represents a record to insert.\nAll structs must have the same set of keys (property names).\nBatches in groups of up to 1000 rows, fewer where the database limits the parameters per\nstatement (SQL Server). All batches run in one\ntransaction (see transaction), so a failing batch rolls back the ones before it. No\nvalidations or callbacks run.\n\n","returntype":"struct","slug":"model.insertAll","parameters":[{"required":true,"hint":"Array of structs, each containing property name/value pairs to insert.","name":"records","type":"array"},{"default":true,"required":false,"hint":"Set to `false` to skip automatic `createdAt`/`updatedAt` timestamping.","name":"timestamps","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"}],"availableIn":["model"],"name":"insertAll","tags":{"categoryClass":"createfunctions","sectionClass":"modelclass","category":"Create Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Add a single integer column to a new table\nt = createTable(name='products');\n\tt.string(columnNames='name', limit=255, allowNull=false);\n\tt.integer(columnNames='quantity');\n\tt.timestamps();\nt.create();\n\n// 2. Add multiple integer columns at once with a default value\nt = createTable(name='scores');\n\tt.integer(columnNames='wins,losses,draws', default=0, allowNull=false);\n\tt.string(columnNames='playerName', limit=100, allowNull=false);\n\tt.timestamps();\nt.create();\n\n// 3. Add an integer column with a limit when altering an existing table\nt = changeTable(name='orders');\n\tt.integer(columnNames='itemCount', default=0, allowNull=false, limit=4);\nt.change();\n
"},"hint":"adds integer columns to table definition\n\n","returntype":"any","slug":"tabledefinition.integer","parameters":[{"required":false,"name":"columnNames","type":"string"},{"required":false,"name":"limit","type":"numeric"},{"required":false,"name":"default","type":"any"},{"required":false,"name":"allowNull","type":"boolean"},{"required":false,"name":"unsigned","type":"boolean"}],"availableIn":["tabledefinition"],"name":"integer","tags":{"categoryClass":"tabledefinitionfunctions","sectionClass":"migrator","category":"Table Definition Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Run a custom model method inside a database transaction.\n// Define the method on the model (e.g. Person.cfc):\npublic boolean function transferFunds(required any personFrom, required any personTo, required numeric amount) {\n\tif (arguments.personFrom.withdraw(arguments.amount) && arguments.personTo.deposit(arguments.amount)) {\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n}\n\n// Then invoke it wrapped in a transaction from a controller action:\nlocal.david = model("Person").findOneByName("David");\nlocal.mary = model("Person").findOneByName("Mary");\nlocal.success = model("Person").invokeWithTransaction(method="transferFunds", personFrom=local.david, personTo=local.mary, amount=100);\n\n// 2. Run in rollback mode to test queries without committing changes.\nlocal.success = model("Person").invokeWithTransaction(method="transferFunds", personFrom=local.david, personTo=local.mary, amount=100, transaction="rollback");\n\n// 3. Run with a stricter isolation level (e.g. serializable) to prevent phantom reads.\nlocal.success = model("Person").invokeWithTransaction(method="transferFunds", personFrom=local.david, personTo=local.mary, amount=100, isolation="serializable");\n
"},"hint":"Runs the specified method within a single database transaction.\n\n","returntype":"any","slug":"model.invokeWithTransaction","parameters":[{"required":true,"hint":"Model method to run.","name":"method","type":"string"},{"default":"commit","required":false,"hint":"Set this to `commit` to update the database, `rollback` to run all the database queries but not commit them, or `none` to skip transaction handling altogether.","name":"transaction","type":"string"},{"required":false,"hint":"Isolation level to be passed through to the cftransaction tag. Defaults to the `transactionIsolation` setting (`read_committed` unless the app changes it). An empty string sends no isolation attribute, so the transaction uses the engine's or driver's default. See your CFML engine's documentation for more details about cftransaction's isolation attribute.","name":"isolation","type":"string"}],"availableIn":["model"],"name":"invokeWithTransaction","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Respond differently based on whether the request is an AJAX call\nif (isAjax()) {\n renderNothing();\n} else {\n redirectTo(action = "index");\n}\n\n// 2. Return JSON for AJAX requests, render a full view otherwise\nif (isAjax()) {\n renderWith(data = model("Article").findAll(returnAs = "objects"));\n} else {\n articles = model("Article").findAll();\n}\n
"},"hint":"Returns whether the page was called from JavaScript or not.\n\n","returntype":"boolean","slug":"controller.isAjax","parameters":[],"availableIn":["controller"],"name":"isAjax","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Use isClass() to branch between class-level and instance-level behavior\n// In a model method, detect whether the method is being called on the class\n// (e.g. model("User").isAdmin(42)) or on an instance (e.g. user.isAdmin()).\nfunction isAdmin(numeric id) {\n\tif (isClass()) {\n\t\t// Called on the class — look up the record by the provided id\n\t\treturn this.findByKey(arguments.id).admin;\n\t} else {\n\t\t// Called on an instance — the property is already available\n\t\treturn this.admin;\n\t}\n}\n\n// 2. Guard a class-only operation\nfunction resetAllPasswords() {\n\tif (!isClass()) {\n\t\tThrow(type="App.Error", message="resetAllPasswords must be called on the class, not an instance.");\n\t}\n\tthis.updateAll(password="changeme");\n}\n
"},"hint":"Use this method to check whether you are currently in a class-level object.\n\n","returntype":"string","slug":"model.isClass","parameters":[],"availableIn":["model"],"name":"isClass","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Only process delete logic when the request method is DELETE\nif (isDelete()) {\n // perform delete operation\n}\n\n// 2. Assign the result to a variable for later use\nrequestIsDelete = isDelete();\n
"},"hint":"Returns whether the request was a DELETE request or not.\n\n","returntype":"boolean","slug":"controller.isDelete","parameters":[],"availableIn":["controller"],"name":"isDelete","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Only allow GET requests in an action\nif (!isGet()) {\n redirectTo(action = "index");\n}\n\n// 2. Respond differently depending on the HTTP method\nif (isGet()) {\n // Render the form for display\n user = model("User").findByKey(params.key);\n} else {\n // Handle a non-GET submission\n renderNothing();\n}\n\n// 3. Store the result to use in a conditional\nrequestIsGet = isGet();\n// requestIsGet -> true (for a normal page request), false otherwise\n
"},"hint":"Returns whether the request was a normal GET request or not.\n\n","returntype":"boolean","slug":"controller.isGet","parameters":[],"availableIn":["controller"],"name":"isGet","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Respond to a HEAD request by rendering nothing\nif (isHead()) {\n renderNothing();\n}\n\n// 2. Restrict an action to HEAD requests only\nif (!isHead()) {\n renderText("Method not allowed");\n}\n\n// 3. Store the result to use in a conditional\nrequestIsHead = isHead();\n// requestIsHead -> true when the HTTP method is HEAD, false otherwise\n
"},"hint":"Returns whether the request was a HEAD request or not.\n\n","returntype":"boolean","slug":"controller.isHead","parameters":[],"availableIn":["controller"],"name":"isHead","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Branch logic inside a shared model method based on class vs. instance context\nfunction memberIsAdmin() {\n\tif (isInstance()) {\n\t\t// Called on an instance object — property is already loaded\n\t\treturn this.admin;\n\t} else {\n\t\t// Called on the class — look up the record first\n\t\treturn this.findByKey(arguments.id).admin;\n\t}\n}\n\n// 2. Use isInstance() in config() to guard instance-only setup\ncomponent extends="Model" {\n\tfunction config() {\n\t\tif (isInstance()) {\n\t\t\t// Instance-specific initialization (rarely needed; shown for contrast)\n\t\t} else {\n\t\t\t// Class-level configuration: validations, associations, callbacks\n\t\t\tvalidatesPresenceOf(properties="username,email");\n\t\t\thasMany(name="posts");\n\t\t}\n\t}\n}\n\n// 3. Pair with isClass() to make the intent explicit\nfunction label() {\n\tif (isClass()) {\n\t\treturn "User (class)";\n\t}\n\treturn "User #this.id#";\n}\n
"},"hint":"Use this method to check whether you are currently in an instance object.\n\n","returntype":"boolean","slug":"model.isInstance","parameters":[],"availableIn":["model"],"name":"isInstance","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check if a newly instantiated object has been saved to the database\nemployee = model("Employee").new(firstName="Jane", lastName="Doe");\nif (employee.isNew()) {\n // employee.save() has not been called yet, so no DB record exists\n employee.save();\n}\n\n// 2. Check after loading from the database (isNew() returns false for persisted records)\nemployee = model("Employee").findOne(where="firstName='Jane'");\nif (!employee.isNew()) {\n // record already exists in the database\n employee.firstName = "Janet";\n employee.save();\n}\n\n// 3. Useful inside a before/after callback to branch logic for new vs. existing records\n// In Employee.cfc:\ncomponent extends="Model" {\n function config() {\n beforeSave("stampAuditFields");\n }\n private function stampAuditFields() {\n if (isNew()) {\n this.createdBy = request.currentUserId;\n }\n this.updatedBy = request.currentUserId;\n }\n}\n
"},"hint":"Returns true if this object hasn't been saved yet (in other words, no matching record exists in the database yet).\nReturns false if a record exists.\n\n","returntype":"boolean","slug":"model.isNew","parameters":[],"availableIn":["model"],"name":"isNew","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelobject","category":"Miscellaneous Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Respond to a CORS preflight OPTIONS request\nif (isOptions()) {\n header(name = "Access-Control-Allow-Methods", value = "GET, POST, PUT, DELETE");\n renderNothing();\n return;\n}\n\n// 2. Restrict an action to only handle OPTIONS requests\nif (!isOptions()) {\n redirectTo(action = "index");\n}\n\n// 3. Store the result to use in a conditional\nrequestIsOptions = isOptions();\n// requestIsOptions -> true when the HTTP method is OPTIONS, false otherwise\n
"},"hint":"Returns whether the request was an OPTIONS request or not.\n\n","returntype":"boolean","slug":"controller.isOptions","parameters":[],"availableIn":["controller"],"name":"isOptions","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Only handle PATCH requests in an action\nif (!isPatch()) {\n redirectTo(action = "index");\n}\n\n// 2. Respond differently depending on whether the request is a PATCH\nif (isPatch()) {\n // Apply a partial update to the resource\n user = model("User").findByKey(params.key);\n user.update(params.user);\n} else {\n // Not a PATCH request; redirect away\n redirectTo(action = "index");\n}\n\n// 3. Store the result to use in a conditional\nrequestIsPatch = isPatch();\n// requestIsPatch -> true for a PATCH request, false otherwise\n
"},"hint":"Returns whether the request was a PATCH request or not.\n\n","returntype":"boolean","slug":"controller.isPatch","parameters":[],"availableIn":["controller"],"name":"isPatch","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Check if a newly created (unsaved) object has been persisted\nuser = model("User").new(firstName="Jane", lastName="Doe");\nwriteOutput(user.isPersisted()); // -> false\n\n// 2. Check if an object loaded from the database is persisted\nuser = model("User").findByKey(1);\nwriteOutput(user.isPersisted()); // -> true\n\n// 3. Check persistence after saving a new object\npost = model("Post").new(title="Hello World", body="First post.");\npost.save();\nwriteOutput(post.isPersisted()); // -> true\n
"},"hint":"Returns true if this object has been persisted to the database or was loaded from the database via a finder.\nReturns false if the record has not been persisted to the database.\n\n","returntype":"boolean","slug":"model.isPersisted","parameters":[],"availableIn":["model"],"name":"isPersisted","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelobject","category":"Miscellaneous Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
// 1. Respond differently depending on whether the request is a POST\nif (isPost()) {\n // Process the submitted form data\n user = model("User").new(params.user);\n if (user.save()) {\n redirectTo(action="index");\n } else {\n renderView(action="new");\n }\n} else {\n renderView(action="new");\n}\n\n// 2. Guard an action so it only accepts POST requests\nfunction create() {\n if (!isPost()) {\n renderNothing(status="405 Method Not Allowed");\n return;\n }\n // handle form submission\n}\n\n// 3. Store the result for later use in the action\nrequestIsPost = isPost();\n// requestIsPost -> true (when submitted via a form POST)\n// requestIsPost -> false (when the page is visited normally with GET)\n
"},"hint":"Returns whether the request came from a form POST submission or not.\n\n","returntype":"boolean","slug":"controller.isPost","parameters":[],"availableIn":["controller"],"name":"isPost","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Allow only PUT requests for a resource update action\nif (!isPut()) {\n redirectTo(action = "index");\n}\n// ... proceed with update logic\n\n// 2. Branch behavior based on HTTP method\nif (isPut()) {\n // Full replacement of the resource\n user = model("User").findByKey(params.key);\n user.update(params.user);\n redirectTo(action = "show", key = user.key());\n} else {\n renderNothing();\n}\n
"},"hint":"Returns whether the request was a PUT request or not.\n\n","returntype":"boolean","slug":"controller.isPut","parameters":[],"availableIn":["controller"],"name":"isPut","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns true when redirectUrl stays on this site: a relative URL, or an absolute or\nprotocol-relative URL whose host is the current server. This is the same rule\nredirectTo(url=...) applies before it redirects, so use it to check a return-to URL\n(for example params.return_to) before storing it or building a link from it.\n\n","returntype":"boolean","slug":"controller.isSafeRedirectUrl","parameters":[{"required":true,"hint":"The URL to check.","name":"redirectUrl","type":"string"},{"default":"[runtime expression]","required":false,"hint":"The host to compare against. Defaults to the current request's server name.","name":"serverName","type":"string"}],"availableIn":["controller"],"name":"isSafeRedirectUrl","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// 1. Redirect non-secure connections to the HTTPS version\nif (!isSecure()) {\n\tredirectTo(protocol="https");\n}\n\n// 2. Conditionally set a secure cookie flag based on the connection\ncookieOptions = {secure: isSecure(), httpOnly: true};\n\n// 3. Log a warning when a sensitive action is performed over a non-secure connection\nif (!isSecure()) {\n\tlogMessage("WARNING: sensitive action performed over non-secure connection");\n}\n
"},"hint":"Returns whether Wheels is communicating over a secure port.\nX-Forwarded-Proto is client-controlled and is only honored when the app has opted into\nproxy trust via set(trustProxyHeaders=true) behind a trusted reverse proxy.\n\n","returntype":"boolean","slug":"controller.isSecure","parameters":[],"availableIn":["controller"],"name":"isSecure","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"controller","category":"Miscellaneous Functions","section":"Controller"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Check if the current request is from an EventSource client.\nUseful for conditionally rendering SSE vs HTML responses.","returntype":"boolean","slug":"controller.isSSERequest","parameters":[],"availableIn":["controller"],"name":"isSSERequest","tags":{"categoryClass":"","sectionClass":"","category":"","section":""}},{"extended":{"hasExtended":true,"docs":"
<!--- view code --->\n<head>\n <!--- Includes `javascripts/main.js` --->\n #javaScriptIncludeTag("main")#\n\n <!--- Includes `javascripts/blog.js` and `javascripts/accordion.js` --->\n #javaScriptIncludeTag("blog,accordion")#\n\n <!--- Includes an external JavaScript file --->\n #javaScriptIncludeTag("https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js")#\n\n <!--- Uses a pipe delimiter instead of the default comma --->\n #javaScriptIncludeTag(sources="app|utils|vendor", delim="|")#\n</head>\n\n<body>\n <!--- Will still appear in the `head` --->\n #javaScriptIncludeTag(source="tabs", head=true)#\n</body>\n
"},"hint":"Returns a script tag for a JavaScript file (or several) based on the supplied arguments.\n\n","returntype":"string","slug":"controller.javaScriptIncludeTag","parameters":[{"default":"","required":false,"hint":"The name of one or many JavaScript files in the `javascripts` folder, minus the `.js` extension. Pass a full URL to access an external JavaScript file. Can also be called with the `source` argument.","name":"sources","type":"string"},{"default":"text/javascript","required":false,"hint":"The `type` attribute for the `script` tag.","name":"type","type":"string"},{"default":false,"required":false,"hint":"Set to `true` to place the output in the `head` area of the HTML page instead of the default behavior (which is to place the output where the function is called from).","name":"head","type":"boolean"},{"default":",","required":false,"hint":"The delimiter to use for the list of JavaScript files.","name":"delim","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"boolean"}],"availableIn":["controller"],"name":"javaScriptIncludeTag","tags":{"categoryClass":"assetfunctions","sectionClass":"viewhelpers","category":"Asset Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the primary key value of a found object\nemployee = model("Employee").findByKey(params.key);\nwriteOutput(employee.key());\n// -> 42\n\n// 2. Use key() when you don't know the primary key column name (dynamic programming)\nobj = model(params.modelName).findByKey(params.id);\nif (IsObject(obj)) {\n\twriteOutput("Found record with key: " & obj.key());\n}\n\n// 3. Composite primary key — key() returns a comma-delimited list of both values\norderItem = model("OrderItem").findByKey(key="1,5");\nwriteOutput(orderItem.key());\n// -> 1,5 (orderId and productId combined)\n
"},"hint":"Returns the value of the primary key for the object.\nIf you have a single primary key named id, then someObject.key() is functionally equivalent to someObject.id.\nThis method is more useful when you do dynamic programming and don't know the name of the primary key or when you use composite keys (in which case it's convenient to use this method to get a list of both key values returned).\n\n","returntype":"string","slug":"model.key","parameters":[{"default":false,"required":false,"name":"$persisted","type":"boolean"},{"default":false,"required":false,"name":"$returnTickCountWhenNew","type":"boolean"}],"availableIn":["model"],"name":"key","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelobject","category":"Miscellaneous Functions","section":"Model Object"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: Basic usage — show a "Last" link at the bottom of a\n// paginated list; renders a disabled span when already on the last page\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nposts = model("Post").findAll(page=params.page, perPage=10, order="createdAt DESC");\n\n// View code\n<cfoutput>\n #firstPageLink()#\n #previousPageLink()#\n #pageNumberLinks()#\n #nextPageLink()#\n #lastPageLink()#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n<cfoutput>\n #lastPageLink(\n text="Last »»",\n class="page-link",\n disabledClass="page-link disabled"\n )#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the last page\n\n// View code\n<cfoutput>\n #lastPageLink(showDisabled=false)#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/3)\n\n// Route setup in app/config/routes.cfm\nmapper()\n .get(name="paginatedArticles", pattern="articles/page/[page]", to="articles##index")\n .get(name="articles", pattern="articles", to="articles##index")\n.end();\n\n// Controller code\nparam name="params.page" type="integer" default="1";\narticles = model("Article").findAll(page=params.page, perPage=20, order="title");\n\n// View code\n<cfoutput>\n #lastPageLink(route="paginatedArticles", pageNumberAsParam=false)#\n</cfoutput>\n
"},"hint":"Creates a link to the last page, or a disabled span when already on the last page.\n\n","returntype":"string","slug":"controller.lastPageLink","parameters":[{"default":"Last","required":false,"hint":"The text for the link.","name":"text","type":"string"},{"default":"query","required":false,"hint":"The handle given to the query that the pagination should be displayed for.","name":"handle","type":"string"},{"default":"page","required":false,"hint":"The name of the param that holds the current page number.","name":"name","type":"string"},{"default":"","required":false,"hint":"CSS class for the link element.","name":"class","type":"string"},{"default":"disabled","required":false,"hint":"CSS class for the disabled span element.","name":"disabledClass","type":"string"},{"default":true,"required":false,"hint":"Whether to render a disabled span when already on the last page.","name":"showDisabled","type":"boolean"},{"default":true,"required":false,"hint":"Decides whether to link the page number as a param or as part of a route.","name":"pageNumberAsParam","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"lastPageLink","tags":{"categoryClass":"paginationfunctions","sectionClass":"viewhelpers","category":"Pagination Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Link to a controller/action pair\nwriteOutput(linkTo(text="Log Out", controller="account", action="logout"));\n// -> <a href="/account/logout">Log Out</a>\n\n// 2. Omit the controller when linking within the same controller\n// (CFWheels uses the current controller automatically)\nwriteOutput(linkTo(text="Log Out", action="logout"));\n// -> <a href="/account/logout">Log Out</a>\n\n// 3. Link to a specific record using a key\nwriteOutput(linkTo(text="View Post", controller="blog", action="post", key=99));\n// -> <a href="/blog/post/99">View Post</a>\n\n// 4. Pass extra query string parameters\nwriteOutput(linkTo(text="View Settings", action="settings", params="show=all&sort=asc"));\n// -> <a href="/account/settings?show=all&sort=asc">View Settings</a>\n\n// 5. Use a named route (configured in app/config/routes.cfm)\nwriteOutput(linkTo(text="Joe's Profile", route="userProfile", userName="joe"));\n// -> <a href="/user/joe">Joe's Profile</a>\n\n// 6. Link to an external URL, bypassing the routing system\nwriteOutput(linkTo(text="ColdFusion on Wheels", href="https://cfwheels.org/"));\n// -> <a href="https://cfwheels.org/">ColdFusion on Wheels</a>\n\n// 7. Add HTML attributes (class, id, rel, etc.) via extra arguments\nwriteOutput(linkTo(text="Delete Post", action="delete", key=99, class="delete", id="delete-99"));\n// -> <a class="delete" href="/blog/delete/99" id="delete-99">Delete Post</a>\n\n// 8. Include icon markup in link text; use encode="attributes" to encode\n// only attribute values and leave the tag content (the icon HTML) untouched\nwriteOutput(linkTo(text="<i class='fa fa-trash'></i> Delete Post", encode="attributes", action="delete", key=99));\n// -> <a href="/blog/delete/99"><i class='fa fa-trash'></i> Delete Post</a>\n\n// 9. Build an absolute URL by turning off onlyPath and setting a protocol/host\nwriteOutput(linkTo(text="Home", action="index", onlyPath=false, protocol="https", host="www.example.com"));\n// -> <a href="https://www.example.com/home/index">Home</a>\n\n// 10. Link to an anchor on the target page\nwriteOutput(linkTo(text="Jump to Comments", controller="blog", action="post", key=99, anchor="comments"));\n// -> <a href="/blog/post/99#comments">Jump to Comments</a>\n
"},"hint":"Creates a link to another page in your application.\nPass in the name of a route to use your configured routes or a controller/action/key combination.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.linkTo","parameters":[{"required":false,"hint":"The text content of the link.","name":"text","type":"string"},{"default":"","required":false,"hint":"Name of a route that you have configured in config/routes.cfm.","name":"route","type":"string"},{"default":"","required":false,"hint":"Name of the controller to include in the URL.","name":"controller","type":"string"},{"default":"","required":false,"hint":"Name of the action to include in the URL.","name":"action","type":"string"},{"default":"","required":false,"hint":"Key(s) to include in the URL.","name":"key","type":"any"},{"default":"","required":false,"hint":"Any additional parameters to be set in the query string (example: wheels=cool&x=y). Please note that Wheels uses the & and = characters to split the parameters and encode them properly for you. However, if you need to pass in & or = as part of the value, then you need to encode them (and only them), example: a=cats%26dogs%3Dtrouble!&b=1.","name":"params","type":"string"},{"default":"","required":false,"hint":"Sets an anchor name to be appended to the path.","name":"anchor","type":"string"},{"default":true,"required":false,"hint":"If true, returns only the relative URL (no protocol, host name or port).","name":"onlyPath","type":"boolean"},{"default":"","required":false,"hint":"Set this to override the current host.","name":"host","type":"string"},{"default":"","required":false,"hint":"Set this to override the current protocol.","name":"protocol","type":"string"},{"default":0,"required":false,"hint":"Set this to override the current port number.","name":"port","type":"numeric"},{"required":false,"hint":"Pass a link to an external site here if you want to bypass the Wheels routing system altogether and link to an external URL.","name":"href","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":false,"required":false,"hint":"When true, blank out caller-supplied `javascript:` / `data:` hrefs. Default false (B3: default deny is a public-behavior change).","name":"sanitizeHref","type":"boolean"}],"availableIn":["controller"],"name":"linkTo","tags":{"categoryClass":"linkfunctions","sectionClass":"viewhelpers","category":"Link Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic mailto link using the email address as the link text\nmailTo(emailAddress="webmaster@example.com");\n// -> <a href="mailto:webmaster@example.com">webmaster@example.com</a>\n\n// 2. Mailto link with a custom display name\nmailTo(emailAddress="support@example.com", name="Contact Support");\n// -> <a href="mailto:support@example.com">Contact Support</a>\n\n// 3. Mailto link with additional HTML attributes (class, title)\nmailTo(emailAddress="info@example.com", name="Email Us", class="email-link", title="Send us a message");\n// -> <a href="mailto:info@example.com" class="email-link" title="Send us a message">Email Us</a>\n
"},"hint":"Creates a mailto link tag to the specified email address, which is also used as the name of the link unless name is specified.\n\n","returntype":"string","slug":"controller.mailTo","parameters":[{"required":true,"hint":"The email address to link to.","name":"emailAddress","type":"string"},{"default":"","required":false,"hint":"A string to use as the link text (\"Joe\" or \"Support Department\", for example).","name":"name","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"mailTo","tags":{"categoryClass":"linkfunctions","sectionClass":"viewhelpers","category":"Link Functions","section":"View Helpers"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Returns the mapper object used to configure your application's routes. Usually you will use this method in config/routes.cfm to start chaining route mapping methods like resources, namespace, etc.\n\n","returntype":"struct","slug":"controller.mapper","parameters":[{"default":true,"required":false,"hint":"Whether to turn on RESTful routing or not. Not recommended to set. Will probably be removed in a future version of wheels, as RESTful routes are the default.","name":"restful","type":"boolean"},{"default":"[runtime expression]","required":false,"hint":"If not RESTful, then specify allowed routes. Not recommended to set. Will probably be removed in a future version of wheels, as RESTful routes are the default.","name":"methods","type":"boolean"},{"default":true,"required":false,"hint":"This is useful for providing formats via URL like `json`, `xml`, `pdf`, etc. Set to false to disable automatic .[format] generation for resource based routes","name":"mapFormat","type":"boolean"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"mapper","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the highest salary across all employees\nhighestSalary = model("employee").maximum("salary");\n\n// 2. Get the highest salary for employees in a specific department\nhighestSalary = model("employee").maximum(property="salary", where="departmentId=#params.key#");\n\n// 3. Return 0 instead of a blank string when no matching records are found\nhighestSalary = model("employee").maximum(property="salary", where="salary > #params.minSalary#", ifNull=0);\n\n// 4. Get the highest salary per department (returns a query with departmentId and the maximum value)\nsalaryByDept = model("employee").maximum(property="salary", group="departmentId");\n
"},"hint":"Calculates the maximum value for a given property.\nUses the SQL function MAX.\nIf no records can be found to perform the calculation on you can use the ifNull argument to decide what should be returned.\n\n","returntype":"any","slug":"model.maximum","parameters":[{"required":true,"hint":"Name of the property to get the highest value for (must be a property of a numeric data type).","name":"property","type":"string"},{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":true,"required":false,"name":"parameterize","type":"any"},{"default":"","required":false,"hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","name":"ifNull","type":"any"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"required":false,"hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"group","type":"string"}],"availableIn":["model"],"name":"maximum","tags":{"categoryClass":"statisticsfunctions","sectionClass":"modelclass","category":"Statistics Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\n// 1. Add a preview route acting on a single photo (GET /photos/1/preview)\nmapper()\n .resources(name="photos", nested=true)\n .member()\n .get("preview")\n .end()\n .end()\n.end();\n\n// 2. Add multiple member routes (GET /articles/1/publish, DELETE /articles/1/archive)\nmapper()\n .resources(name="articles", nested=true)\n .member()\n .get("publish")\n .delete("archive")\n .end()\n .end()\n.end();\n\n</cfscript>\n
"},"hint":"Scope routes within a nested resource which require use of the primary key as part of the URL pattern;\nA member route will require an ID, because it acts on a member.\nphotos/1/preview is an example of a member route, because it acts on (and displays) a single object.\n\n","returntype":"struct","slug":"mapper.member","parameters":[],"availableIn":["mapper"],"name":"member","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Run a specific migration by version number (out-of-sequence)\nresult = application.wheels.migrator.migrateIndividual("20240315120000");\n// result -> "Running individual migration 20240315120000.\n// -------- 20240315120000_add_status_to_orders --------------------\n// "\n\n// 2. Check the result string for errors or success messages\nresult = application.wheels.migrator.migrateIndividual("20240101000000");\nif (FindNoCase("Error", result)) {\n writeOutput("Migration failed: " & result);\n} else if (FindNoCase("already been applied", result)) {\n writeOutput("Skipped: migration was already applied.");\n} else {\n writeOutput("Migration applied successfully.");\n}\n\n// 3. Apply an individual colleague's migration without advancing the version pointer\n// This is useful when a team member's migration has a lower timestamp than\n// the current version but was not yet applied in your environment.\ncolVersion = "20231205083000";\nresult = application.wheels.migrator.migrateIndividual(colVersion);\nwriteOutput(result);\n
"},"hint":"Runs a single specific migration's up() regardless of sequence order.\nUsed for out-of-sequence migrations that were created by other developers\nand need to be applied individually without affecting the current version pointer.\n\n","returntype":"string","slug":"migrator.migrateIndividual","parameters":[{"required":true,"hint":"The version number of the specific migration to run","name":"version","type":"string"}],"availableIn":["migrator"],"name":"migrateIndividual","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Migrate up to a specific version\nresult = application.wheels.migrator.migrateTo("20240315120000");\n// result -> "Migrating from 20231201000000 up to 20240315120000.\n// -------- 20240315120000_add_status_to_orders --------------------\n// "\n\n// 2. Migrate down to an earlier version (rolls back newer migrations)\nresult = application.wheels.migrator.migrateTo("20230601000000");\n// result -> "Migrating from 20240315120000 down to 20230601000000.\n// ------- 20240315120000_add_status_to_orders ---------------------\n// "\n\n// 3. Migrate to version 0 (rolls back all migrations)\nresult = application.wheels.migrator.migrateTo("0");\n// result -> "Migrating from 20240315120000 down to 0.\n// ..."\n\n// 4. Check the result string for errors before proceeding\nresult = application.wheels.migrator.migrateTo("20240315120000");\nif (FindNoCase("Error", result)) {\n writeOutput("Migration failed: " & result);\n} else {\n writeOutput("Migration result: " & result);\n}\n\n// 5. Apply a missing (out-of-order gap) migration using missingMigFlag\n// Use this when a migration with a timestamp earlier than the current version\n// was never applied in your environment.\nresult = application.wheels.migrator.migrateTo(\n version = "20231205083000",\n missingMigFlag = true\n);\nwriteOutput(result);\n
"},"hint":"Migrates database to a specified version. Whilst you can use this in your application, the recommended usage is via either the CLI or the provided GUI interface\n\n","returntype":"string","slug":"migrator.migrateTo","parameters":[{"default":"","required":false,"hint":"The Database schema version to migrate to","name":"version","type":"string"},{"default":false,"required":false,"hint":"Flag for any available missing migrations","name":"missingMigFlag","type":"boolean"}],"availableIn":["migrator"],"name":"migrateTo","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Run all pending migrations to bring the database up to the latest version\nresult = application.wheels.migrator.migrateToLatest();\n// result -> "Migrating from 20240101000000 up to 20240315120000.\n// -------- 20240315120000_add_status_to_orders --------------------\n// "\n\n// 2. Already at the latest version — no migration required\nresult = application.wheels.migrator.migrateToLatest();\n// result -> "Database is currently at version 20240315120000. No migration required."\n\n// 3. Check for errors after migrating to latest\nresult = application.wheels.migrator.migrateToLatest();\nif (FindNoCase("Error", result)) {\n writeOutput("Migration failed: " & result);\n} else {\n writeOutput("All migrations applied successfully.");\n}\n
"},"hint":"Shortcut function to migrate to the latest version\n\n","returntype":"string","slug":"migrator.migrateToLatest","parameters":[],"availableIn":["migrator"],"name":"migrateToLatest","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":false,"docs":""},"hint":"Reports who holds the migration lock (#4209): held, expired (its lease ran out, so the\nnext migration takes it over), owner, host, heldForSeconds and expiresInSeconds\n(negative once expired). A missing lock table means nothing holds it.\n\n","returntype":"struct","slug":"migrator.migrationLockStatus","parameters":[],"availableIn":["migrator"],"name":"migrationLockStatus","tags":{"categoryClass":"generalfunctions","sectionClass":"migrator","category":"General Functions","section":"Migrator"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the MIME type for a known file extension\nmimeType = mimeTypes("xls");\n// mimeType -> "application/vnd.ms-excel"\n\n// 2. Get the MIME type for a dynamic extension from user input, with a custom fallback\nmimeType = mimeTypes(extension=params.fileType, fallback="text/plain");\n\n// 3. Use the default fallback (application/octet-stream) for an unknown extension\nmimeType = mimeTypes("xyz");\n// mimeType -> "application/octet-stream"\n
"},"hint":"Returns an associated MIME type based on a file extension.\n\n","returntype":"string","slug":"controller.mimeTypes","parameters":[{"required":true,"hint":"The extension to get the MIME type for.","name":"extension","type":"string"},{"default":"application/octet-stream","required":false,"hint":"The fallback MIME type to return.","name":"fallback","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"mimeTypes","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"globalhelpers","category":"Miscellaneous Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get the amount of the lowest salary for all employees\nlowestSalary = model("employee").minimum("salary");\n\n// 2. Get the amount of the lowest salary for employees in a given department\nlowestSalary = model("employee").minimum(property="salary", where="departmentId=#params.key#");\n\n// 3. Make sure a numeric amount is always returned, even when there were no records analyzed by the query\nlowestSalary = model("employee").minimum(property="salary", where="salary BETWEEN #params.min# AND #params.max#", ifNull=0);\n
"},"hint":"Calculates the minimum value for a given property.\nUses the SQL function MIN.\nIf no records can be found to perform the calculation on you can use the ifNull argument to decide what should be returned.\n\n","returntype":"any","slug":"model.minimum","parameters":[{"required":true,"hint":"Name of the property to get the lowest value for (must be a property of a numeric data type).","name":"property","type":"string"},{"default":"","required":false,"hint":"Maps to the `WHERE` clause of the query (or `HAVING` when necessary). The following operators are supported: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `AND`, and `OR` (note that the key words need to be written in upper case). You can also use parentheses to group statements. Nested queries not allowed. You do not need to specify the table name(s); Wheels will do that for you.","name":"where","type":"string"},{"default":"","required":false,"hint":"Associations that should be included in the query using `INNER` or `LEFT OUTER` joins (which join type that is used depends on how the association has been set up in your model). If all included associations are set on the current model, you can specify them in a list (e.g. `department,addresses,emails`). You can build more complex include strings by using parentheses when the association is set on an included model, like `album(artist(genre))`, for example. These complex `include` strings only work when `returnAs` is set to `query` though.","name":"include","type":"string"},{"default":true,"required":false,"hint":"Set to `true` to use `cfqueryparam` on all columns, or pass in a list of property names to use `cfqueryparam` on those only.","name":"parameterize","type":"any"},{"default":"","required":false,"hint":"The value returned if no records are found. Common usage is to set this to `0` to make sure a numeric value is always returned instead of a blank string.","name":"ifNull","type":"any"},{"default":"false","required":false,"hint":"Set to `true` to include soft-deleted records in the queries that this method runs.","name":"includeSoftDeletes","type":"boolean"},{"required":false,"hint":"Maps to the `GROUP BY` clause of the query. You do not need to specify the table name(s); Wheels will do that for you.","name":"group","type":"string"}],"availableIn":["model"],"name":"minimum","tags":{"categoryClass":"statisticsfunctions","sectionClass":"modelclass","category":"Statistics Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage — the "Tag" version accepts a `name` and `selected` instead of binding to a model object\n<cfoutput>\n #minuteSelectTag(name="minuteOfMeeting", selected=params.minuteOfMeeting)#\n</cfoutput>\n\n// 2. Only show 15-minute intervals\n<cfoutput>\n #minuteSelectTag(name="minuteOfMeeting", selected=params.minuteOfMeeting, minuteStep=15)#\n</cfoutput>\n\n// 3. Include a blank option and add a label\n<cfoutput>\n #minuteSelectTag(name="minuteOfMeeting", selected=params.minuteOfMeeting, includeBlank=true, label="Minute")#\n</cfoutput>\n
"},"hint":"Builds and returns a string containing one select form control for the minutes of an hour based on the supplied name.\n\n","returntype":"string","slug":"controller.minuteSelectTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"The minute that should be selected initially.","name":"selected","type":"string"},{"default":1,"required":false,"hint":"Pass in 10 to only show minute 10, 20, 30, etc.","name":"minuteStep","type":"numeric"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":"[runtime expression]","required":false,"name":"$now","type":"date"}],"availableIn":["controller"],"name":"minuteSelectTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get a reference to the User model and call a class-level finder on it\nuser = model("User").findByKey(params.key);\n\n// 2. Find all active users by calling findAll() on the model reference\nactiveUsers = model("User").findAll(where="active = 1", order="lastName");\n\n// 3. Create a new record via the model reference\nnewPost = model("Post").new(title=params.title, body=params.body);\nnewPost.save();\n\n// 4. Count records using the model reference\ntotalOrders = model("Order").count(where="status = 'pending'");\n
"},"hint":"Returns a reference to the requested model so that class level methods can be called on it.\n\n","returntype":"any","slug":"controller.model","parameters":[{"required":true,"hint":"Name of the model to get a reference to.","name":"name","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"model","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"globalhelpers","category":"Miscellaneous Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic usage: render a month select tag bound to a form param\n<cfoutput>\n #monthSelectTag(name="monthOfBirthday", selected=params.monthOfBirthday)#\n</cfoutput>\n\n// 2. Display month abbreviations instead of full names and include a blank prompt\n<cfoutput>\n #monthSelectTag(\n name="month",\n selected=params.month,\n monthDisplay="abbreviations",\n includeBlank="- Select Month -"\n )#\n</cfoutput>\n\n// 3. Display month numbers with a label wrapped around the control\n<cfoutput>\n #monthSelectTag(\n name="expirationMonth",\n selected=params.expirationMonth,\n monthDisplay="numbers",\n label="Expiration Month"\n )#\n</cfoutput>\n
"},"hint":"Builds and returns a string containing a select form control for the months of the year based on the supplied name.\n\n","returntype":"string","slug":"controller.monthSelectTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"The month that should be selected initially.","name":"selected","type":"string"},{"default":"names","required":false,"hint":"Pass in names, numbers, or abbreviations to control display.","name":"monthDisplay","type":"string"},{"default":"January,February,March,April,May,June,July,August,September,October,November,December","required":false,"hint":"[see:dateSelect].","name":"monthNames","type":"string"},{"default":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","required":false,"hint":"[see:dateSelect].","name":"monthAbbreviations","type":"string"},{"default":false,"required":false,"hint":"Whether to include a blank option in the select form control. Pass true to include a blank line or a string that should represent what display text should appear for the empty value (for example, \"- Select One -\").","name":"includeBlank","type":"any"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"},{"default":"[runtime expression]","required":false,"name":"$now","type":"date"}],"availableIn":["controller"],"name":"monthSelectTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\nmapper()\n .namespace("api")\n .namespace("v2")\n // Route name: apiV2Products\n // Example URL: /api/v2/products/1234\n // Controller: api.v2.Products\n .resources("products")\n .end()\n\n .namespace("v1")\n // Route name: apiV1Users\n // Example URL: /api/v1/users\n // Controller: api.v1.Users\n .get(name="users", to="users##index")\n .end()\n .end()\n\n // Custom package and path: name="foo", package="foos", path="foose"\n // The `path` argument overrides the default URL prefix (which would be "foo").\n // The `package` argument overrides the default controller subfolder (which would be "foo").\n .namespace(name="foo", package="foos", path="foose")\n // Route name: fooBars\n // Example URL: /foose/bars\n // Controller: foos.Bars\n .post(name="bars", to="bars##create")\n .end()\n.end();\n\n</cfscript>\n
"},"hint":"Scopes any the controllers for any routes configured within this block to a subfolder (package) and also adds the package name to the URL.\n\n","returntype":"struct","slug":"mapper.namespace","parameters":[{"required":true,"hint":"Name to prepend to child route names.","name":"name","type":"string"},{"default":"[runtime expression]","required":false,"hint":"Subfolder (package) to reference for controllers. This defaults to the value provided for `name`.","name":"package","type":"string"},{"default":"[runtime expression]","required":false,"hint":"Subfolder path to add to the URL.","name":"path","type":"string"}],"availableIn":["mapper"],"name":"namespace","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. In `models/User.cfc`, allow `groupEntitlements` to be saved and deleted through the `user` object.\nfunction config() {\n\thasMany("groupEntitlements");\n\tnestedProperties(association="groupEntitlements", allowDelete=true);\n}\n\n// 2. Allow nested `addresses` to be saved but not auto-saved with the parent; also reject blank `street` values.\nfunction config() {\n\thasMany("addresses");\n\tnestedProperties(association="addresses", autoSave=false, rejectIfBlank="street");\n}\n\n// 3. Allow nested `lineItems` with a sort order driven by the `position` property, and enable deletion.\nfunction config() {\n\thasMany("lineItems");\n\tnestedProperties(association="lineItems", allowDelete=true, sortProperty="position");\n}\n\n// 4. Enable nested properties for multiple associations at once.\nfunction config() {\n\thasOne("profile");\n\thasMany("phoneNumbers");\n\tnestedProperties(associations="profile,phoneNumbers");\n}\n
"},"hint":"Allows for nested objects, structs, and arrays to be set from params and other generated data.\n\n","returntype":"void","slug":"model.nestedProperties","parameters":[{"default":"","required":false,"hint":"The association (or list of associations) you want to allow to be set through the params. This argument is also aliased as `associations`.","name":"association","type":"string"},{"default":true,"required":false,"hint":"Whether to save the association(s) when the parent object is saved.","name":"autoSave","type":"boolean"},{"default":false,"required":false,"hint":"Set this to `true` to tell Wheels to look for the property `_delete` in your model. If present and set to a value that evaluates to true, the model will be deleted when saving the parent.","name":"allowDelete","type":"boolean"},{"default":"","required":false,"hint":"Set this to a property on the object that you would like to sort by. The property should be numeric, should start with 1, and should be consecutive. Only valid with `hasMany` associations.","name":"sortProperty","type":"string"},{"default":"","required":false,"hint":"A list of properties that should not be blank. If any of the properties are blank, any CRUD operations will be rejected.","name":"rejectIfBlank","type":"string"}],"availableIn":["model"],"name":"nestedProperties","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelconfiguration","category":"Miscellaneous Functions","section":"Model Configuration"}},{"extended":{"hasExtended":true,"docs":"
// 1. Create a new author in memory (not saved to the database)\nnewAuthor = model("author").new();\n\n// 2. Create a new author by passing in a struct of properties\nnewAuthor = model("author").new(params.authorStruct);\n\n// 3. Create a new author by passing in named arguments\nnewAuthor = model("author").new(firstName="John", lastName="Doe");\n\n// 4. Create a new object without running callbacks\nnewAuthor = model("author").new(firstName="Jane", callbacks=false);\n\n// 5. Create a new object and allow explicit assignment of timestamp properties\nnewAuthor = model("author").new(firstName="Bob", createdAt="2024-01-01", allowExplicitTimestamps=true);\n\n// 6. Scoped call via a `hasMany` association (calls `model("order").new(customerId=aCustomer.id)` internally)\naCustomer = model("customer").findByKey(params.customerId);\nanOrder = aCustomer.newOrder(shipping=params.shipping);\n
"},"hint":"Creates a new object based on supplied properties and returns it.\nThe object is not saved to the database, it only exists in memory.\nProperty names and values can be passed in either using named arguments or as a struct to the properties argument.\n\n","returntype":"any","slug":"model.new","parameters":[{"default":"[runtime expression]","required":false,"hint":"The properties you want to set on the object (can also be passed in as named arguments).","name":"properties","type":"struct"},{"default":true,"required":false,"hint":"Set to `false` to disable callbacks for this method.","name":"callbacks","type":"boolean"},{"default":false,"required":false,"hint":"Set this to `true` to allow explicit assignment of `createdAt` or `updatedAt` properties","name":"allowExplicitTimestamps","type":"boolean"}],"availableIn":["model"],"name":"new","tags":{"categoryClass":"createfunctions","sectionClass":"modelclass","category":"Create Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: Basic usage — show a "Next" link below a paginated list;\n// renders a disabled span when already on the last page\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nposts = model("Post").findAll(page=params.page, perPage=10, order="createdAt DESC");\n\n// View code\n<cfoutput>\n #firstPageLink()#\n #previousPageLink()#\n #pageNumberLinks()#\n #nextPageLink()#\n #lastPageLink()#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom link text and CSS classes\n\n// View code\n<cfoutput>\n #nextPageLink(\n text="Next »",\n class="page-link",\n disabledClass="page-link disabled"\n )#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 3: Hide the disabled element entirely when on the last page\n\n// View code\n<cfoutput>\n #nextPageLink(showDisabled=false)#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 4: Use a named route so page numbers appear in the URL path\n// instead of as a query-string param (e.g. /articles/page/3)\n\n// Route setup in app/config/routes.cfm\nmapper()\n .get(name="paginatedArticles", pattern="articles/page/[page]", to="articles##index")\n .get(name="articles", pattern="articles", to="articles##index")\n.end();\n\n// Controller code\nparam name="params.page" type="integer" default="1";\narticles = model("Article").findAll(page=params.page, perPage=20, order="title");\n\n// View code\n<cfoutput>\n #nextPageLink(route="paginatedArticles", pageNumberAsParam=false)#\n</cfoutput>\n
"},"hint":"Creates a link to the next page, or a disabled span when on the last page.\n\n","returntype":"string","slug":"controller.nextPageLink","parameters":[{"default":"Next","required":false,"hint":"The text for the link.","name":"text","type":"string"},{"default":"query","required":false,"hint":"The handle given to the query that the pagination should be displayed for.","name":"handle","type":"string"},{"default":"page","required":false,"hint":"The name of the param that holds the current page number.","name":"name","type":"string"},{"default":"","required":false,"hint":"CSS class for the link element.","name":"class","type":"string"},{"default":"disabled","required":false,"hint":"CSS class for the disabled span element.","name":"disabledClass","type":"string"},{"default":true,"required":false,"hint":"Whether to render a disabled span when on the last page.","name":"showDisabled","type":"boolean"},{"default":true,"required":false,"hint":"Decides whether to link the page number as a param or as part of a route.","name":"pageNumberAsParam","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"nextPageLink","tags":{"categoryClass":"paginationfunctions","sectionClass":"viewhelpers","category":"Pagination Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic number field bound to a model object\n#numberField(objectName="product", property="price")#\n\n// 2. Number field with a label and min/max/step constraints\n#numberField(label="Quantity", objectName="orderItem", property="quantity", min="1", max="100", step="1")#\n\n// 3. Number field for a nested association (line items in an order)\n<cfloop from="1" to="#ArrayLen(order.lineItems)#" index="i">\n\t#numberField(label="Amount ##i#", objectName="order", association="lineItems", position=i, property="amount", min="0")#\n</cfloop>
"},"hint":"Builds and returns a string containing a number field form control based on the supplied objectName and property.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.numberField","parameters":[{"required":true,"hint":"The variable name of the object to build the form control for.","name":"objectName","type":"any"},{"required":true,"hint":"The name of the property to use in the form control.","name":"property","type":"string"},{"required":false,"hint":"The name of the association that the property is located on. Used for building nested forms that work with nested properties. If you are building a form with deep nesting, simply pass in a list to the nested object, and Wheels will figure it out.","name":"association","type":"string"},{"required":false,"hint":"The position used when referencing a hasMany relationship in the association argument. Used for building nested forms that work with nested properties. If you are building a form with deep nestings, simply pass in a list of positions, and Wheels will figure it out.","name":"position","type":"string"},{"required":false,"hint":"Minimum allowed value.","name":"min","type":"string"},{"required":false,"hint":"Maximum allowed value.","name":"max","type":"string"},{"required":false,"hint":"Stepping interval.","name":"step","type":"string"},{"default":"useDefaultLabel","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":"span","required":false,"hint":"HTML tag to wrap the form control with when the object contains errors.","name":"errorElement","type":"string"},{"default":"field-with-errors","required":false,"hint":"The class name of the HTML tag that wraps the form control when there are errors.","name":"errorClass","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"numberField","tags":{"categoryClass":"formobjectfunctions","sectionClass":"viewhelpers","category":"Form Object Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Basic number field with a name and current value\n#numberFieldTag(name="quantity", value=params.quantity)#\n\n// 2. Number field with min, max, and step constraints plus a label\n#numberFieldTag(name="rating", value=params.rating, label="Rating", min="1", max="5", step="1")#\n\n// 3. Number field with a CSS class and prepended label text\n#numberFieldTag(name="price", value=params.price, label="Price ($)", min="0", step="0.01", class="price-input")#\n
"},"hint":"Builds and returns a string containing a number field form control based on the supplied name.\nNote: Pass any additional arguments like class, rel, and id, and the generated tag will also include those values as HTML attributes.\n\n","returntype":"string","slug":"controller.numberFieldTag","parameters":[{"required":true,"hint":"Name to populate in tag's name attribute.","name":"name","type":"string"},{"default":"","required":false,"hint":"Value to populate in tag's value attribute.","name":"value","type":"string"},{"required":false,"hint":"Minimum allowed value.","name":"min","type":"string"},{"required":false,"hint":"Maximum allowed value.","name":"max","type":"string"},{"required":false,"hint":"Stepping interval.","name":"step","type":"string"},{"default":"","required":false,"hint":"The label text to use in the form control.","name":"label","type":"string"},{"default":"around","required":false,"hint":"Whether to place the label before, after, or wrapped around the form control. Label text placement can be controlled using aroundLeft or aroundRight.","name":"labelPlacement","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control. Useful to wrap the form control with HTML tags.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String to append to the form control. Useful to wrap the form control with HTML tags.","name":"append","type":"string"},{"default":"","required":false,"hint":"String to prepend to the form control's label. Useful to wrap the form control with HTML tags.","name":"prependToLabel","type":"string"},{"default":"","required":false,"hint":"String to append to the form control's label. Useful to wrap the form control with HTML tags.","name":"appendToLabel","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"numberFieldTag","tags":{"categoryClass":"formtagfunctions","sectionClass":"viewhelpers","category":"Form Tag Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Obfuscate a primary key value before including it in a URL\nobfuscatedId = obfuscateParam(99);\n// obfuscatedId -> "a3f6c1" (an obfuscated hex string)\n\n// 2. Use an obfuscated key in a generated URL to hide the real record ID\nparams.userKey = obfuscateParam(model("User").findOne().key());\nredirectTo(route="userProfile", key=params.userKey);\n\n// 3. Reverse the obfuscation with deobfuscateParam to get the original value back\nobfuscated = obfuscateParam(42);\noriginal = deobfuscateParam(obfuscated);\n// original -> "42"\n
"},"hint":"Obfuscates a value. Typically used for hiding primary key values when passed along in the URL.\n\n","returntype":"string","slug":"controller.obfuscateParam","parameters":[{"required":true,"hint":"The value to obfuscate.","name":"param","type":"any"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"obfuscateParam","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"globalhelpers","category":"Miscellaneous Functions","section":"Global Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Override a global `provides()` setting for a single action — only respond with HTML\nonlyProvides("html");\n\n// 2. Allow a specific action to respond with JSON and XML only\nonlyProvides("json,xml");\n\n// 3. Override the provides formats for a named action from within another context (e.g. config())\nonlyProvides(formats="json", action="create");\n
"},"hint":"Use this in an individual controller action to define which formats the action will respond with.\nThis can be used to define provides behavior in individual actions or to override a global setting set with provides in the controller's config().\nRestrictions are enforced (since 4.0.4): renderWith() falls back to the html view for a\nformat outside the list. When the action renders nothing itself, a request whose format\nparam (e.g. the route's `.\n","returntype":"void","slug":"controller.onlyProvides","parameters":[{"default":"","required":false,"hint":"Formats to instruct the controller to provide. Valid values are `html` (the default), `xml`, `json`, `csv`, `pdf`, and `xls`.","name":"formats","type":"string"},{"default":"[runtime expression]","required":false,"hint":"Name of action, defaults to current.","name":"action","type":"string"}],"availableIn":["controller"],"name":"onlyProvides","tags":{"categoryClass":"providesfunctions","sectionClass":"controller","category":"Provides Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
// Note: onMissingMethod() is not called directly. It is the CFML hook that\n// powers Wheels' dynamic model methods. The examples below show what you\n// call in your code — Wheels intercepts each one automatically.\n\n// 1. Dynamic finder: findOneBy<Property>\n// Finds the first user whose email matches the given value.\nuser = model("User").findOneByEmail("jane@example.com");\n\n// 2. Dynamic finder: findAllBy<Property>\n// Finds all posts with the given status.\nposts = model("Post").findAllByStatus("published");\n\n// 3. Dynamic finder across multiple properties joined by "And"\n// Finds a single order matching both customerId and status.\norder = model("Order").findOneByCustomerIdAndStatus(42, "pending");\n\n// 4. Find or create by property\n// Returns an existing tag with the name "cfml", or creates one if none exists.\ntag = model("Tag").findOrCreateByName("cfml");\n\n// 5. Association helpers generated for hasMany (comments on a post)\npost = model("Post").findByKey(1);\n// Retrieve all associated comments\ncomments = post.comments();\n// Count associated comments\ntotal = post.commentCount();\n// Create a new associated comment (foreign key set automatically)\npost.createComment(body="Great post!");\n\n// 6. Property change helpers\nuser = model("User").findByKey(1);\nuser.email = "new@example.com";\n// Check whether a specific property has changed since the record was loaded\nchanged = user.emailHasChanged();\n// Get the original value before the change\noriginal = user.emailChangedFrom();\n\n// 7. Enum boolean helpers (requires enum() declaration in model config)\n// component Post extends="Model" { function config() { enum(property="status", values="draft,published,archived"); } }\npost = model("Post").findByKey(1);\nwriteOutput(post.isPublished()); // true or false\nwriteOutput(post.isDraft()); // true or false\n
"},"hint":"This method is not designed to be called directly from your code, but provides functionality for dynamic finders such as findOneByEmail()\n\n","returntype":"any","slug":"model.onMissingMethod","parameters":[{"required":true,"name":"missingMethodName","type":"string"},{"required":true,"name":"missingMethodArguments","type":"struct"}],"availableIn":["model"],"name":"onMissingMethod","tags":{"categoryClass":"miscellaneousfunctions","sectionClass":"modelclass","category":"Miscellaneous Functions","section":"Model Class"}},{"extended":{"hasExtended":true,"docs":"
<cfscript>\n\n// 1. Scope controllers into a subfolder without adding the package name to the URL\nmapper()\n .package("admin")\n // Route name: adminProducts\n // Example URL: /products (no "admin" in the URL)\n // Controller: admin.Products\n .resources("products")\n\n // Example URL: /users (no "admin" in the URL)\n // Controller: admin.Users\n .resources("users")\n .end()\n.end();\n\n// 2. Use the `package` argument to override the subfolder name\nmapper()\n .package(name="v2", package="api/v2")\n // Route name: v2Articles\n // Example URL: /articles\n // Controller: api/v2.Articles\n .resources("articles")\n .end()\n.end();\n\n// 3. Nest a `package` inside a resource to scope sub-resource controllers\nmapper()\n .resources(name="users", nested=true)\n // Calling `package` here scopes nested routes to a subfolder without\n // changing the URL structure.\n .package("users")\n // Route name: usersProfile\n // Example URL: /users/4321/profile\n // Controller: users.Profiles\n .resource("profile")\n .end()\n .end()\n.end();\n\n</cfscript>\n
"},"hint":"Scopes any the controllers for any routes configured within this block to a subfolder (package) without adding the package name to the URL.\n\n","returntype":"struct","slug":"mapper.package","parameters":[{"required":true,"hint":"Name to prepend to child route names.","name":"name","type":"string"},{"default":"[runtime expression]","required":false,"hint":"Subfolder (package) to reference for controllers. This defaults to the value provided for `name`.","name":"package","type":"string"}],"availableIn":["mapper"],"name":"package","tags":{"categoryClass":"routing","sectionClass":"configuration","category":"Routing","section":"Configuration"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: Basic page number links for a paginated query\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nposts = model("Post").findAll(page=params.page, perPage=10, order="createdAt DESC");\n\n// View code — renders links like: 1 2 [3] 4 5 (current page as a span)\n<cfoutput>#pageNumberLinks()#</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 2: Widen the window around the current page and add CSS classes\n\n// View code — shows 5 pages on each side of the current page,\n// styling each link and the current-page span differently\n<cfoutput>\n #pageNumberLinks(windowSize=5, class="page-link", classForCurrent="active")#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 3: Wrap each page number in a list item\n\n// View code\n<ul>\n <cfoutput>\n #pageNumberLinks(prependToPage="<li>", appendToPage="</li>")#\n </cfoutput>\n</ul>\n\n\n//--------------------------------------------------------------------\n// Example 4: Make the current page a link (useful for reloading)\n\n// View code\n<cfoutput>#pageNumberLinks(linkToCurrentPage=true)#</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 5: Multiple paginated queries — reference each by its handle\n\n// Controller code\nauthors = model("Author").findAll(handle="authorQuery", page=params.page, perPage=20, order="lastName");\nposts = model("Post").findAll(handle="postQuery", page=params.page, perPage=5, order="createdAt");\n\n// View code\n<cfoutput>\n Authors: #pageNumberLinks(handle="authorQuery")#\n Posts: #pageNumberLinks(handle="postQuery")#\n</cfoutput>\n
"},"hint":"Creates a windowed set of page number links around the current page.\nThe current page is rendered as a span (not a link) unless linkToCurrentPage is true.\n\n\nWhen non-plain, emits the canonical wrapper markup for that framework (e.g. )\nand ignores prependToPage / appendToPage / classForCurrent / class in favor of the preset.","returntype":"string","slug":"controller.pageNumberLinks","parameters":[{"default":2,"required":false,"hint":"The number of page links to show around the current page.","name":"windowSize","type":"numeric"},{"default":"query","required":false,"hint":"The handle given to the query that the pagination should be displayed for.","name":"handle","type":"string"},{"default":"page","required":false,"hint":"The name of the param that holds the current page number.","name":"name","type":"string"},{"default":"","required":false,"hint":"CSS class for each page number link.","name":"class","type":"string"},{"default":"current","required":false,"hint":"CSS class for the current page span or link.","name":"classForCurrent","type":"string"},{"default":false,"required":false,"hint":"Whether to render the current page as a link.","name":"linkToCurrentPage","type":"boolean"},{"default":"","required":false,"hint":"String to prepend before each page number.","name":"prependToPage","type":"string"},{"default":"","required":false,"hint":"String to append after each page number.","name":"appendToPage","type":"string"},{"default":false,"required":false,"hint":"Whether to inject `active ` into the prependToPage `class` attribute on the current page (Bootstrap idiom). Has no effect if `prependToPage` contains no `class` attribute.","name":"addActiveClassToPrependedParent","type":"boolean"},{"default":true,"required":false,"hint":"Decides whether to link the page number as a param or as part of a route.","name":"pageNumberAsParam","type":"boolean"},{"default":"plain","required":false,"hint":"CSS-framework preset for markup: \"plain\" (default), \"bootstrap5\", \"bootstrap4\", or \"tailwind\".","name":"viewStyle","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"pageNumberLinks","tags":{"categoryClass":"paginationfunctions","sectionClass":"viewhelpers","category":"Pagination Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
// 1. Get pagination info for the default query handle\nauthors = model("Author").findAll(page=1, perPage=25, order="lastName");\ninfo = pagination();\n// info.currentPage -> 1\n// info.totalPages -> 4\n// info.totalRecords -> 98\n\n// 2. Get pagination info using a named handle (when running multiple paginated queries)\narticles = model("Article").findAll(page=2, perPage=10, order="publishedAt DESC", handle="articles");\narticleInfo = pagination("articles");\nwriteOutput("Page " & articleInfo.currentPage & " of " & articleInfo.totalPages);\n\n// 3. Use pagination info to build a simple summary string\nproducts = model("Product").findAll(page=params.page, perPage=20, order="name", handle="products");\ninfo = pagination("products");\nwriteOutput("Showing page " & info.currentPage & " of " & info.totalPages & " (" & info.totalRecords & " total products)");\n
"},"hint":"Returns a struct with information about the specified paginated query.\nThe keys that will be included in the struct are currentPage, totalPages and totalRecords.\n\n","returntype":"struct","slug":"controller.pagination","parameters":[{"default":"query","required":false,"hint":"The handle given to the query to return pagination information for.","name":"handle","type":"string"}],"availableIn":["controller","model","mapper","migrator","migration","tabledefinition"],"name":"pagination","tags":{"categoryClass":"paginationfunctions","sectionClass":"controller","category":"Pagination Functions","section":"Controller"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: Basic usage — display the default summary text for a\n// paginated query (e.g. "Showing 26-50 of 1,000 records")\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nposts = model("Post").findAll(page=params.page, perPage=25, order="createdAt DESC");\n\n// View code\n<cfoutput>\n #paginationInfo()#\n</cfoutput>\n// -> "Showing 26-50 of 1,000 records"\n\n\n//--------------------------------------------------------------------\n// Example 2: Custom format string using available tokens\n// Tokens: [startRow], [endRow], [totalRecords], [currentPage], [totalPages]\n\n// View code\n<cfoutput>\n #paginationInfo(format="Page [currentPage] of [totalPages] ([totalRecords] total)")#\n</cfoutput>\n// -> "Page 2 of 40 (1,000 total)"\n\n\n//--------------------------------------------------------------------\n// Example 3: Multiple paginated queries on the same page using handles\n\n// Controller code\nparam name="params.postPage" type="integer" default="1";\nparam name="params.commentPage" type="integer" default="1";\nposts = model("Post").findAll(handle="posts", page=params.postPage, perPage=10, order="createdAt DESC");\ncomments = model("Comment").findAll(handle="comments", page=params.commentPage, perPage=5, order="createdAt DESC");\n\n// View code\n<cfoutput>\n Posts: #paginationInfo(handle="posts")#\n Comments: #paginationInfo(handle="comments")#\n</cfoutput>\n// -> "Posts: Showing 1-10 of 87 records"\n// -> "Comments: Showing 1-5 of 342 records"\n
"},"hint":"Displays a text summary of the current pagination state, e.g. \"Showing 26-50 of 1,000 records\".\nUses token replacement in the format string: \n","returntype":"string","slug":"controller.paginationInfo","parameters":[{"default":"query","required":false,"hint":"The handle given to the query that the pagination info should be displayed for.","name":"handle","type":"string"},{"default":"Showing [startRow]-[endRow] of [totalRecords] records","required":false,"hint":"Format string with tokens: [startRow], [endRow], [totalRecords], [currentPage], [totalPages].","name":"format","type":"string"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"paginationInfo","tags":{"categoryClass":"paginationfunctions","sectionClass":"viewhelpers","category":"Pagination Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: List authors page by page, 25 at a time\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nauthors = model("author").findAll(page=params.page, perPage=25, order="lastName");\n\n// View code\n<ul>\n <cfoutput query="authors">\n <li>#EncodeForHtml(firstName)# #EncodeForHtml(lastName)#</li>\n </cfoutput>\n</ul>\n\n<cfoutput>#paginationLinks(route="authors")#</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 2: Using the same model call above, show all authors with a\n// window size of 5\n\n// View code\n<cfoutput>#paginationLinks(route="authors", windowSize=5)#</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 3: If more than one paginated query is being run, then you\n// need to reference the correct `handle` in the view\n\n// Controller code\nauthors = model("author").findAll(handle="authQuery", page=5, order="id");\n\n// View code\n<ul>\n <cfoutput>\n #paginationLinks(\n route="authors",\n handle="authQuery",\n prependToPage="<li>",\n appendToPage="</li>"\n )#\n </cfoutput>\n</ul>\n\n\n//--------------------------------------------------------------------\n// Example 4: Call to `paginationLinks` using routes\n\n// Route setup in app/config/routes.cfm\nmapper()\n .get(name="paginatedCommentListing", pattern="blog/[year]/[month]/[day]/[page]", to="blogs##stats")\n .get(name="commentListing", pattern="blog/[year]/[month]/[day]", to="blogs##stats")\n.end();\n\n// Controller code\nparam name="params.page" type="integer" default="1";\ncomments = model("comment").findAll(page=params.page, order="createdAt");\n\n// View code\n<ul>\n <cfoutput>\n #paginationLinks(\n route="paginatedCommentListing",\n year=2009,\n month="feb",\n day=10\n )#\n </cfoutput>\n</ul>\n\n\n//--------------------------------------------------------------------\n// Example 5: Highlight the current page with a CSS class and wrap\n// each page number in a Bootstrap-style list item, marking the active\n// item's parent with an "active" class\n\n// View code\n<ul class="pagination">\n <cfoutput>\n #paginationLinks(\n route="articles",\n prependToPage='<li class="page-item">',\n appendToPage="</li>",\n classForCurrent="page-link active",\n addActiveClassToPrependedParent=true,\n linkToCurrentPage=true\n )#\n </cfoutput>\n</ul>\n
"},"hint":"Builds and returns a string containing links to pages based on a paginated query.\nUses linkTo() internally to build the link, so you need to pass in a route name or a controller/action/key combination.\nAll other linkTo() arguments can be supplied as well, in which case they are passed through directly to linkTo().\nIf you have paginated more than one query in the controller, you can use the handle argument to reference them. (Don't forget to pass in a handle to the findAll() function in your controller first.)\n\n","returntype":"string","slug":"controller.paginationLinks","parameters":[{"default":2,"required":false,"hint":"The number of page links to show around the current page.","name":"windowSize","type":"numeric"},{"default":true,"required":false,"hint":"Whether or not links to the first and last page should always be displayed.","name":"alwaysShowAnchors","type":"boolean"},{"default":" ... ","required":false,"hint":"String to place next to the anchors on either side of the list.","name":"anchorDivider","type":"string"},{"default":false,"required":false,"hint":"Whether or not the current page should be linked to.","name":"linkToCurrentPage","type":"boolean"},{"default":"","required":false,"hint":"String or HTML to be prepended before result.","name":"prepend","type":"string"},{"default":"","required":false,"hint":"String or HTML to be appended after result.","name":"append","type":"string"},{"default":"","required":false,"hint":"String or HTML to be prepended before each page number.","name":"prependToPage","type":"string"},{"default":false,"required":false,"hint":"Whether or not to add an active class to the parent element of the current page link (requires prependToPage to contain a class attribute).","name":"addActiveClassToPrependedParent","type":"boolean"},{"default":true,"required":false,"hint":"Whether or not to prepend the prependToPage string on the first page in the list.","name":"prependOnFirst","type":"boolean"},{"default":true,"required":false,"hint":"Whether or not to prepend the prependToPage string on the anchors.","name":"prependOnAnchor","type":"boolean"},{"default":"","required":false,"hint":"String or HTML to be appended after each page number.","name":"appendToPage","type":"string"},{"default":true,"required":false,"hint":"Whether or not to append the appendToPage string on the last page in the list.","name":"appendOnLast","type":"boolean"},{"default":true,"required":false,"hint":"Whether or not to append the appendToPage string on the anchors.","name":"appendOnAnchor","type":"boolean"},{"default":"","required":false,"hint":"Class name for the current page number (if linkToCurrentPage is true, the class name will go on the a element. If not, a span element will be used).","name":"classForCurrent","type":"string"},{"default":"query","required":false,"hint":"The handle given to the query that the pagination links should be displayed for.","name":"handle","type":"string"},{"default":"page","required":false,"hint":"The name of the param that holds the current page number.","name":"name","type":"string"},{"default":false,"required":false,"hint":"Will show a single page when set to true. (The default behavior is to return an empty string when there is only one page in the pagination).","name":"showSinglePage","type":"boolean"},{"default":true,"required":false,"hint":"Decides whether to link the page number as a param or as part of a route. (The default behavior is true).","name":"pageNumberAsParam","type":"boolean"},{"default":true,"required":false,"hint":"Use this argument to decide whether the output of the function should be encoded in order to prevent Cross Site Scripting (XSS) attacks. Set it to `true` to encode all relevant output for the specific HTML element in question (e.g. tag content, attribute values, and URLs). For HTML elements that have both tag content and attribute values you can set this argument to `attributes` to only encode attribute values and not tag content.","name":"encode","type":"any"}],"availableIn":["controller"],"name":"paginationLinks","tags":{"categoryClass":"linkfunctions","sectionClass":"viewhelpers","category":"Link Functions","section":"View Helpers"}},{"extended":{"hasExtended":true,"docs":"
//--------------------------------------------------------------------\n// Example 1: Basic usage — render a full pagination nav for a\n// paginated query (first, previous, page numbers, next, last links)\n\n// Controller code\nparam name="params.page" type="integer" default="1";\nposts = model("Post").findAll(page=params.page, perPage=25, order="createdAt DESC");\n\n// View code\n<cfoutput>\n #paginationNav()#\n</cfoutput>\n// -> <nav class="pagination"><a href="/posts?page=1">1</a> <a href="/posts?page=2">2</a> ...</nav>\n\n\n//--------------------------------------------------------------------\n// Example 2: Show pagination info text alongside the nav links,\n// and use a custom CSS class on the wrapping nav element\n\n// View code\n<cfoutput>\n #paginationNav(showInfo=true, navClass="pagination-bar")#\n</cfoutput>\n// -> <nav class="pagination-bar">Showing 1-25 of 87 records <a href="...">1</a> ...</nav>\n\n\n//--------------------------------------------------------------------\n// Example 3: Minimal nav — page numbers only (no first/last links)\n\n// View code\n<cfoutput>\n #paginationNav(showFirst=false, showLast=false)#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 4: Multiple paginated queries on the same page using handles\n\n// Controller code\nparam name="params.postPage" type="integer" default="1";\nparam name="params.commentPage" type="integer" default="1";\nposts = model("Post").findAll(handle="posts", page=params.postPage, perPage=10, order="createdAt DESC");\ncomments = model("Comment").findAll(handle="comments", page=params.commentPage, perPage=5, order="createdAt DESC");\n\n// View code\n<cfoutput>\n #paginationNav(handle="posts")#\n #paginationNav(handle="comments")#\n</cfoutput>\n\n\n//--------------------------------------------------------------------\n// Example 5: Show pagination even when there is only one page of results\n\n// View code\n<cfoutput>\n #paginationNav(showSinglePage=true)#\n</cfoutput>\n
"},"hint":"Creates a complete pagination navigation element wrapping individual pagination helpers.\nOutputs a element containing first/previous/page-numbers/next/last links and optional info text.\nThe showFirst / showLast / showPrevious / showNext args accept the\nstrings \"auto\", \"always\", or \"never\". Booleans are normalized for\nbackwards compatibility: true maps to \"always\", false maps to \"never\".\nUnder \"auto\" the first/last anchors only render when the visible page-number\nwindow does not already reach the boundary (matching legacy 3.x semantics).\nUnder \"auto\" the previous/next anchors always delegate to their sub-helper,\nwhich renders a disabled at the boundary by default —\nuse \"never\" to suppress the boundary indicator entirely.\n\n\nWhen non-plain, the entire nav is rendered with the framework's canonical structure\n(e.g. ), removing the need\nfor Replace() post-processing in app code. Passed through to pageNumberLinks().","returntype":"string","slug":"controller.paginationNav","parameters":[{"default":"query","required":false,"hint":"The handle given to the query that the pagination should be displayed for.","name":"handle","type":"string"},{"default":"pagination","required":false,"hint":"CSS class for the wrapping nav element.","name":"navClass","type":"string"},{"default":"auto","required":false,"hint":"Anchor display mode for the first page link: \"auto\" (default), \"always\", \"never\", or boolean.","name":"showFirst","type":"any"},{"default":"auto","required":false,"hint":"Anchor display mode for the last page link: \"auto\" (default), \"always\", \"never\", or boolean.","name":"showLast","type":"any"},{"default":"auto","required":false,"hint":"Anchor display mode for the previous page link: \"auto\" (default), \"always\", \"never\", or boolean.","name":"showPrevious","type":"any"},{"default":"auto","required":false,"hint":"Anchor display mode for the next page link: \"auto\" (default), \"always\", \"never\", or boolean.","name":"showNext","type":"any"},{"default":false,"required":false,"hint":"Whether to show the pagination info text.","name":"showInfo","type":"boolean"},{"default":false,"required":false,"hint":"Whether to show pagination when there is only one page.","name":"showSinglePage","type":"boolean"},{"default":2,"required":false,"hint":"Number of page links shown around the current page in `pageNumberLinks` and used by the auto-mode predicates.","name":"windowSize","type":"numeric"},{"default":"plain","required":false,"hint":"CSS-framework preset for markup: \"plain\" (default), \"bootstrap5\", \"bootstrap4\", or \"tailwind\".","name":"viewStyle","type":"string"},{"default":"","required":false,"hint":"String or HTML to be prepended inside the `