CiviCRM Entities¶
An "entity" in CiviCRM is a persistent object (typically a sql table), with the following properties:
- A database table: In most cases, there is a 1-to-1 relationship between entities and tables.
- Or other storage medium: Some entities are stored elsewhere, for example Afforms are stored as files.
- Fields: Typically the columns of the database table, although extra fields (e.g. a read-only calculated value) are supported by APIv4.
- An API: Most entities have a corresponding api for CRUD, metadata and other actions.
Tools¶
- Boilerplate code for a new entityType can be generated with
civix generate:entity
. - Most entities are exposed to the CiviCRM API and can be browsed with the API Explorer
- Some Entity-Relationship Diagrams are available to help with better understanding the CiviCRM database design.
Declaration¶
Every entity in CiviCRM is declared via either:
- An
.entityType.php
file loaded viaentity-types-php
mixin (recommended for most entities). - Or
hook_civicrm_entityTypes
(advanced use, for dynamic or generated entities, e.g. ECK).
Note: at the lowest level, hook_civicrm_entityTypes
is the only way for extensions to declare entities.
But the extension mixin entity-types-php
typically handles this automatically; it finds and loads all
.entityType.php
files and passes their contents to the hook.
If you have an advanced use-case and need to implement hook_civicrm_entityTypes
yourself, the data you
pass to the hook will be an array in the same format as that of an .entityType.php
file described below, keyed by the name of the entity, plus the extra key 'module` which must contain the full_name of your extension.
Definition¶
The entityType definition array can contain the following keys:
*
Denotes a required value
'name*'
(string
) - unique entity name, capitalized CamelCase (e.g."SearchDisplay"
)'module*'
(string
) - name of extension declaring the entity (only required when usinghook_civicrm_entityTypes
, the mixin passes this automatically)'table'
(string|null
) - a SQL table name (e.g."civicrm_search_display"
) (required for all entities with a sql table)'class'
(string|null
) - a PHP DAO class (e.g."CRM_Search_DAO_SearchDisplay"
) - used for backward compatibility when converting existing entities from xml/dao toentityType.php
'getInfo'
(callback():array
) - Function returning entity metadata such as:title
(ts(string)
)title_plural
(ts(string)
)description
(ts(string)
)log
(boolean
)add
(string
)icon
(string
)label_field
(string
)
'getPaths'
(callback():array
) - Function returning an array of zero or more paths, each keyed by the action that the path is used for. The most common actions are'add'
,'view'
,'update'
and'delete'
. Less common actions include'browse'
,'preview'
,'copy'
and'detach'
. Paths may include square-bracket tokens such as[id]
or[price_set_id]
.'getIndices'
(callback():array
) - Function returning an array of sql indices.'getFields'
(callback():array
) - Function returning an array of field definitions, keyed by field name, with possible values:title
(ts(string)
)description
(ts(string)
)sql_type
(string
) e.g 'int', 'int(10) unsigned', 'bigint', 'tinyint', 'varchar(30)', 'datetime', 'decimal', 'text'input_type
(string
) one of:ChainSelect
CheckBox
Date
Email
EntityRef
(Autocomplete entity) see also specifyentity_reference
key below.File
Hidden
Location
(Address location)Number
may use the followinginput_attrs
keys:step
Radio
RichTextEditor
Select
Select Date
may use the followinginput_attrs
keys:time
date
start_date_years
end_date_years
Text
may use the followinginput_attrs
keys:text_length
TextArea
may use the followinginput_attrs
keys:note_rows
note_columns
Url
data_type
(string
) One of the following.Blob
Boolean
Date
Email
Enum
Float
Int
Link
Mediumblob
Money
String
Text
Time
Timestamp
required
(boolean
)localizable
(boolean
)serialize
(int
) One of theCRM_Core_DAO::SERIALIZE_*
constants, with a preference towardsCRM_Core_DAO::SERIALIZE_JSON
default
(mixed
)usage
(array
)input_attrs
(array
)pseudoconstant
(array
) See old XML documentation for detailspermission
(array
)entity_reference
for use with EntityRef type, has the following keys:entity
e.g. "Email" or "Contact"key
the field on the entity being referenced that matches this field’s valueon_delete
(CASCADE
orSET NULL
).
'fields_callback'
(deprecated) (array[function($class, &$fields)]
) list of callbacks to modify legacyDAO::fields
'links_callback'
(deprecated): (array[function($class, &$links)]
list of callbacks to modify legacyDAO::getReferenceColumns
Pseudoconstant array¶
Pseudoconstant settings tell the code how to determine the valid options for the field value.
Shared option: prefetch
bool. Should the options for these fields be pre-fetched for UI elements. This defaults to TRUE but can be set to FALSE where it is likely there will be many options.
The options must be specified by using one of the following three methodologies:
Using the civicrm_option_value
table¶
With this methodology, the acceptable field values are taken from rows in the civicrm_option_value
for a given OptionGroup.
Example use in a something.entityType.php
file. Note that the keyColumn
line could be omitted since the default is 'value'
anyway.
<?php
return [
...
'getInfo' => fn() => [
'hat_colour_id' => [
'title' => E::ts('Color of hat'),
...
'pseudoconstant' => [
'optionGroupName' => 'hat_color',
'key_column' => 'value',
]
]
],
];
Using an arbitrary table¶
With this methodology, the acceptable field values are taken from key_column
in table
, with some extra settings that make it different from your typical foreign key.
table
the name of the table to usekey_column
as above, the name of the column that stores the value being referenced.label_column
the column that stores the human readable variant name.name_column
Optional. The column in the referenced table which contains a machine-readable name of the value.condition
Optional. Extra SQL to add in aWHERE
clause that will further limit the possible options
Example:
<?php
return [
...
'getInfo' => fn() => [
'campaign_id' => [
'title' => E::ts('Campaign'),
...
'pseudoconstant' => [
'table' => 'civicrm_campaign',
'key_column' => 'id',
'name_column' => 'iso_code',
'label_column' => 'full_name',
'condition' => 'parent_id IS NULL',
]
]
],
];
name_column
In some cases, key_column
will reference a column containing integers and name_column
will reference a column containing values like "Individual"
. Setting name_column
in these cases allows us to use specify "Individual"
when making API calls with the colon syntax, e.g.
->addWhere('campaign_id:name', '=', 'defund_billionaires')
Using a callback function¶
Take the acceptable field values from a PHP callback function.
<?php
return [
...
'getInfo' => fn() => [
'hat_colour' => [
'title' => E::ts('Color of hat'),
...
'pseudoconstant' => [
'callback' => 'get_the_hat_colours',
]
]
],
];
Elsewhere, e.g. in yourextension.php
<?php
/**
* Callback providing options for hat_colour values.
*
*
*/
function get_the_hat_colours(): array {
return [
// <value> => <label>
'ff0000' => 'Red'
'blue' => 'Blue'
];
}
Typically you might implement the function as a static public method on a class, in which case you would specify the callback
value like CRM_OAuth_BAO_OAuthClient::getProviders