Mura ORM Entity
In a nutshell, a Mura ORM entity is described by creating a ColdFusion component (.CFC). Mura leverages some of the standard attributes of a Mura ORM component, and also utilizes some custom attributes, as outlined in the table below.
Attribute | Req/Opt | Default | Description |
---|---|---|---|
bundleable | Optional | true | If false , entities will not be included in any bundles. |
cachename | Optional | You may optionally supply a custom cache name to use when being stored in Mura's cache factory. | |
datasource | Optional | m.globalConfig('datasource') | If you wish to use a datasource that's different from the one Mura uses by default, you may supply one here. |
dbtype | Optional | If specifying a
|
|
discriminatorcolumn | Optional | empty string | You may specify a property to filter on by default. |
discriminatorvalue | Optional | empty string | If using a discriminatorcolumn , you may specify the property's criteria to filter on by default. |
extends | Required | mura.bean.beanORM | This attribute should always be present, and should always extend mura.bean.beanORM or mura.bean.beanORMHistorical |
entityname | Required | This is the name of the object/entity. | |
manageschema | Optional | true | If false , Mura will not manage the underlying table for the entity, and you are assuming all responsibility for any schema changes. |
orderby | Optional | You may pass a comma-delimited list of properties to sort by. | |
public | Optional | false | If true , allows the entity to be used via the JSON API by non-administrative users. If false , users must be logged in, and have access to the specific site in order to work with the entity. |
readonly | Optional | false | If true , Mura will not allow any new records to be added to the database, or any updates to existing records in the database. |
table | Required | Specify the name to use for a database table to store data about this entity. | |
usetrash | Optional | true | If false , entities will not be moved to the Trash Bin, and will be hard deleted instead. |
Example Mura ORM Component
- component
- extends="mura.bean.beanORM"
- entityname="something"
- table="somethings"
- bundleable="true"
- displayname="SomethingBean"
- public=true
- orderby="{someproperty}" {
- // Properties & Methods
- }
Mura ORM Component Properties
To describe the various properties/attributes and relationships of Mura ORM entities, use CFML properties. The following table describes the available attributes for Mura ORM component properties.
Attribute | Req/Opt | Default | Description |
---|---|---|---|
cascade | Optional | If the property is a related entity and the value is "delete ", when the parent entity/object is deleted, any related entities will also be deleted. |
|
cfc | Optional | If the property is a related entity, set to the related entity's "entityname " value. |
|
comparable | Optional | true | If false , the property will not be included in entity comparisons. For example:entityDifferences = entityA.compare(entityB); |
datatype | Optional | varchar | Valid options are:
|
default | Optional | If the required attribute is set to "no", or not specified, you may supply a default value to use. |
|
fieldtype | Optional | If property is a primary key, you should set If property is a related entity, you may specify the relationship type here. The left side of the "to" types listed below is the parent entity, and the right side of the "to" is the related entity. So, for example "one-to-many" would mean one parent entity could have many related entities, and so on. Valid options are:
|
|
fkcolumn | Optional | If the property is a related entity, you may specify the attribute of the entity to store in this field. This is useful when creating relationships to Mura's entities. For example: property name="site" cfc="site" fieldtype="many-to-one" fkcolumn="siteid"; |
|
length | Optional | 50 | If the datatype attribute is set to "varchar" or "char", you may specify the maximum number of characters to allow. |
loadkey | Optional | If the property is a related entity, you may specify the attribute of the entity to load by. | |
message | Optional | If required, or fails validation, the error message to return to the user. | |
relatesto | Optional | Alias for "cfc " |
|
name | Required | Name of the property. | |
nullable | Optional | false | If true , empty values will be stored as NULL . |
orderby | Optional | If property is a related entity, you may specify the related entity's property you wish to sort by. | |
persistent | Optional | true | If false , a column in the related table will not be created for the property. |
required | Optional | false | If true , an error will be sent to the user if a value is not set. |
singluarname | Optional | If the property is a related entity, this allows you to use a singular name in lieu of the property name itself. For example: property name="addresses" singularname="address" cfc="address" fieldtype="one-to-many"; |
|
validate | Optional | If you desire the entity to be validated before saving, you may use one of the following options:
|
Validation Attributes
If property has a "validate
" attribute, you may include additional attributes to the property for validation.
Attribute | Description |
---|---|
regex | The regular expression to use for validation. |
minvalue | The minimum value to allow. |
maxvalue | The maximum value to allow. |
minlength | The minimum length to allow. |
maxlenth | The maximum length to allow. |
inlist | The list to compare against. |
method | A custom entity method to execute. |
lte | Less than or equal to. |
lt | Less than. |
gte | Greater than or equal to. |
gt | Greater than. |
eq | Equal to. |
neq | Not equal to. |
The example below illustrates how to use a validation attribute, when a property has a "validate
" attribute.
- property name="year" datatype="int" validate="numeric" minvalue="1900" maxvalue="2017";
Related Entity Synthesized Methods
If the property is a related entity, and the fieldtype
attribute is either "one-to-many" or "many-to-many", the following methods are automatically available to the entity itself. The methods below are executed for both the property's name
and singularname
.
Method | Description |
---|---|
get{PropertyName}Iterator | Returns an iterator of related entities. For example: entity.getAddressesIterator() |
get{PropertyName} | Under the hood, returns get{PropertyName}Iterator . |
get{PropertyName}Query | Returns a recordset/query of the related entities. For example: entity.getAddressesQuery() |
has{PropertyName} | Returns a recordcount of related entities. Useful for if/else statements. |
add{PropertyName} | Pass in the object/entity to save as a related entity, and Mura will automatically save the related entity when executing the call to entity.save() . Useful for adding multiple related entities. For example: entity.addPhoneNumber(phoneNumberObject) |
remove{PropertyName} | Pass in the object/entity to be deleted, and Mura will automatically delete the related entity when executing the call to entity.save() . For example: entity.removePhoneNumber(phoneNumberObject) |
If the property is a related entity, and the fieldtype
attribute is either "one-to-one" or "many-to-one", the following methods are automatically available to the entity itself.
Method | Description |
---|---|
get{PropertyName} | Returns the related entity. For example: entity.getEmergencyContact() |
add{PropertyName} | Pass in the object/entity to save as a related entity, and Mura will automatically save the related entity when executing the call to entity.save() . For example: entity.addEmergencyContact(emergencyContactObject) |
remove{PropertyName} | Pass in the object/entity to be deleted, and Mura will automatically delete the related entity when executing the call to entity.save() . For example: entity.removeEmergencyContact(emergencyContactObject) |
Example Mura ORM Component With Properties
The following code defines an entity named "something" that contains a few basic properties.
- component
- extends="mura.bean.beanORM"
- entityname="something"
- table="somethings"
- bundleable="true"
- displayname="SomethingBean"
- public=true
- orderby="namefirst,namelast" {
- // primary key
- property name="somethingid" fieldtype="id";
- // attributes
- property name="namefirst" datatype="varchar" length="255" required=true;
- property name="namelast" datatype="varchar" length="255" required=true;
- // methods could go here
- }
Working With Entities
The code examples below demonstrate various methods for working with entities. As you'll see, the syntax is no different than working with any other Mura bean object.
- // Loading entities
- entity = m.getBean('entityName')
- .loadBy(someAttribute='Something');
- // Getting attributes
- entity.get('attributeName');
- // Setting attributes
- entity.set('attributeName', 'Some Value')
- // Deleting entities
- entity.delete();
- // Saving entities
- entity.save();
- // Get a feed of entites
- m.getFeed('entityName');
Error Handling
As previously mentioned, working with entities is no different than working with any other Mura bean object. We've already covered a bit of error handling, but it doesn't hurt to review it once again here.
Errors are returned as a structure, where each key in the struct represents the object's attribute "name", and the value contains the error message itself.
- entity.save();
- // If the bean has errors, then it did not save...
- if ( entity.hasErrors() ) {
- // errors are returned as a struct
- errors = entity.getErrors();
- WriteOutput('<h3>Please review the following errors:</h3><ul>');
- // Loop over the errors
- for ( e in errors ) {
- WriteOutput('<li>Attribute: #e# <br> Message: #errors[e]#</li>');
- }
- WriteOutput('</ul>');
- } else {
- WriteOutput('<h2>Success :: No Errors!</h2>');
- }
Custom Validation
Mura also allows you to include your own custom validation rules. In order to do so, you simply include a custom validate()
method in your entity's component file (.CFC), and when a save()
call is made on your entity, it will trigger your custom method. The key is you don't "return" anything, you simply add your custom errors to the existing errors struct.
You could also use this to do complex validation requirements. For example, maybe you have a custom radio button or checkbox, and when it's selected, your form displays additional form fields that you will then want to be "required". You could simply check for the existence and/or value of the triggering field, and if it exists, run through each of the additional required form fields in your own validation.
The example below demonstrates how to create your own error messages when validating an attribute of your entity.
- public any function validate() {
- // This runs the standard validation ...
- // which will use your property definition's "validate" requirements, etc.
- // and it also gives you a way to reference the entity object itself
- var obj = super.validate();
- // Obtain a reference to any errors
- var errors = obj.getErrors();
- // Now, you can check anything you want on your properties or entity attributes
- // For example, if you have a property labeled "wantsmoreoptions" and it's true,
- // You could check for the other fields
- if ( obj.get('wantsmoreoptions') ) {
- // Yes, they want more options!
- // Make sure they completed them ...
- if ( !Len(obj.get('option99')) ) {
- errors.option99 = 'Option 99 is required.';
- }
- // etc. ...
- }
- }