© 2015 X2Engine Inc.

Difference between revisions of "X2Model and Dynamic Fields"

From X2Engine
Jump to: navigation, search
(Introduction)
(Introduction)
 
(18 intermediate revisions by 2 users not shown)
Line 3: Line 3:
 
= Introduction =
 
= Introduction =
  
Typically in Yii, when a model (see: [[yii:CActiveRecord|CActiveRecord]]) is used to retrieve data from a table in the database, the model's attributes are simply inherited from the schema for that table. However, in order to provide the means to add and remove fields from models (and thus from database tables), in addition to providing more advanced options for setting behaviors of attributes, most of the model classes in X2EngineCRM (the ones that are associated with database tables) are extended from a class [[x2doc:X2Model|X2Model]]. The attributes of all such models are not derived from the database itself but from an attribute registry stored in the <tt>x2_fields</tt> table. The following columns in the fields table are of particular importance:
+
Typically in Yii, when a model (see: [[yii:CActiveRecord|CActiveRecord]]) is used to retrieve data from a table in the database, the model's attributes are simply inherited from the schema for that table. However, in order to provide the means to add and remove fields from models (and thus from database tables), in addition to providing more advanced options for setting behaviors of attributes, most of the model classes in X2Engine (the ones that are associated with database tables) are extended from a class [[x2doc:X2Model|X2Model]]. The attributes of all such models are not derived from the database itself but from an attribute registry stored in the <tt>x2_fields</tt> table. The following columns in the fields table are of particular importance:
  
;modelName
+
 
: The exact name of the model class to which the field belongs, with only one exception (fields with modelName="Quotes" belong to class [[x2doc:Quote|Quote]])
+
{|class="wikitable" align="left"
;fieldName
+
|-
: The name of the database column
+
! scope="col" | Field Name
;attributeLabel
+
! scope="col" | Typically renders as
: The attribute label (the name of the field as displayed in the UI)
+
! scope="col" | Value
;modified
+
|-
: Whether the field has been modified by the user.
+
! scope="row" | modelName
;custom
+
| Plain text (filtered/mapped to be human-readable)
: Whether the field has been created by the user.
+
| The exact name of the model class to which the field belongs, with a few if any exceptions (i.e. fields with modelName="Quotes" belong to class [[x2doc:Quote|Quote]])
;type
+
|-
: The type of the column. This does not merely specify the canonical MySQL type, but is used for specifying advanced behaviors for the field.
+
! scope="row" | fieldName
;required
+
| N/A (attribute label rendered in its place)
: Specifies that the model attribute cannot be null or empty, if set to 1.
+
| The name of the database column
;readOnly
+
|-
: Signifies that the model attribute cannot be modified through user input, if set to 1.
+
! scope="row" | attributeLabel
;linkType
+
| Plain text
: In the case that the field is being used as a link, keywords set in this field signify what type of link should be generated in output.
+
| The attribute label (the name of the field as displayed in the UI)
:searchable
+
|-
; If set to 1, the field's contents are included in global searches through records.
+
! scope="row" | modified
:relevance
+
| N/A
; An integer value used for sorting search results.
+
| Whether the field has been modified by the user.
:isVirtual
+
|-
; If set to 1, the field does not actually correspond to a database column; rather, it is an ephemeral attribute of the model that is used for passing data from the view to the controller and vice-versa. For instance, it would be used in the case of input that needs to be collected as part of the model (initially) so that it can be put through input validation.
+
! scope="row" | custom
 +
| N/A
 +
| Whether the field has been created by the user.
 +
|-
 +
! scope="row" | type
 +
| Plain text (filtered/mapped to be human-readable)
 +
| The type of the column. This does not merely specify the canonical MySQL type, but is used for specifying advanced behaviors for the field. See [[#Field Types|Field Types]] for more information.
 +
|-
 +
! scope="row" | required
 +
| Checkbox
 +
| Specifies that the model attribute cannot be null or empty, if set to 1.
 +
|-
 +
! scope="row" | readOnly
 +
| Checkbox
 +
| Signifies that the model attribute cannot be modified through user input, if set to 1.
 +
|-
 +
! scope="row" | linkType
 +
| N/A
 +
| In the case that the field is being used as a link, keywords set in this field signify what type of link should be generated in output.
 +
|-
 +
! scope="row" | searchable
 +
| Checkbox
 +
| If set to 1, the field's contents are included in global searches through records.
 +
|-
 +
! scope="row" | relevance
 +
| Verbatim what it is in the database
 +
| A value used for sorting search results: "Low", "Medium" or "High"
 +
|-
 +
! scope="row" | isVirtual
 +
| N/A
 +
| If set to 1, the field does not actually correspond to a database column; rather, it is an ephemeral attribute of the model that is used for passing data from the view to the controller and vice-versa. For instance, it would be used in the case of input that needs to be collected as part of the model (initially) so that it can be put through input validation.
 +
|-
 +
|}
  
 
= Field Types =
 
= Field Types =
The types of fields, as mentioned before, are not canonical MySQL data types, but rather keywords for specifying how they are to be treated and rendered, and that includes the allowable types that the field may be. When rendering an attribute, X2Model and its subclasses use [http://doc.x2engine.com/class-X2Model.html#_renderAttribute renderAttribute], wherein a <tt>case</tt> statement is used to distinguish between field types and choose a method of displaying the field.
+
The type of a field as set in <tt>x2_fields.type</tt>, as mentioned before, is not necessarily a canonical MySQL data type, but rather could be a keyword for specifying how the attribute is to be treated and rendered. For example, when rendering an attribute, X2Model and its subclasses use [[x2propdoc:X2Model.html#_renderAttribute|X2Model::renderAttribute()]], wherein a <tt>case</tt> statement is used to distinguish between field types and choose a method of displaying the field.
  
 
{|class="wikitable"
 
{|class="wikitable"
Line 41: Line 73:
 
|assignment
 
|assignment
 
|VARCHAR
 
|VARCHAR
|The attribute is rendered as a link using [//doc.x2engine.com/class-User.html#_getUserLinks User::getUserLinks]. The input field for it is a dropdown list of users and groups.
+
|The attribute is rendered as a link using [[x2propdoc:User.html#_getUserLinks|User::getUserLinks]]. The input field for it is a dropdown list of users and groups.
 
|-
 
|-
 
|boolean  
 
|boolean  
Line 81: Line 113:
 
|text
 
|text
 
|TEXT,VARCHAR
 
|TEXT,VARCHAR
|Distinct from VARCHAR in that links within the field's data are automatically transformed using [http://doc.x2engine.com/class-x2base.html#_convertUrls x2base::convertUrls].
+
|Distinct from VARCHAR in that links within the field's data are automatically transformed using [[x2propdoc:x2base.html#_convertUrls|x2base::convertUrls()]].
 
|-
 
|-
 
|url
 
|url
Line 94: Line 126:
 
|INT
 
|INT
 
|If 1, the record's contents are public. If 0, it is private. If 2, the record is visible only to the user's groups.
 
|If 1, the record's contents are public. If 0, it is private. If 2, the record is visible only to the user's groups.
 +
|-
 +
|percentage
 +
|FLOAT
 +
|Arbitrary numeric value rendered with a percent symbol after it.
 +
|-
 +
|credentials
 +
|INT
 +
|A record in x2_credentials to use for authenticating with some third-party service. The <tt>linkType</tt> column represents the service type, and if it contains a colon, then it is the service type (first) and (after the colon) the "system role" alias/nickname for that field (i.e. to identify the field as storing the ID of the SMTP email account for sending notification email).
 +
|-
 
|}
 
|}
  
= Linking back to a record in child classes =
+
= Setting automatic record links in child classes =
Relevant documentation: [[yiiguide:basics.component#component-behavior|Component Behavior]]
+
Relevant documentation: [[yiiguide:basics.component#component-behavior|Component Behavior]], [[yii:CModel#behaviors-detail|CModel::behaviors()]]
  
In cases where <tt>link</tt> and <tt>linkType</tt> are used, [[x2doc:X2LinkableBehavior|X2LinkableBehavior]] comes into play; X2Model inherits the behaviors and attributes from that class, since it is attached as a behavior. The method <tt>getLink</tt> is used for generating controller routes. In this method, it is assumed that the model has the same name as the controller/module. Thus, for every module/controller, the models used by them have the same names, with few exceptions. In the case of any new model that is a child class of X2Model, for which the class does not follow these naming conventions, the following steps will be necessary:
+
In cases where <tt>link</tt> and <tt>linkType</tt> are used, [[x2doc:X2LinkableBehavior|X2LinkableBehavior]] comes into play; X2Model inherits the behaviors and attributes from that class, since it is attached as a behavior. The method <tt>getLink</tt> is used for generating controller routes. In this method, it is assumed that the model has the same name as the controller/module. Thus, for every module/controller, the models used by them have the same names, with few exceptions. Thus, this should typically be taken care of already. However, in the case of any new model that is a child class of X2Model, for which the class '''does not or cannot''' follow these naming conventions (i.e. a second model inside of a module that needs to use the fields table), the following steps will be necessary:
  
 
* Override the <tt>behaviors()</tt> method so that the subclass does not have <tt>X2LinkableBehavior</tt>; have it return an empty array or an array with other desired behaviors
 
* Override the <tt>behaviors()</tt> method so that the subclass does not have <tt>X2LinkableBehavior</tt>; have it return an empty array or an array with other desired behaviors
Line 110: Line 151:
 
*: The route that will be used for querying auto-complete results for use in auto-completion fields.
 
*: The route that will be used for querying auto-complete results for use in auto-completion fields.
 
* Create a <tt>getLink</tt> method in the child class that generates the actual link markup.
 
* Create a <tt>getLink</tt> method in the child class that generates the actual link markup.
 +
(Note: the attributes <tt>baseRoute</tt>, <tt>viewRoute</tt> and <tt>autoCompleteSource</tt> essentially tie the model to a "part" of the web application distinguished by its URL, thus allowing the application to generate URLs for usage of it.)

Latest revision as of 21:35, 2 May 2014


Introduction

Typically in Yii, when a model (see: CActiveRecord) is used to retrieve data from a table in the database, the model's attributes are simply inherited from the schema for that table. However, in order to provide the means to add and remove fields from models (and thus from database tables), in addition to providing more advanced options for setting behaviors of attributes, most of the model classes in X2Engine (the ones that are associated with database tables) are extended from a class X2Model. The attributes of all such models are not derived from the database itself but from an attribute registry stored in the x2_fields table. The following columns in the fields table are of particular importance:


Field Name Typically renders as Value
modelName Plain text (filtered/mapped to be human-readable) The exact name of the model class to which the field belongs, with a few if any exceptions (i.e. fields with modelName="Quotes" belong to class Quote)
fieldName N/A (attribute label rendered in its place) The name of the database column
attributeLabel Plain text The attribute label (the name of the field as displayed in the UI)
modified N/A Whether the field has been modified by the user.
custom N/A Whether the field has been created by the user.
type Plain text (filtered/mapped to be human-readable) The type of the column. This does not merely specify the canonical MySQL type, but is used for specifying advanced behaviors for the field. See Field Types for more information.
required Checkbox Specifies that the model attribute cannot be null or empty, if set to 1.
readOnly Checkbox Signifies that the model attribute cannot be modified through user input, if set to 1.
linkType N/A In the case that the field is being used as a link, keywords set in this field signify what type of link should be generated in output.
searchable Checkbox If set to 1, the field's contents are included in global searches through records.
relevance Verbatim what it is in the database A value used for sorting search results: "Low", "Medium" or "High"
isVirtual N/A If set to 1, the field does not actually correspond to a database column; rather, it is an ephemeral attribute of the model that is used for passing data from the view to the controller and vice-versa. For instance, it would be used in the case of input that needs to be collected as part of the model (initially) so that it can be put through input validation.

Field Types

The type of a field as set in x2_fields.type, as mentioned before, is not necessarily a canonical MySQL data type, but rather could be a keyword for specifying how the attribute is to be treated and rendered. For example, when rendering an attribute, X2Model and its subclasses use X2Model::renderAttribute(), wherein a case statement is used to distinguish between field types and choose a method of displaying the field.

Type keyword Canonical type Description
assignment VARCHAR The attribute is rendered as a link using User::getUserLinks. The input field for it is a dropdown list of users and groups.
boolean TINYINT Self-explanatory; true or false.
currency FLOAT A currency value. Setting a field to this type enables printing currency symbols by values.
date INT Date, as a Unix timestamp. Using this type for an integer field ensures it will effectively be treated as a Unix timestamps and converted to a full date when rendered.
dropdown VARCHAR Specifies the ID of a list of items stored in x2_dropdowns to use as the permissible values for the field.
email VARCHAR Specifies that the contents are formatted like (and correspond to an actual) email address.
int INT Self-explanatory
link VARCHAR If the field content is an integer, this field specifies another record that it is linked to / associated with (and the model is specified by linkType), and thus the rendered field will be a link to the view of that record. If it is text, it is treated as a URL and simply rendered.
phone VARCHAR Field is a phone number and should be treated/formatted as such when formatting for output.
rating FLOAT The CStarRating widget should be used to format this field in output.
text TEXT,VARCHAR Distinct from VARCHAR in that links within the field's data are automatically transformed using x2base::convertUrls().
url VARCHAR Field is a URL
varchar VARCHAR Self-explanatory.
visibility INT If 1, the record's contents are public. If 0, it is private. If 2, the record is visible only to the user's groups.
percentage FLOAT Arbitrary numeric value rendered with a percent symbol after it.
credentials INT A record in x2_credentials to use for authenticating with some third-party service. The linkType column represents the service type, and if it contains a colon, then it is the service type (first) and (after the colon) the "system role" alias/nickname for that field (i.e. to identify the field as storing the ID of the SMTP[[wikipedia:Simple Mail Transfer Protocol]]: a network protocol for sending email to a remote server, often involving password authentication and end-to-end SSL encryption. email account for sending notification email).

Setting automatic record links in child classes

Relevant documentation: Component Behavior, CModel::behaviors()

In cases where link and linkType are used, X2LinkableBehavior comes into play; X2Model inherits the behaviors and attributes from that class, since it is attached as a behavior. The method getLink is used for generating controller routes. In this method, it is assumed that the model has the same name as the controller/module. Thus, for every module/controller, the models used by them have the same names, with few exceptions. Thus, this should typically be taken care of already. However, in the case of any new model that is a child class of X2Model, for which the class does not or cannot follow these naming conventions (i.e. a second model inside of a module that needs to use the fields table), the following steps will be necessary:

  • Override the behaviors() method so that the subclass does not have X2LinkableBehavior; have it return an empty array or an array with other desired behaviors
  • Manually set the following attributes:
    baseRoute
    The route prior to any actions; may contain a module and/or a controller ID.
    viewRoute
    The route (before adding the ID as a GET parameter) used for viewing records.
    autoCompleteSource
    The route that will be used for querying auto-complete results for use in auto-completion fields.
  • Create a getLink method in the child class that generates the actual link markup.

(Note: the attributes baseRoute, viewRoute and autoCompleteSource essentially tie the model to a "part" of the web application distinguished by its URL, thus allowing the application to generate URLs for usage of it.)