Core Documentation
Here you will find the new official reference manuals. These documents are related to the core of TYPO3 and address the built in functionality of TYPO3. They are designed to provide you with in-depth information.
- Coding Guidelines
- Core Api Reference
- File Abstraction Layer
- Inside TYPO3
- Skinning
- TCA-Reference
- TSconfig Reference
- Typoscript Reference
- Typoscript Syntax
- TYPO3 Services
Old Core Documentation
The [ctrl] section contains properties for the table in general.
These properties are basically divided into two main categories:
properties which affect how the table is displayed and handled in the backend interface . This includes which icon, what name, which columns contains the title value, which column defines the type value etc.
properties which determines how it is processed by the system (TCE).This includes publishing control, "deleted" flag, if the table can only be edited by admin-users, may only exist in the tree root etc.
Key | Datatype | Description | Scope |
|---|---|---|---|
title | string or LLL reference | Contains the system name of the table. Is used for display in the backend. For instance the "tt_content" table is of course named "tt_content" technically. However in the backend display it will be shown as "Pagecontent" when the backend language is English. When another language is chosen, like Danish, then the label "Sideindhold" is shown instead. This value is managed by the "title" value. You can insert plain text values, but the preferred way is to enter a reference to a localized string. See the example below. Refer to the localization section in "Inside TYPO3" for more details. Example: $TCA['sys_template'] = array( 'ctrl' => array( 'title' => 'LLL:EXT:cms/locallang_tca.xml:sys_template', In the above example the "LLL:" prefix tells the system to look up a label from a localized file. The next prefix "EXT:cms" will look for the data in the extension with the key "cms". In that extension the file "locallang_tca.xml" contains a XML structure inside of which one label tag has an index attribute named "sys_template". This tag contains the value to display in the default language. Other languages are provided by the language packs. | Display |
label | string (field name) | Required! Points to the field name of the table which should be used as the "title" when the record is displayed in the system. Note: label_userFunc overrides this property (but it is still required). | Display |
label_alt | String (comma-separated list of field names) | Comma-separated list of field names, which are holding alternative values to the value from the field pointed to by "label" (see above) if that value is empty. May not be used consistently in the system, but should apply in most cases. Example: $TCA['tt_content'] = array( 'ctrl' => array( 'label' => 'header', 'label_alt' => 'subheader,bodytext', See t3lib_BEfunc::getRecordTitle() Also see "label_alt_force" Note: label_userFunc overrides this property. | Display |
label_alt_force | boolean | If set, then the "label_alt" fields are always shown in the title separated by comma. See t3lib_BEfunc::getRecordTitle() Note: label_userFunc overrides this property. | Display |
label_userFunc | string | Function or method reference. This can be used whenever the label or label_alt options don't offer enough flexibility, e.g. when you want to look up another table to create your label. The result of this function overrules the “label”, “label_alt” or “label_alt_force” settings. When calling a method from a class, enter "[classname]->[methodname]". The class name must be prefixed "user_" or "tx_". When using a function, just enter the function name. The function name must be prefixed "user_" or "tx_". The preferred way is to use a class and a method. Two arguments will be passed to the function/method: The first argument is an array which contains the following information about the record for which to get the title: $params['table'] = $table; $params['row'] = $row; The resulting title must be written to $params['title'] which is passed by reference. The second argument is a reference to the parent object. Note: The function file must be included manually (e.g. include it in your ext_tables.php file). When using a class, the preferred way is to declare it with the autoloader. Example: Let's look at what is done for the "haiku" table of the "examples" extension. First, in the ext_autoload.php file: $extensionPath = t3lib_extMgm::extPath('examples'); return array( 'tx_examples_tca' => $extensionPath . 'class.tx_examples_tca.php', ); the necessary class is declared. The call to the user function appears in the ext_tables.php file: $TCA['tx_examples_haiku'] = array( 'ctrl' => array( ... 'label' => 'title', 'label_userFunc' => 'tx_examples_tca->haikuTitle', ... ) ); Finally in class.tx_examples_tca.php is the code itself: public function haikuTitle(&$parameters, $parentObject) { $record = t3lib_BEfunc::getRecord($parameters['table'], $parameters['row']['uid']); $newTitle = $record['title']; $newTitle .= ' (' . substr(strip_tags($record['poem']), 0, 10) . '...)'; $parameters['title'] = $newTitle; } | Display |
type | string (field name) | Field name, which defines the "record type". The value of this field determines which one of the 'types' configurations are used for displaying the fields in the TCEforms. It will probably also affect how the record is used in the context where it belongs. The most widely known usage of this feature is the Content Elements where the "Type:" selector is defined as the "type" field and when you change that selector you will also get another rendering of the form: It is also used by the "doktype" field in the "pages" table. Example: The "dummy" table from the "examples" extension defines different types. The field used for differentiating the types is the "record_type" field. Hence we have the following in the [ctrl] section of the tx_examples_dummy table: 'type' => 'record_type' The "record_type" field can takes values ranging from 0 to 2. Accordingly we define types for the same values. Each type defines which fields will be displayed in the BE form. Types are discussed in more details later on. 'types' => array( '0' => array('showitem' => 'hidden, record_type, title, some_date '), '1' => array('showitem' => 'record_type, title '), '2' => array('showitem' => 'title, some_date, hidden, record_type '), ), Since TYPO3 4.7, it is also possible to make the type depend on the value of a related record, i.e. switch using the type field of a foreign table. The syntax is "relation_field:foreign_type_field". Example Imagine two tables, related as parent and child. The child table has a relation to the parent table using a "select" field called "myparent" with "foreign_table" set to the parent table. Now, if you want the fields displayed in the child table to depend on a field called "parenttype" of the parent table, you can define the [ctrl][type] of the child table like "myparent:parenttype". | Display / Proc. |
hideTable | boolean | Hide this table in record listings. | |
requestUpdate | string (list of field names) | This is a list of fields that will trigger an update of the form, on top of the "type" field. This is generally done to hide or show yet more fields depending on the value of the field that triggered the update. | Proc. |
iconfile | string | Pointing to the icon file to use for the table. Icons should be dimensioned 16x16 pixels and of the GIF or PNG file type. The value of the option can be any of these:
Example: How to assign an icon from an extension For haikus from the "examples" extension, the icon is defined this way: 'iconfile' => t3lib_extMgm::extRelPath($_EXTKEY) . 'icon_tx_examples_haiku.gif', | Display |
typeicon_column | string (field name) | Field name, whose value decides alternative icons for the table (The default icon is the one defined with the 'iconfile' value.) An icon in the 'typeicons' array may override the default icon if an entry is found for the key having the value of the field pointed to by "typeicon_column" (this feature). Notice: These options ("typeicon_column" and "typeicons") do not work for the pages-table, which is configured by the $PAGES_TYPES array. Related "typeicons" This feature is used by for instance the "tt_content" table (Content Elements) where each type of content element has its own icon. Example: See "typeicons" | Display |
typeicons | array | (See "typeicon_column") Example of configuration (from the "tt_content" table): 'typeicon_column' => 'CType', 'typeicons' => array( 'header' => 'tt_content_header.gif', 'textpic' => 'tt_content_textpic.gif', 'image' => 'tt_content_image.gif', 'bullets' => 'tt_content_bullets.gif', 'table' => 'tt_content_table.gif', 'splash' => 'tt_content_news.gif', 'uploads' => 'tt_content_uploads.gif', 'multimedia' => 'tt_content_mm.gif', 'menu' => 'tt_content_menu.gif', 'list' => 'tt_content_list.gif', 'mailform' => 'tt_content_form.gif', 'search' => 'tt_content_search.gif', 'login' => 'tt_content_login.gif', 'shortcut' => 'tt_content_shortcut.gif', 'script' => 'tt_content_script.gif', 'div' => 'tt_content_div.gif', 'html' => 'tt_content_html.gif' ), | Display |
thumbnail | string (field name) | Field name, which contains the value for any thumbnails of the records. This could be a field of the "group" type containing a list of file names. Example: For the "tt_content" table this option points to the field "image" which contains the list of images that can be attached to the content element: 'thumbnail' => 'image', The effect of the field can be see in listings in e.g. the "List" module: (You might have to enable "Show Thumbnails by default" in the "Startup" tab of the User Settings module first in order to see this display). | Display |
selicon_field | string (field name) | Field name, which contains the thumbnail image used to represent the record visually whenever it is shown in TCEforms as a foreign reference selectable from a selector box. Only images in a usual format for the web (i.e. gif, png, jpeg, jpg) are allowed. No scaling is done. You should consider this a feature where you can attach an "icon" to a record which is typically selected as a reference in other records. For example a "category". In such a case this field points out the icon image which will then be shown. This feature can thus enrich the visual experience of selecting the relation in other forms. Example: The "backend_layout" table defines the "icon" field as being the one containing reference icons: $TCA['backend_layout'] = array ( 'ctrl' => array ( ... 'selicon_field' => 'icon', 'selicon_field_path' => 'uploads/media', ... ) ); Also see "selicon_field_path" below. | Display |
selicon_field_path | string | The path prefix of the value from 'selicon_field'. This must the same as the "upload_path" of that field. See example above. | Display |
sortby | string (field name) | Field name, which is used to manage the order of the records. The field will contain an integer value which positions it at the correct position between other records from the same table on the current page. NOTICE: The field should not be editable by the user since the TCE will manage the content automatically in order to manage the order of records. This feature is used by e.g. the "pages" table and "tt_content" table (Content Elements) in order to output the pages or the content elements in the order expected by the editors. Extensions are expected to respect this field. Typically the field name "sorting" is dedicated to this feature. Also see "default_sortby" below. | Display/Proc. |
default_sortby | string | If a field name for "sortby" is defined, then this is ignored. Otherwise this is used as the 'ORDER BY' statement to sort the records in the table when listed in the TYPO3 backend. Example: For the "haikus" table of the "examples" extension, records are listed alphabetically, based on their title: $TCA['tx_examples_haiku'] = array( 'ctrl' => array( ... 'default_sortby' => 'ORDER BY title', ... ) ); | Display |
mainpalette | comma-separated list of integers (pointing to multiple palette keys) | Points to the palette-number(s) that should always be shown in the bottom of the TCEform. Example: The [ctrl] section looks like this: 'mainpalette' => '1', The number "1" references a palette. This palette could be something like: 'palettes' => array( '1' => array('showitem' => 'hidden,starttime,endtime,fe_group'), Note that "mainpalette" is not much used anymore. It has the drawback of positioning the related fields weirdly when tabs are added to existing tables via extensions (the fields come at the end of the new tabs, which may be disturbing for editors). | Display |
canNotCollapse | boolean | By default, fields placed in palettes (see later for more about palettes) are not shown by TCEforms. They appear only once the "Show secondary options" checkbox at the bottom of the screen is checked. By setting "canNotCollapse" to true, the palettes of this table will always be displayed, as if the above-mentioned option was always checked. This setting can also be defined per palette (see later). | Display |
tstamp | string (field name) | Field name, which is automatically updated to the current timestamp (UNIX-time in seconds) each time the record is updated/saved in the system. Typically the name "tstamp" is used for that field. Example: from the [ctrl] section of the "haikus" table: $TCA['tx_examples_haiku'] = array( ... 'tstamp' => 'tstamp', 'crdate' => 'crdate', 'cruser_id' => 'cruser_id', ... ) ); The above example shows the same definition for the "crdate" and "cruser_id" fields described below. | Proc. |
crdate | string (field name) | Field name, which is automatically set to the current timestamp when the record is created. Is never modified again. Typically the name "crdate" is used for that field. See example above. | Proc. |
cruser_id | string (field name) | Field name, which is automatically set to the uid of the backend user (be_users) who originally created the record. Is never modified again. Typically the name "cruser_id" is used for that field. See example above. | Proc. |
rootLevel | [0, 1, -1] | Determines where a record may exist in the page tree. There are three options depending on the value:
Notice: The setting for "rootLevel" is ignored for records in the "pages" table (they are hardcoded to be allowed anywhere, equal to a "-1" setting of rootLevel). Warning: this property does not tell the whole story. If set to "0" or "-1", it allows records from the table in the page tree, but not on any kind of page. By default records can be created only in "Folder"-type pages. To enable the creation of records on any kind of page, an additional call must be made: t3lib_extMgm::allowTableOnStandardPages('tx_examples_haiku'); | Proc. / Display |
readOnly | boolean | Records from this table may not be edited in the TYPO3 backend. Such tables are usually called "static". | Proc. / Display |
adminOnly | boolean | Records may be changed only by "admin"-users (having the "admin" flag set). Example: The "cms" system extension defines the table "sys_template" as being editable only by admin users: $TCA['sys_template'] = array ( 'ctrl' => array ( ... 'adminOnly' => 1, ... ) ); | Proc. / Display |
editlock | string (field name) | Field name, which – if set – will prevent all editing of the record for non-admin users. The field should be configured as a checkbox type. Non-admins could be allowed to edit the checkbox but if they set it, they will effectively lock the record so they cannot edit it again – and they need an Admin-user to remove the lock. Note that this flag is cleared when a new copy or version of the record is created. This feature is used on the pages table, where it also prevents editing of records on that page (except other pages)! Also, no new records (including pages) can be created on the page. | Proc / Display |
origUid | string (field name) | Field name, which will contain the UID of the original record in case a record is created as a copy or new version of another record. Is used when new versions are created from elements and enables the backend to display a visual comparison between a new version and its original. | Proc |
delete | string (field name) | Field name, which indicates if a record is considered deleted or not. If this feature is used, then records are not really deleted, but just marked 'deleted' by setting the value of the field name to "1". And in turn the whole system must strictly respect the record as deleted. This means that any SQL query must exclude records where this field is true. This is a very common feature. Most tables use it throughout the TYPO3 Core. | Proc. / Display |
enablecolumns | array | Specifies which publishing control features are automatically implemented for the table. This includes that records can be "disabled" or "hidden", have a starting and/or ending time and be access controlled so only a certain front end user group can access them In the frontend libraries the enableFields() function automatically detects which of these fields are configured for a table and returns the proper WHERE clause SQL code for creating select queries. There are the keys in the array you can use. Each of the values must be a field name in the table which should be used for the feature: "disabled": defining hidden-field of record "starttime": defining start time-field of record "endtime": defining end time-field of record "fe_group": defining fe_group-field of record Notice: In general these fields do not affect the access or display in the backend! They are primarily related to the frontend. However the icon of records having these features enabled will normally change as these examples show: See also the "delete" feature which is related, but is active for both frontend and backend. Example: Typically the "enablecolumns" could be configured like this (here for the "tt_content" table): 'enablecolumns' => array( 'disabled' => 'hidden', 'starttime' => 'starttime', 'endtime' => 'endtime', 'fe_group' => 'fe_group', ), | Proc. / Display |
searchFields | string | Comma-separated list of fields from the table that will be included when searching for records in the TYPO3 backend. Starting with TYPO3 4.6, no record from a table will ever be found if that table does not have "searchFields" defined. There are finer controls per column, see the "search" property in the list of "Common properties" further in this manual. Example: The "tt_content" table has the following definition: $TCA['pages'] = array( 'ctrl' => array( ... 'searchFields' => 'title,alias,nav_title,subtitle,url,keywords,description,abstract,author,author_email', ... ), ); | Search |
groupName | string | This option can be used to group records in the new record wizard. If you define a new table and set its "groupName" to the key of another extension, your table will appear in the list of records from that other extension in the new record wizard. | Special |
hideAtCopy | boolean | If set, and the "disabled" field from "enablecolumns" (see above) is specified, then records will be disabled/hidden when they are copied. | Proc. |
prependAtCopy | string or LLL reference | This string will be prepended the records title field when the record is inserted on the same PID as the original record (thus you can distinguish them). Usually the value is something like " (copy %s)" which tells that it was a copy that was just inserted (The token "%s" will take the copy number). | Proc. |
copyAfterDuplFields | string (list of field names) | The fields in this list will automatically have the value of the same field from the 'previous' record transferred when they are copied or moved to the position after another record from same table. Example: 'copyAfterDuplFields' => 'colPos, sys_language_uid', | Proc. |
setToDefaultOnCopy | string (list of field names) | These fields are restored to the default value of the record when they are copied. Example: $TCA['sys_action'] = array( 'ctrl' => array( 'setToDefaultOnCopy' => 'assign_to_groups', | Proc. |
useColumnsForDefaultValues | string (list of field names) | When a new record is created, this defines the fields from the 'previous' record that should be used as default values. Example: $TCA['sys_filemounts'] = array( 'ctrl' => array( 'useColumnsForDefaultValues' => 'path,base', | Proc. |
shadowColumnsForNewPlaceholders | string (list of field names) | When a new element is created in a draft workspace a placeholder element is created in the Live workspace. Some values must be stored in this placeholder and not just in the overlay record. A typical example would be "sys_language_uid". This property defines the list of fields whose values are "shadowed" to the Live record. All fields listed for this option must be defined in $TCA[<table>]['columns'] as well. Furthermore fields which are listed in "transOrigPointerField", "languageField", "label" and "type" are automatically added to this list of fields and do not have to mentioned again here. Example: $TCA['tt_content'] = array( 'ctrl' => array( 'shadowColumnsForNewPlaceholders' => 'sys_language_uid,l18n_parent,colPos', | Proc. |
is_static | boolean | This marks a table to be "static". A "static table" means that it should not be updated for individual databases because it is meant to be centrally updated and distributed. For instance static tables could contain country-codes used in many systems. The foremost property of a static table is that the uid's used are the SAME across systems. Import/Export of records expect static records to be common for two systems. Example (also including the features "rootLevel", "readOnly" and "adminOnly" above): $TCA['static_template'] = array( 'ctrl' => array( 'label' => 'title', 'tstamp' => 'tstamp', 'title' => 'LLL:EXT:statictemplates/locallang_tca.xml:static_template', 'readOnly' => 1,// Prevents the table from being altered 'adminOnly' => 1, // Only admin, if any 'rootLevel' => 1, 'is_static' => 1, | Used by import/export |
fe_cruser_id | string (field name) | Field name which is used to store the uid of a frontend user if the record is created through fe_adminLib | FE |
fe_crgroup_id | string (field name) | Field name which is used for storing the uid of a frontend group whose members are allowed to edit through fe_adminLib . | FE |
fe_admin_lock | string (field name) | Field name which points to the field name which - as a boolean - will prevent any editing by the fe_adminLib if set. Say if the "fe_cruser_id" field matches the current fe_user normally the field is editable. But with this option, you could make a check-box in the backend that would lock this option. | FE |
languageField | string (field name) | Localization access control. Field name which contains the pointer to the language of the record's content. Language for a record is defined by an integer pointing to a “sys_language” record (found in the page tree root). Backend users can be limited to have edit access for only certain of these languages and if this option is set, edit access for languages will be enforced for this table. The values in this field may be the following: -1 : (ALL) The record does not represent any specific language. Localization access control is never carried out for such a record. Typically this is used if the record has content which itself handles localization (such as plugins or flexforms). 0 : The default language of the system. Localization access control applies. Values > 0 : Points to a uid of a sys_language record representing a possible language for translation. Localization access control applies. The field name pointed to should be a single value selector box (maxitems <=1) saving its value into an integer field in the database. | Proc / Display |
transOrigPointerField | string (field name) | Name of the field used by translations to point back to the original record (i.e. the record in the default language of which they are a translation). If this value is found being set together with “languageField” then TCEforms will show the default translation value under the fields in the main form. This is very neat if translators are to see what they are translating of course... Must be configured in $TCA[<table>]['columns'], at least as a passthrough type. | Proc / Display |
transForeignTable | string (table name) | Translations may be stored in a separate table, instead of the same one. In such a case, the name of the translation table is stored in this property. The translation table in turn will use the "transOrigPointerTable" property to point back to this table. This is used in the TYPO3 Core for the "pages" table, which uses the "pages_language_overlay" table to hold the translations. Example: $TCA['pages'] = array( 'ctrl' => array( ... 'transForeignTable' => 'pages_language_overlay', $TCA['pages_language_overlay'] = array ( 'ctrl' => array ( ... 'transOrigPointerField' => 'pid', 'transOrigPointerTable' => 'pages', Note that the "transOrigPointerField" is still used, but within the table holding the translations. WARNING: This is still not fully for all other tables than the “pages” table. You should expect some issues and inconsistencies when using this translation method. | |
transOrigPointerTable | string (table name) | Symmetrical property to "transForeignTable". See above for explanations. | Proc / Display |
transOrigDiffSourceField | string (field name) | Field name which will be updated with the value of the original language record whenever the translation record is updated. This information is later used to compare the current values of the default record with those stored in this field and if they differ there will be a display in the form of the difference visually. This is a big help for translators so they can quickly grasp the changes that happened to the default language text. The field type in the database should be a large text field (clob/blob). You don't have to configure this field in $TCA[<table>]['columns'], but if you do, select the “passthrough” type. That will enable that the undo function to also work on this field. | Proc / Display |
versioningWS | boolean / version number | If set, versioning is enabled for this table. If integer it indicates a version number of versioning features.
Versioning in TYPO3 is based on this scheme: [Online version, pid>=0] 1- * [Offline versions, pid=-1] Offline versions are identified by having a pid value = -1 and they refer to their online version by the field “t3ver_oid”. Offline versions of the “Page” and “Branch” types (contrary to “Element” type) can have child records which points to the uid of their offline “root” version with their pid fields (as usual). These children records are typically copies of child elements of the online version of the offline root version, but are not considered “versions” of them in a technical sense, hence they don't point to them with their t3ver_oid field (and shouldn't). In the backend “Offline” is labeled “Draft” while “Online” is labeled “Live”. In order for versioning to work on a table there are certain requirements; Tables supporting versioning must have these fields:
Corresponding SQL definitions: t3ver_oid int(11) DEFAULT '0' NOT NULL, t3ver_id int(11) DEFAULT '0' NOT NULL, t3ver_wsid int(11) DEFAULT '0' NOT NULL, t3ver_label varchar(30) DEFAULT '' NOT NULL, t3ver_state tinyint(4) DEFAULT '0' NOT NULL, t3ver_stage int(11) DEFAULT '0' NOT NULL, t3ver_count int(11) DEFAULT '0' NOT NULL, t3ver_tstamp int(11) DEFAULT '0' NOT NULL, t3ver_move_id int(11) DEFAULT '0' NOT NULL, Special “t3ver_swapmode” field for pages When pages are versioned it is an option whether content and even the branch of the page is versioned. This is determined by the parameter “treeLevels” set when the page is versioned. “-1” means swap only record, 0 means record and content and >0 means full branch. When the version is later published the swapping will happen accordingly. | Proc. |
versioningWS_alwaysAllowLiveEdit | boolean | If set, this table can always be edited live even in a workspace and even if “live editing” is not enabled in a custom workspace. For instance this is set by default for Backend user and group records since it is assumed that administrators like the flexibility of editing backend users without having to go to the Live workspace. | |
versioning_followPages | boolean | (Only for other tables than “pages”) If set, content from this table will get copied along when a new version of a page is created. Tracking Originals It is highly recommended to use the “origUid” feature for tables whose records are copied with pages that are versioned with content or subtree since this will enable the possibility of content comparison between current and future versions. | Proc. |
dividers2tabs | integer | This key defines the activation of tabs, according to the following values: 0: disabled (default) 1: activated, empty tabs are removed 2: activated, empty tabs are disabled When tabs are activated, the special field name "--div--" used in the types configuration will be interpreted as starting a new tab in a tab-menu for the record. The second part after "--div--" is the title of the tab. If you place a "--div--" field as the very first element in the types configuration it will just be used to set the title of the first tab (which is by default "General"). Example: The [ctrl] section of table "tt_content" contains the following: $TCA['tt_content'] = array ( 'ctrl' => array ( 'dividers2tabs' => 1 Then the types make use of "--div--" fields. Example for the "text"-type (usage of "--div--" highlighted in bold): 'types' => array( '1' => array( 'showitem' => 'CType', ), ... 'text' => array( 'showitem' => '--palette--;LLL:EXT:cms/ locallang_ttc.xml:palette.general;general, --palette--;LLL:EXT:cms/ locallang_ttc.xml:palette.header;header, bodytext;LLL:EXT:cms/ locallang_ttc.xml:bodytext_formlabel;;richtext:rte_transform[flag=rte_enabled|mode=ts_css], rte_enabled;LLL:EXT:cms/ locallang_ttc.xml:rte_enabled_formlabel, --div--;LLL:EXT:cms/ locallang_ttc.xml:tabs.access, --palette--;LLL:EXT:cms/ locallang_ttc.xml:palette.visibility;visibility, --palette--;LLL:EXT:cms/ locallang_ttc.xml:palette.access;access, --div--;LLL:EXT:cms/ locallang_ttc.xml:tabs.appearance, --palette--;LLL:EXT:cms/ locallang_ttc.xml:palette.frames;frames, --palette--;LLL:EXT:cms/ locallang_ttc.xml:palette.textlayout;textlayout, --div--;LLL:EXT:cms/ locallang_ttc.xml:tabs.extended', ), This will render a tab menu for the record where the fields are distributed on the various tabs: Here another tab is activated and another part of the form is shown: Since TYPO3 4.3, it is customary for most tables to make use of tabs for improved usability. | |
dynamicConfigFile | string | Reference to the complete $TCA entry content. Filename of the PHP file which contains the full configuration of the table in $TCA. The [ctrl] part (and [feInterface] if used) are always mandatory, but the rest may be placed in such a file in order to limit the amount of memory consumed by the $TCA array (when e.g. the columns definitions are not needed). The format of the value may be:
Example: Looking at the definition of the "haikus" table, we find the following in the "ext_tables.php" file: $TCA['tx_examples_haiku'] = array( 'ctrl' => array( ... 'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY) . 'tca.php', ... ) ); Then in the file "tca.php" is PHP code which completes the $TCA entry for the table: <?php $TCA['tx_examples_haiku'] = array( 'ctrl' => $TCA['tx_examples_haiku']['ctrl'], 'columns' => array( 'hidden' => array( 'exclude' => 1, 'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden', 'config' => array( 'type' => 'check', 'default' => '0' ) ), … Note how the [ctrl] section is referenced so as not to be lost. See Appendix B for a detailed discussion of dynamically loading $TCA. | API |
EXT[extension_key] | array | User-defined content for extensions. You can use this as you like. Let's say that you have an extension with the key "myext", then you have the right to define properties for: ...['ctrl']['EXT']['myext'] = ... (whatever you define) Note that this is just a convention. You can use some other syntax but with the risk that it conflicts with some other extension or future changes in the TYPO3 Core. | Ext. |
Here are a couple examples of complete configurations of [ctrl] sections.
$TCA['pages'] = array(
'ctrl' => array(
'label' => 'title',
'tstamp' => 'tstamp',
'sortby' => 'sorting',
'title' => 'LLL:EXT:lang/locallang_tca.xml:pages',
'type' => 'doktype',
'versioningWS' => 2,
'origUid' => 't3_origuid',
'delete' => 'deleted',
'crdate' => 'crdate',
'hideAtCopy' => 1,
'prependAtCopy' => 'LLL:EXT:lang/locallang_general.xml:LGL.prependAtCopy',
'cruser_id' => 'cruser_id',
'editlock' => 'editlock',
'useColumnsForDefaultValues' => 'doktype,fe_group,hidden',
'dividers2tabs' => 1,
'enablecolumns' => array(
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
'fe_group' => 'fe_group',
),
'transForeignTable' => 'pages_language_overlay',
'typeicon_column' => 'doktype',
'typeicon_classes' => array(
'1' => 'apps-pagetree-page-default',
'1-hideinmenu' => 'apps-pagetree-page-not-in-menu',
...
'contains-news' => 'apps-pagetree-folder-contains-news',
'default' => 'apps-pagetree-page-default',
),
'typeicons' => array(
'1' => 'pages.gif',
'254' => 'sysf.gif',
'255' => 'recycler.gif',
),
'dynamicConfigFile' => 'T3LIB:tbl_pages.php',
)
);
This is found in file "t3lib/stddb/tables.php". Here are a few notes:
When pages are displayed in the backend, the "label" property indicates that you will see the content from the field named "title" shown as the title of the page record.
The field called "sorting" will be used to determine the order in which pages are displayed within each branch of the page tree.
The title for the pages table as shown in the backend (e.g. "Pages" in english, "Sider" in danish etc...) is defined as coming from a "locallang" file.
The "type" field will be the one named "doktype". This determines the set of fields shown in the edit forms in the backend.
Note on the last line how the dynamic configuration file is referenced.
Configuration for the tt_content table (Content Elements) is no less complete. It can be found in file "/typo3/sysext/cms/ext_tables.php":
// ******************************************************************
// This is the standard TypoScript content table, tt_content
// ******************************************************************
$TCA['tt_content'] = array (
'ctrl' => array (
'label' => 'header',
'label_alt' => 'subheader,bodytext',
'sortby' => 'sorting',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'title' => 'LLL:EXT:cms/locallang_tca.xml:tt_content',
'delete' => 'deleted',
'versioningWS' => 2,
'versioning_followPages' => true,
'origUid' => 't3_origuid',
'type' => 'CType',
'hideAtCopy' => true,
'prependAtCopy' => 'LLL:EXT:lang/locallang_general.xml:LGL.prependAtCopy',
'copyAfterDuplFields' => 'colPos,sys_language_uid',
'useColumnsForDefaultValues' => 'colPos,sys_language_uid',
'shadowColumnsForNewPlaceholders' => 'colPos',
'transOrigPointerField' => 'l18n_parent',
'transOrigDiffSourceField' => 'l18n_diffsource',
'languageField' => 'sys_language_uid',
'enablecolumns' => array (
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
'fe_group' => 'fe_group',
),
'typeicon_column' => 'CType',
'typeicon_classes' => array(
'header' => 'mimetypes-x-content-header',
...
'default' => 'mimetypes-x-content-text',
),
'typeicons' => array (
'header' => 'tt_content_header.gif',
...
'html' => 'tt_content_html.gif'
),
'thumbnail' => 'image',
'requestUpdate' => 'list_type,rte_enabled',
'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY).'tbl_tt_content.php',
'dividers2tabs' => 1
)
);
of particular note is the "enablecolumns" property. It is quite extensive for this table since it is a frontend-related table. Thus proper access rights, publications dates, etc. must be enforced.
every type of content element has its own icon and its own class, used in conjunction with the skinning API to visually represent that type in the TYPO3 backend.
the column "image" is defined as the one to use to fetch any thumbnails related to the record.
Contains configuration for display and listing in various parts of the core backend:
Key | Datatype | Description |
|---|---|---|
showRecordFieldList | string (list of field names) | Defines which fields are shown in the show-item dialog. E.g. 'doktype,title,alias,hidden,....' |
always_description | boolean | If set, the description/helpicons are always shown regardless of the configuration of the user. Works only in TCEforms and for tables loaded via t3lib_BEfunc::loadSingleTableDescription()
|
maxDBListItems | integer | Max number of items shown in the List module |
maxSingleDBListItems | integer | Max number of items shown in the List module, if this table is listed in Extended mode (listing only a single table) |
The "feInterface" section contains properties related to Front End Editing of the table, mostly related to the feAdmin_lib.
Is deprecated in the sense that it will still exist, but will not be (and should not be) extended further.
Key | Datatype | Description |
|---|---|---|
editableRecordFields | string (list of field names) | List of fields, example: '*name, *type, biography, filmography'. Used for front-end edit module created by Rene Fritz <r.fritz@colorcube.de> |
fe_admin_fieldList | string (list of field names) | List of fields allowed for editing/creation with the fe_adminLib module, see media/scripts/fe_adminLib, example: 'pid,name,title,address' |
The "columns" section contains configuration for each table field (also called "column") which can be edited by the backend.
The configuration includes both properties for the display in the backend as well as the processing of the submitted data.
Each field can be configured as a certain "type" (e.g. checkbox, selector, input field, text area, file or db-relation field, user defined etc.) and for each type a separate set of additional properties applies. These properties are clearly explained below for each type.
This table shows the keys of the ['columns'][field name] array:
Key | Datatype | Description | Scope |
|---|---|---|---|
label | string or LLL reference | Required! The name of the field as it is shown in the interface:
| Display |
exclude | boolean | If set, all backend users are prevented from editing the field unless they are members of a backend user group with this field added as an "Allowed Excludefield" (or "admin" user). See "Inside TYPO3" document about permissions. | Proc. |
l10n_mode | string (keyword) | Localization mode. Only active if the ctrl-directive “languageField” is set. The main relevance is when a record is localized by an API call in TCEmain that makes a copy of the default language record. You can think of this process as copying all fields from the source record, except if a special mode applies as defined below: Keywords are:
As mentioned above if “l10n_mode” is not set for a given field, that field is just copied as is to the translated record. (Doesn't apply to flexform fields.) | Display / Proc. |
l10n_display | list of keywords | Localization display. see: l10n_mode This option can be used to define the language related field rendering. This has nothing to do with the processing of language overlays and data storage but the display of form fields. Keywords are:
| Display |
l10n_cat | string (keyword) | Localization category. Keywords: text,media When localization mode is set for a TCEforms, it must be either of these values. Only the fields that have l10n_cat set to the localization mode is shown. Used to limit display so only most relevant fields are shown to translators. It doesn't prevent editing of other fields if records are edited outside localization mode, it merely works as a display condition. It is also used in localization export (pending at this moment). | Display |
config | array | Contains the actual configuration properties of the fields display and processing behavior. The possibilities for this array depend on the value of the array key "type" within the array. Each valid value for "type" is shown below in a separate table. Furthermore there are some properties common to all field types, described in the next chapter "['columns'][field name]['config'] / Common properties". | - |
displayCond | string | Contains a condition rule for whether to display the field or not. A rule is a string divided into several parts by ":" (colons). The first part is the rule-type and the subsequent parts will depend on the rule type. Currently these rule values can be used:
For FlexForm elements the fields are tags on same level. If <langChildren> is enabled, then the value of other fields on same level is taken from the same language. The field-values of the FlexForm-parent record are prefixed with "parentRec.". These fields can be used like every other field (since TYPO3 4.3). Example: This example will require the field named "tx_templavoila_ds" to be true, otherwise the field for which this rule is set will not be displayed: 'displayCond' => 'FIELD:tx_templavoila_ds:REQ:true', This example requires the extension "static_info_tables" to be loaded, otherwise the field is not displayed (this is useful if the field makes a look-up on a table coming from another extension!): 'displayCond' => 'EXT:static_info_tables:LOADED:true', This example would require the header-field of the FlexForm-parent record to be true, otherwise the FlexForm field is not displayed (works only within FlexForm datastructure definitions): <displayCond>FIELD:parentRec.header:REQ:true</displayCond> | Display |
defaultExtras | string | In the “types” configuration of a field you can specify on position 4 a string of "extra configuration". This string will be the default string of extra options for a field regardless of types configuration. For instance this can be used to create an RTE field without having to worry about special configuration in “types” config. This is also the way by which you can enable the RTE for FlexForm fields. Example value: richtext[cut|copy|paste|formatblock|textcolor|bold|italic|underline|left|center|right|orderedlist|unorderedlist|outdent|indent|link|table|image|line|chMode]:rte_transform[mode=ts_css|imgpath=uploads/tx_mininews/rte/] |
There are a number of properties which are common to all field types. They are described below.
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | This defines the type of field. It must one of the values described in the following chapters. | Display / Proc. |
form_type | string | This will override the field type when displaying it as a form. It can take any of the values available for "type" above. | Display |
default | - | This property can be used to set a default value for the field. Its data type is whatever is appropriate for the given field. | Display / Proc. |
softref | string | Used to attach "soft reference parsers". See under "Additional TCA features" for information about softref keys. The syntax for this value is key1,key2[parameter1;parameter2;...],... | Proc. |
readOnly | boolean | Renders the form in a way that the user can see the values but cannot edit them. The rendering is as similar as possible to the normal rendering but may differ in layout and size.Notice: Read-only rendering might not be implemented by user defined form items! It is up to each developer to implement read-only rendering for its own user-types. | Display |
search | array | Defines additional search-related options for a given field.
Example: The "tt_content" table has the following definition: $TCA['tt_content'] = array( ... 'columns' => array( ... 'bodytext' => array( ... 'config' => array( ... ), 'search' => array( 'andWhere' => 'CType=\'text\' OR CType=\'textpic\'', ) ), ... ), ... ); This means that the "bodytext" field of the "tt_content" table will be searched in only for elements of type Text and Text with image. This helps make any search more relevant. | Search |
The type "input" generates an <input> field, possibly with additional features applied.
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "input"] | Display / Proc. |
size | integer | Abstract value for the width of the <input> field. To set the input field to the full width of the form area, use the value 48. Default is 30. | Display |
max | integer | Value for the "maxlength" attribute of the <input> field. If the form element edits a varchar(40) field in the database you should also set this value to 40. | Display |
default | string | The default value | Display / Proc. |
eval | list of keywords | Configuration of field evaluation. Some of these evaluation keywords will trigger a JavaScript pre-evaluation in the form. Other evaluations will be performed in the backend. The evaluation functions will be executed in the list-order. Keywords:
All the above evaluations (unless noted) are done by JavaScript with the functions found in the script t3lib/jsfunc.evalfield.js "(TCE)" means the evaluation is done in the TCE on the server. The class used for this is t3lib_TCEmain. Example: Setting the field to evaluate the input to a date returned to the database in UNIX-time (seconds) 'eval' => 'date', Trimming the value for white space before storing in the database (important for varchar fields!) 'eval' => 'trim', By this configuration the field will be stripped for any space characters, converted to lowercase, only accepted if filled in and on the server the value is required to be unique for all records from this table: 'eval' => 'nospace,lower,unique,required' User-defined form evaluations: You can supply your own form evaluations in an extension by creating a class with two functions, one which returns the JavaScript code for client side validation called returnFieldJS() and one which does the server side validation called evaluateFieldValue(). The function evaluateFieldValue() has 3 arguments:
Example: class.tx_exampleextraevaluations_extraeval1.php: <?php class tx_exampleextraevaluations_extraeval1 { function returnFieldJS() { return ' return value + " [added by JS]"; '; } function evaluateFieldValue($value, $is_in, &$set) { return $value . ' [added by PHP]'; } } ?> ext_localconf.php <?php // here we register "tx_exampleextraevaluations_extraeval1" $TYPO3_CONF_VARS['SC_OPTIONS']['tce']['formevals']['tx_exampleextraevaluations_extraeval1'] = 'EXT:example_extraevaluations/ class.tx_exampleextraevaluations_extraeval1.php'; ?> | Display / Proc. |
is_in | string | If the evaluation type "is_in" (see above, under key "eval") is used for evaluation, then the characters in the input string should be found in this string as well. This value is also passed as argument to the evaluation function if a user-defined evaluation function is registered. | Display / Proc. |
checkbox | string | This setting is not used anymore since TYPO3 4.5. To set a default value, use the "default" property. If defined (even empty), a checkbox is placed before the input field. If a value other than the value of 'checkbox' (this value) appears in the input-field the checkbox is checked. Example: 'checkbox' => '123', If you set this value then entering "12345" in the field will render this:
Example listing: 'config' => array( 'type' => 'input', 'size' => '8', 'max' => '20', 'eval' => 'date', 'checkbox' => '0', 'default' => '0' ) Will create a field like this below. Checking the checkbox will insert the date of the current day. Unchecking the checkbox will just remove the value and silently sent a zero to the server (since the value of the key "checkbox" is set to "0").
| Display / Proc. |
range | array | An array which defines an integer range within which the value must be. Keys: "lower": Defines the lower integer value. "upper": Defines the upper integer value. You can specify both or only one of them. Notice: This feature is evaluated on the server only so any regulation of the value will have happened after saving the form. Example: Limits an integer to be within the range 10 to 1000: 'eval' => 'int', 'range' => array( 'lower' => 10, 'upper' => 1000 ), In this example the upper limit is set to the last day in year 2020 while the lowest possible value is set to the date of yesterday. 'range' => array( 'upper' => mktime(0, 0, 0, 12, 31, 2020), 'lower' => mktime(0,0,0,date('m'), date('d'), date('Y')) ) 'range' => array( 'upper' => mktime(0, 0, 0, 12, 31, 2020), 'lower' => mktime(0,0,0,date('m'), date('d'), date('Y')) ) | Proc. |
wizards | array | [See section later for options] | Display |
Now follows some code listings as examples:
This is the typical configuration for a date field, like "starttime":
script_ended = 0;
function jumpToUrl(URL) {
document.location = URL;
}
'starttime' => array('exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.php:LGL.starttime',
'config' => array(
'type' => 'input',
'size' => '8',
'max' => '20',
'eval' => 'date',
'default' => '0'
)
),
In this example the field is for entering a username (from "fe_users"). A number of requirements are imposed onto the field, namely that it must be unique within the page where the record is stored, must be in lowercase and without spaces in it:
script_ended = 0;
function jumpToUrl(URL) {
document.location = URL;
}
'username' => array('label' => 'LLL:EXT:cms/locallang_tca.php:fe_users.username',
'config' => array(
'type' => 'input',
'size' => '20',
'max' => '50',
'eval' => 'nospace,lower,uniqueInPid,required'
)
),
This is just a very typical configuration which sets the size and a character limit to the field. In addition the input value is trimmed for surrounding whitespace which is a very good idea when you enter values into varchar fields.
script_ended = 0;
function jumpToUrl(URL) {
document.location = URL;
}
'name' => array('exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.php:LGL.name',
'config' => array(
'type' => 'input',
'size' => '40',
'eval' => 'trim',
'max' => '80'
)
),
Here the field is required to be filled in:
script_ended = 0;
function jumpToUrl(URL) {
document.location = URL;
}
'title' => array('label' => 'LLL:EXT:cms/locallang_tca.php:fe_groups.title',
'config' => array(
'type' => 'input',
'size' => '20',
'max' => '20',
'eval' => 'trim,required'
)
),
This field type generates a <textarea> field or inserts a RTE (Rich Text Editor).
Such a field looks like this:
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "text"] | Display / Proc. |
cols | integer | Abstract value for the width of the <textarea> field. To set the textarea to the full width of the form area, use the value 48. Default is 30. | Display |
rows | integer | The number of rows in the textarea. May be corrected for harmonization between browsers. Will also automatically be increased if the content in the field is found to be of a certain length, thus the field will automatically fit the content. Default is 5. Max value is 20. | Display |
wrap | ["off", "virtual"] | Determines the wrapping of the textarea field. There are two options:
Notice: If the string "nowrap" is found among options in the fields extra configuration from the "types" listing this will override the setting here to "off". Example: This configuration will create a textarea useful for entry of code lines since it will not wrap the lines: 'config' => array( 'type' => 'text', 'cols' => '40', 'rows' => '15', 'wrap' => 'off', ) | Display |
default | string | Default value | Display / Proc. |
eval | list of keywords | Configuration of field evaluation. Some of these evaluation keywords will trigger a JavaScript pre-evaluation in the form. Other evaluations will be performed in the backend. The evaluation functions will be executed in the list-order. Keywords:
| Display / Proc. |
is_in | string | If a user-defined evaluation is used for the field (see above, under key "eval"), then this values will be passed as argument to the user-defined evaluation function. | Display / Proc. |
wizards | array | [See section later for options] | Display |
Now follows some code listings as examples:
This is the typical configuration for a textarea field:
script_ended = 0;
function jumpToUrl(URL) {
document.location = URL;
}
'message' => array('label' => 'LLL:EXT:sys_note/locallang_tca.php:sys_note.message',
'config' => array(
'type' => 'text',
'cols' => '40',
'rows' => '15'
)
),
This type creates checkbox(es). Such elements might look like this:
You can also configure checkboxes to appear in an array:
You can have between 1 and 10 checkboxes and the field type in the database must be an integer. No matter how many checkboxes you have each check box will correspond to a single bit in the integer value. Even if there is only one checkbox (which in turn means that you should theoretically check the bit-0 of values from single-checkbox fields and not just whether it is true or false!).
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "check"] | Display / Proc. |
items | array | If set, this array will create an array of checkboxes instead of just a single "on/off" checkbox. Notice: You can have a maximum of 10 checkboxes in such an array and each element is represented by a single bit in the integer value which ultimately goes into the database. In this array each entry is itself an array where the first entry is the label (string or LLL reference) and the second entry is a blank value. The value sent to the database will be an integer where each bit represents the state of a checkbox in this array. Example: 'items' => array( array('Green tomatoes', ''), array('Red peppers', '') ), | Display |
cols | integer | How many columns the checkbox array are shown in. Range is 1-10, 1 being default. (Makes sense only if the 'array' key is defining a checkbox array) | Display |
showIfRTE | boolean | If set, this field will show only if the RTE editor is enabled (which includes correct browser version and user-rights altogether.) | Display |
default | integer | Setting the default value of the checkbox(es). Notice: Each bit corresponds to a check box (even if only one checkbox which maps to bit-0). | Display / Proc. |
itemsProcFunc | string (function reference) | PHP function which is called to fill / manipulate the array with elements. The function/method will have an array of parameters passed to it (where the item-array is passed by reference in the key 'items'). By modifying the array of items, you alter the list of items. For more information, see how user-functions are specified in the section about 'wizards' some pages below here. | Display |
Now follows some code listings as examples:
A plain vanilla checkbox:
'enforce_date' => array(
'exclude' => 0,
'label' => 'LLL:EXT:examples/locallang_db.xml:tx_examples_dummy.enforce_date',
'config' => array(
'type' => 'check',
)
),
This is an example of a checkbox array with two checkboxes in it. The first checkbox will have bit-0 and the second bit-1:
'l18n_cfg' => array(
'exclude' => 1,
'label' => 'LLL:EXT:cms/locallang_tca.xml:pages.l18n_cfg',
'config' => array(
'type' => 'check',
'items' => array(
array(
'LLL:EXT:cms/locallang_tca.xml:pages.l18n_cfg.I.1',
'',
),
array(
$GLOBALS['TYPO3_CONF_VARS']['FE']['hidePagesIfNotTranslatedByDefault'] ?
'LLL:EXT:cms/locallang_tca.xml:pages.l18n_cfg.I.2a' :
'LLL:EXT:cms/locallang_tca.xml:pages.l18n_cfg.I.2',
'',
),
),
),
),
If we wanted both checkboxes to checked by default, we would set the "default" property to '3' (since this contains both bit-0 and bit-1).
Radio buttons are seldom used, but sometimes they can be more attractive than their more popular sisters (selector boxes).
Here you see radio buttons in action for the "Filemounts" records:
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "radio"] | Display / Proc. |
items | array | Required. An array of the values which can be selected. Each entry is in itself an array where the first entry is the title (string or LLL reference) and the second entry is the value of the radio button. See example below. | Display |
default | mixed | Default value. | Display / Proc. |
itemsProcFunc | string (function reference) | PHP function which is called to fill / manipulate the array with elements. The function/method will have an array of parameters passed to it (where the item-array is passed by reference in the key 'items'). By modifying the array of items, you alter the list of items. For more information, see how user-functions are specified in the section about 'wizards' some pages below here. | Display |
An example of radio buttons configuration from "sys_filemounts" (see above):
'base' => array(
'label' => 'LLL:EXT:lang/locallang_tca.xml:sys_filemounts.base',
'config' => array(
'type' => 'radio',
'items' => array(
array('LLL:EXT:lang/locallang_tca.xml:sys_filemounts.base_absolute', 0),array('LLL:EXT:lang/locallang_tca.xml:sys_filemounts.base_relative', 1)),
'default' => 0
)
)
Selectors boxes are very common elements in forms. By the "select" type you can create selector boxes. In the most simple form this is a list of values among which you can chose only one. In that way it is similar to the "radio" type above.
It is also possible to configure more complex types where the values from from a look up in another database table and you can even have a type where more than one value can be selected in any given order you like.
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "select"] | Display / Proc. |
items | array | Contains the elements for the selector box unless the property "foreign_table" or "special" has been set in which case automated values are set in addition to any values listed in this array. Each element in this array is in itself an array where:
Example: A configuration could look like this: script_ended = 0; function jumpToUrl(URL) { document.location = URL; } 'type' => 'select', 'items' => array( array('English', ''), array('Danish', 'dk'), array('German', 'de'), ) A more complex example could be this (includes icons): 'type' => 'select', 'items' => array( array('LLL:EXT:cms/locallang_ttc.php:k1', 0, 'selicons/k1.gif'), array('LLL:EXT:cms/locallang_ttc.php:k2', 1, 'selicons/k2.gif'), array('LLL:EXT:cms/locallang_ttc.php:k3', 2, 'selicons/k3.gif'), ) | Display |
itemsProcFunc | string (function reference) | PHP function which is called to fill / manipulate the array with elements. The function/method will have an array of parameters passed to it (where the item-array is passed by reference in the key 'items'). By modifying the array of items, you alter the list of items. For more information, see how user-functions are specified in the section about 'wizards' some pages below here. | Display |
selicon_cols | integer (>0) | The number of rows in which to position the icons for the selector box. Default is to render as many columns as icons. | Display |
suppress_icons | string | Lets you disable display of icons. Can be nice to do if icons are coming from foreign database records and you don't want them. Set it to "IF_VALUE_FALSE" if you only want to see icons when a value (non-blank, non-zero) is selected. Otherwise no icons are shown. Set it to "ONLY_SELECTED" if you only want to see an icon for the selected item. Set to "1" (true) if you never want any icons. | Display |
iconsInOptionTags | boolean | If set, icons will appear in the <option> tags of the selector box. This feature seems only to work in Mozilla. | Display |
noIconsBelowSelect | boolean | Disables the rendering of the icons after the select even when icons for the <select>s <option> tags were supplied and iconsInOptionTags was set. | Display |
foreign_table | string (table name) | The item-array will be filled with records from the table defined here. The table must be configured in $TCA. See the other related options below. | Proc. / Display |
foreign_table_where | string (SQL WHERE clause) | The items from "foreign_table" are selected with this WHERE-clause. The table is joined with the "pages"-table and items are selected only from pages where the user has read access! (Not checking DB mount limitations!) Example: AND [foreign_table].pid=0 ORDER BY [foreign_table].sorting Markers: You can use markers in the WHERE clause:
The markers are preprocessed so that the value of CURRENT_PID and PAGE_TSCONFIG_ID are always integers (default is zero), PAGE_TSCONFIG_IDLIST will always be a comma-separated list of integers (default is zero) and PAGE_TSCONFIG_STR will be addslashes'ed before substitution (default is blank string). See example below "Simple selector box with TSconfig markers". | Proc. / Display |
foreign_table_prefix | string or LLL reference | Label prefix to the title of the records from the foreign-table. | Display |
foreign_table_loadIcons | boolean | If set, then the icons for the records of the foreign table are loaded and presented in the form. This depends on the 'selicon_field' of the foreign tables [ctrl] section being configured. | Display |
neg_foreign_table neg_foreign_table_where neg_foreign_table_prefix neg_foreign_table_loadIcons neg_foreign_table_imposeValueField | [mixed] | Four options corresponding to the 'foreign_table'-keys but records from this table will be referenced by negative uid-numbers (unless if MM is configured in which case it works like the group-type). 'neg_foreign_table' is active only if 'foreign_table' is defined also. | Display / Proc. |
fileFolder | string | Specifying a folder from where files are added to the item array. Specify the folder relative to the PATH_site, possibly using the prefix "EXT:" to point to an extension folder. Files from the folder is selected recursively to the level specified by "fileFolder_recursions" (see below) and only files of the extension defined by "fileFolder_extList" is selected (see below). Only the file reference relative to the "fileFolder" is stored. If the files are images (gif,png,jpg) they will be configured as icons (third parameter in items array). Example: 'config' => array ( 'type' => 'select', 'items' => array ( array('', 0), ), 'fileFolder' => 'EXT:cms/tslib/media/flags/', 'fileFolder_extList' => 'png,jpg,jpeg,gif', 'fileFolder_recursions' => 0, 'selicon_cols' => 8, 'size' => 1, 'minitems' => 0, 'maxitems' => 1, ) | Display / Proc |
fileFolder_extList | string | List of extensions to select. If blank, all files are selected. Specify list in lowercase. See "t3lib_div::getAllFilesAndFoldersInPath()" | Display / Proc |
fileFolder_recursions | integer | Depth of directory recursions. Default is 99. Specify in range from 0-99. 0 (zero) means no recursion into subdirectories. See "t3lib_div::getAllFilesAndFoldersInPath()" | Display / Proc |
allowNonIdValues | boolean | If "foreign_table" is enabled: If set, then values which are not integer ids will be allowed. May be needed if you use itemsProcFunc or just enter additional items in the items array to produce some string-value elements for the list. Notice: If you mix non-database relations with database relations like this, DO NOT use integers for values and DO NOT use "_" (underscore) in values either! Notice: Will not work if you also use "MM" relations! | Proc. |
default | string | Default value. If empty, the first element in the items array is selected. | Display / Proc. |
dontRemapTablesOnCopy | (See same feature for type="group", internal_type="db") Set it to the exact same value as "foreign_table" if you don't want values to be remapped on copy. | Proc. | |
rootLevel | boolean | If set, the "foreign_table_where" will be ignored and a "pid=0" will be added to the query to select only records from root level of the page tree. | Display |
MM | string (table name) | Means that the relation to the records of "foreign_table" / "neg_foreign_table" is done with a M-M relation with a third "join" table. That table has three columns as a minimum:
Example SQL #1 (most simple MM table): CREATE TABLE user_testmmrelations_one_rel_mm ( uid_local int(11) DEFAULT '0' NOT NULL, uid_foreign int(11) DEFAULT '0' NOT NULL, sorting int(11) DEFAULT '0' NOT NULL,
KEY uid_local (uid_local), KEY uid_foreign (uid_foreign) ); Example SQL #2 (Advanced with UID field, “ident” used with MM_match_fields and sorting_foreign for bidirectional MM relations): # # Table structure for table 'user_testmmrelations_two_rel_mm' # # CREATE TABLE user_testmmrelations_two_rel_mm ( uid int(11) NOT NULL auto_increment, uid_local int(11) DEFAULT '0' NOT NULL, uid_foreign int(11) DEFAULT '0' NOT NULL, tablenames varchar(30) DEFAULT '' NOT NULL, sorting int(11) DEFAULT '0' NOT NULL, sorting_foreign int(11) DEFAULT '0' NOT NULL, ident varchar(30) DEFAULT '' NOT NULL, KEY uid_local (uid_local), KEY uid_foreign (uid_foreign), PRIMARY KEY (uid), ); The field name of the config is not used for data-storage anymore but rather it's set to the number of records in the relation on each update, so the field should be an integer. Notice: Using MM relations you can ONLY store real relations for foreign tables in the list - no additional string values or non-record values. MM relations and flexforms MM relations has been tested to work with flexforms if not in a repeated element in a section. See example below. | Proc. |
MM_opposite_field | string (field name) | If you want to make a MM relation editable from the foreign side (bidirectional) of the relation as well, you need to set MM_opposite_field on the foreign side to the field name on the local side. E.g. if the field "companies.employees" is your local side and you want to make the same relation editable from the foreign side of the relation in a field called persons.employers, you would need to set the MM_opposite_field value of the TCA configuration of the persons.employers field to the string "employees". Notice: Bidirectional references only get registered once on the native side in sys_refindex | Proc. |
MM_match_fields | array | Array of field=>value pairs to both insert and match against when writing/reading MM relations | |
MM_insert_fields | array | Array of field=>value pairs to insert when writing new MM relations | |
MM_table_where | string (SQL WHERE) | Additional where clause used when reading MM relations. | |
MM_hasUidField | boolean | If the “multiple” feature is used with MM relations you MUST set this value to true and include a UID field! Otherwise sorting and removing relations will be buggy. | |
special | string (any of keywords) | This configures the selector box to fetch content from some predefined internal source. These are the possibilities:
As you might have guessed these options are used for backend user management and pretty worthless for most other purposes. | Display / Proc. |
size | integer | Height of the selector box in TCEforms. | Display |
autoSizeMax | integer | If set, then the height of multiple-item selector boxes (maxitems > 1) will automatically be adjusted to the number of selected elements, however never less than "size" and never larger than the integer value of "autoSizeMax" itself (takes precedence over "size"). So "autoSizeMax" is the maximum height the selector can ever reach. | Display |
selectedListStyle | string | If set, this will override the default style of the selector box with selected items (which is “width:200px”). Applies for when maxitems is > 1 | Display |
itemListStyle | string | If set, this will override the default style of the selector box with available items to select (which is “width:200px”). Applies for when maxitems is > 1 | Display |
renderMode | string (any of keywords) | (Only for maxitems > 1) Renders the list of multiple options as either a list of checkboxes or as a selector box with multiple choices. The data type is fully compatible with an ordinary multiple element list except that duplicate values cannot be represented for obvious reasons (option "multiple" does not work) and the order of values is fixed. Keywords are:
When renderMode is “checkbox” or “singlebox” all values selected by “foreign_table” settings will automatically have their icon part in the items array set to the record icon (unless overruled by “selicon_field” of that table). Notice: “maxitems” and “minitems” are not enforced in the browser for any of the render modes here! However they will be on the server. It is recommended to set “minitems” to zero and “maxitems” to a very large number exceeding the possible number of values you can select (for instance set it to 1000 or so). | |
treeConfig | (configuration options) | Configuration if the renderMode is set to "tree". Either childrenField or parentField has to be set - childrenField takes precedence. Sub-properties:
| |
multiple | boolean | Allows the same item more than once in a list. If used with bidirectional MM relations it must be set for both the native and foreign field configuration. Also, with MM relations in general you must use a UID field in the join table, see description for “MM” | Display / Proc. |
maxitems | integer > 0 | Maximum number of items in the selector box. (Default = 1) | Display / Proc |
minitems | integer > 0 | Minimum number of items in the selector box. (Default = 0) | Display |
wizards | array | [See section later for options] | Display |
disableNoMatchingValueElement | boolean | If set, then no element is inserted if the current value does not match any of the existing elements. A corresponding options is also found in Page TSconfig. | Display |
authMode | string keyword | Authorization mode for the selector box. Keywords are:
Notice: The authentication modes will work only with values that are statically present in the “items” configuration. Any values added from foreign tables, file folder or by user processing will not be configurable and the evaluation of such values is not guaranteed for! maxitems > 1 “authMode” works also for selector boxes with maxitems > 1. In this case the list of values is traversed and each value is evaluated. Any disallowed values will be removed. If all submitted values turns out to be removed the result will be that the field is not written – basically leaving the old value. For maxitems <=1 (single value) this means that a non-allowed value is just not written. For multiple values (maxitems >1) it depends on whether any elements are left in the list after evaluation of each value. | Display / Proc |
authMode_enforce | string keyword | Various additional enforcing options for authMode. Keywords are:
| Display / Proc |
exclusiveKeys | string (list of) | List of keys that exclude any other keys in a select box where multiple items could be selected. "Show at any login" of "fe_groups" (tables "pages" and "tt_content") is an example where such a configuration is used. | |
localizeReferencesAtParentLocalization | boolean | Defines whether referenced records should be localized when the current record gets localized (mostly used in Inline Relational Record Editing) | Proc. |
Here follow some code listings as examples:
This is the most simple selector box you can get. It contains a static set of options you can select from:
'tx_examples_options' => array (
'exclude' => 0,
'label' => 'LLL:EXT:examples/locallang_db.xml:fe_users.tx_examples_options',
'config' => array (
'type' => 'select',
'items' => array (
array('LLL:EXT:examples/locallang_db.xml:fe_users.tx_examples_options.I.0', '1'),array('LLL:EXT:examples/locallang_db.xml:fe_users.tx_examples_options.I.1', '2'),array('LLL:EXT:examples/locallang_db.xml:fe_users.tx_examples_options.I.2', '--div--'),array('LLL:EXT:examples/locallang_db.xml:fe_users.tx_examples_options.I.3', '3'),),
'size' => 1,
'maxitems' => 1,
)
),
In the configuration the elements are configured by the "items" array. Each entry in the array contains pairs of label/value. Notice the third entry of the “items” array. It defines a divider. This value cannot be selected. It only helps to divide the list of options with a label indicating a new section.
This example shows the use of markers inside the "foreign_table_where" clause and how the corresponding TSconfig must be set up.
In the TCA definition of the "haiku" table ("examples" extension) there is a simple select field to create a reference to a page in the "pages" table:
'reference_page' => array(
'label' => 'LLL:EXT:examples/locallang_db.xml:tx_examples_haiku.reference_page',
'config' => array(
'type' => 'select',
'foreign_table' => 'pages',
'foreign_table_where' => "AND pages.title LIKE '%###PAGE_TSCONFIG_STR###%'",
'size' => 1,
'minitems' => 0,
'maxitems' => 1
),
),
Without any TSconfig, the selector will display a full list of pages:
Let's add the following bit of Tsconfig to the page containing our "haiku" record:
TCEFORM.tx_examples_haiku.reference_page.PAGE_TSCONFIG_STR = image
The list of pages that we can select from is now reduced to:
The user group selector is based on the fe_groups table. It appears as a multiple selector:
The corresponding TCA configuration:
'fe_group' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.fe_group',
'config' => array(
'type' => 'select',
'size' => 7,
'maxitems' => 20,
'items' => array(
array(
'LLL:EXT:lang/locallang_general.xml:LGL.hide_at_login',
-1,
),
array(
'LLL:EXT:lang/locallang_general.xml:LGL.any_login',
-2,
),
array(
'LLL:EXT:lang/locallang_general.xml:LGL.usergroups',
'--div--',
),
),
'exclusiveKeys' => '-1,-2',
'foreign_table' => 'fe_groups',
'foreign_table_where' => 'ORDER BY fe_groups.title',
),
),
The value stored in the database will be a comma list of uid numbers of the records selected.
The interesting point of this example is that it shows that static values can be mixed with values fetched from a database table.
In this case the selector box looks up languages in a static table from an extension "static_info_tables":
The configuration looks like this (taken from the sys_lang table):
'static_lang_isocode' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_tca.php:sys_language.isocode',
'displayCond' => 'EXT:static_info_tables:LOADED:true',
'config' => array(
'type' => 'select',
'items' => array(
array('', 0),),
'foreign_table' => 'static_languages',
'foreign_table_where' => 'AND static_languages.pid=0 ORDER BY static_languages.lg_name_en',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
)
),
Notice how a condition is set that this box should only be displayed if the extension it relies on exists! This is very important since otherwise the table will not be in the database and we will get SQL errors.
This example shows how you can add icons to the selection choice very easily. Each icon is associated with an option in the selector box and clicking the icon will automatically select the option in the selector box and more the black arrow:
The configuration looks like this.
'imageorient' => array(
'label' => 'LLL:EXT:cms/locallang_ttc.xml:imageorient',
'config' => array(
'type' => 'select',
'items' => array(
array(
'LLL:EXT:cms/locallang_ttc.xml:imageorient.I.0',
0,
'selicons/above_center.gif',
),
array(
'LLL:EXT:cms/locallang_ttc.xml:imageorient.I.1',
1,
'selicons/above_right.gif',
),
array(
'LLL:EXT:cms/locallang_ttc.xml:imageorient.I.2',
2,
'selicons/above_left.gif',
),
...
array(
'LLL:EXT:cms/locallang_ttc.xml:imageorient.I.10',
26,
'selicons/intext_left_nowrap.gif',
),
),
'selicon_cols' => 6,
'default' => '0',
'iconsInOptionTags' => 1,
),
),
Notice how each label/value pair contains an icon reference on the third position. Towards the bottom the layout of the icons is defined as being arranged in 6 columns.
The following configuration change:
t3lib_div::loadTCA('pages');$tempConfiguration = array(
'type' => 'select',
'foreign_table' => 'pages',
'size' => 10,
'renderMode' => 'tree',
'treeConfig' => array(
'expandAll' => true,
'parentField' => 'pid',
'appearance' => array(
'showHeader' => TRUE,
),
),
);
$TCA['pages']['columns']['storage_pid']['config'] = array_merge(
$TCA['pages']['columns']['storage_pid']['config'],
$tempConfiguration
);
will transform the General Record Storage Page selector into:
This example shows how wizards can be added to a selector box. The three typical wizards for a selector box is edit, add and list items. This enables the user to create new items in the look up table while being right at the selector box where he want to select them:
The configuration is rather long and looks like this (notice, that wizards are not exclusively available for selector boxes!):
'file_mountpoints' => array(
'label' => 'LLL:EXT:lang/locallang_tca.xml:be_users.options_file_mounts',
'config' => array(
'type' => 'select',
'foreign_table' => 'sys_filemounts',
'foreign_table_where' => ' AND sys_filemounts.pid=0 ORDER BY sys_filemounts.title',
'size' => '3',
'maxitems' => '10',
'autoSizeMax' => 10,
'iconsInOptionTags' => 1,
'wizards' => array(
'_PADDING' => 1,
'_VERTICAL' => 1,
'edit' => array(
'type' => 'popup',
'title' => 'LLL:EXT:lang/locallang_tca.xml:file_mountpoints_edit_title',
'script' => 'wizard_edit.php',
'icon' => 'edit2.gif',
'popup_onlyOpenIfSelected' => 1,
'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
),
'add' => array(
'type' => 'script',
'title' => 'LLL:EXT:lang/locallang_tca.xml:file_mountpoints_add_title',
'icon' => 'add.gif',
'params' => array(
'table' => 'sys_filemounts',
'pid' => '0',
'setValue' => 'prepend'
),
'script' => 'wizard_add.php',
),
'list' => array(
'type' => 'script',
'title' => 'LLL:EXT:lang/locallang_tca.xml:file_mountpoints_list_title',
'icon' => 'list.gif',
'params' => array(
'table' => 'sys_filemounts',
'pid' => '0',
),
'script' => 'wizard_list.php',
)
)
)
),
The part with the wizards is highlighted in bold. See the wizard section in this document for more information.
Notice the configuration of "autoSizeMax". This value will make the height of the selector boxes adjust themselves automatically depending on the content in them. The result is as follows:
For a table, “user_testmmrelations_two”, we have a field “rel” with configured with MM relations:
"rel" => Array (
"exclude" => 1,
"label" => "Relations:",
"config" => Array (
"type" => "select",
"foreign_table" => "user_testmmrelations_one",
"foreign_table_where" => "ORDER BY user_testmmrelations_one.uid",
"size" => 10,
"minitems" => 0,
"maxitems" => 10,
"MM" => "user_testmmrelations_two_rel_mm",
'MM_match_fields' => array('ident'=>'table_two'))
),
The MM table is called “user_testmmrelations_two_rel_mm”, and the field “ident” is used to match on with the word “table_two”. Doing this enables us to use the same MM table for other fields using other keywords for the “ident” field.
In another table “user_testmmrelations_one” a field called “rel2” constitutes the foreign side of the bidirectional relation:
"rel2" => Array (
"label" => "Foreign relation:",
"config" => Array (
"type" => "select",
"foreign_table" => "user_testmmrelations_two",
"foreign_table_where" => "ORDER BY user_testmmrelations_two.uid",
"size" => 10,
"minitems" => 0,
"maxitems" => 10,
"MM" => "user_testmmrelations_two_rel_mm",
'MM_match_fields' => array('ident'=>'table_two'),"MM_opposite_field" => "rel"
)
),
Notice how in both cases “ foreign_table” points to the table name of the other. Also they use the exact same set up except in the foreign side case above the field “MM_opposite_field” is set to “rel” - the name of the field in table “user_testmmrelations_two"!
The SQL looks like:
#
# Table structure for table 'user_testmmrelations_two_rel_mm'
#
#
CREATE TABLE user_testmmrelations_two_rel_mm (
uid int(11) NOT NULL auto_increment,
uid_local int(11) DEFAULT '0' NOT NULL,
uid_foreign int(11) DEFAULT '0' NOT NULL,
tablenames varchar(30) DEFAULT '' NOT NULL,
sorting int(11) DEFAULT '0' NOT NULL,
sorting_foreign int(11) DEFAULT '0' NOT NULL,
ident varchar(30) DEFAULT '' NOT NULL,
KEY uid_local (uid_local),
KEY uid_foreign (uid_foreign),
PRIMARY KEY (uid),
);
In the backend the form could look like:
So, from a record in table two (native) there are two relations made to records in table one.
If we look at one of the records from table one we see the relation made from “TWO (1)”:
In the database it looks like this:
MM relations can be used with flexforms. Here is an example:
The flexform field configuration looks like this:
<rel1>
<TCEforms>
<label>Relation:</label>
<config>
<type>group</type>
<internal_type>db</internal_type>
<allowed>user_testmmrelations_three</allowed>
<size>10</size>
<minitems>0</minitems>
<maxitems>10</maxitems>
<MM>user_testmmrelations_two_rel_mm</MM>
<MM_match_fields>
<ident>table_one_flex</ident>
</MM_match_fields>
<multiple>1</multiple>
<MM_hasUidField>1</MM_hasUidField>
</config>
</TCEforms>
</rel1>
As you can see the same element (titled “3-3 (UID-3)”) is selected twice (the “<multiple>” flag has been set) – and as a consequence <MM_hasUidField>1</MM_hasUidField> is set as well. In fact this configuration is sharing the MM table with another field (see the previous example) so the configuration
<MM_match_fields>
<ident>table_one_flex</ident>
</MM_match_fields>
makes sure all MM relations for this flexform field is marked with the string “table_one_flex”.
In the database the entry looks like:
(The first two entries belong to that other field, see previous example).
Of course you can specify a dedicated join table to the flexform instead of sharing it.
What will not work in flexforms is if you put MM relation fields in elements that can get repeated, like in sections:
Here I have added three sections and tried to add entries to each. However, when saved the two last entries are loaded for all of them. The result of the save was:
The reason is that the fields all use the same uid (that of the record) to find the MM records. This could work when MM fields were used outside sections of flexform fields which could only occur one time per record, but here it's not possible.
The group element in TYPO3 makes it possible to create references to records from multiple tables in the system. This is especially useful (compared to the "select" type) when records are scattered over the page tree and requires the Element Browser to be selected. In this example, Content Element records are attached (taken from the "Insert records" content element):
The "group" element is also the element you can use to bind files to records in TYPO3. In this case image files:
One thing to notice about such a field is that the files that are referenced actually get moved into an internal file folder for TYPO3! It does not create references to the files' original positions!
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "group"] | Display / Proc. |
internal_type | string | Required! Configures the internal type of the "group" type of element. There are four possible options to choose from:
The default value is none of them - you must specify one of the values correctly! | Display / Proc. |
allowed | string (list of) | For the "file" internal type (Optional): A lowercase comma list of file extensions that are permitted. E.g. 'jpg,gif,txt'. Also see 'disallowed'. For the "db" internal type (Required!): A comma list of tables from $TCA. For example the value could be "pages,be_users". Value from these tables are always the 'uid' field. First table in list is understood as the default table, if a table-name is not prepended to the value. If the value is '*' then all tables are allowed (in this case you should set "prepend_tname" so all tables are prepended with their table name for sure). Notice, if the field is the foreign side of a bidirectional MM relation, only the first table is used and that must be the table of the records on the native side of the relation. | Proc. / Display |
disallowed | string (list of) | [internal_type = file ONLY] Default value is '*' which means that anything file-extension which is not allowed is denied. If you set this value (to for example "php,php3") AND the "allowed" key is an empty string all extensions are permitted except ".php" and ".php3" files (works like the [BE][fileExtensions] config option). In other words:
| Proc. / Display |
MM | string (table name) | Defines MM relation table to use. Means that the relation to the files/db is done with a M-M relation through a third "join" table. A MM-table must have these four columns:
see ['columns'][fieldname]['config'] / TYPE: "select" => MM for additional features. | Proc. |
MM_opposite_field | string (field name) | see ['columns'][fieldname]['config'] / TYPE: "select" => MM_opposite_field | Proc. |
MM_match_fields | array | see ['columns'][fieldname]['config'] / TYPE: "select" => MM_match_fields | |
MM_insert_fields | array | see ['columns'][fieldname]['config'] / TYPE: "select" => MM_insert_fields | |
MM_table_where | string (SQL WHERE) | see ['columns'][fieldname]['config'] / TYPE: "select" => MM_table_where | |
MM_hasUidField | boolean | see ['columns'][fieldname]['config'] / TYPE: "select" => MM_hasUidField | |
max_size | integer | [internal_type = file ONLY] Files: Maximum file size allowed in KB | Proc. |
uploadfolder | string | [internal_type = file ONLY] Path to folder under PATH_site in which the files are stored. Example: 'uploads' or 'uploads/pictures' Notice: TYPO3 does NOT create a reference to the file in its original position! It makes a copy of the file into this folder and from that moment that file is not supposed to be manipulated from outside. Being in the upload folder means that files are understood as a part of the database content and should be managed by TYPO3 only. Warning: do NOT add a trailing slash (/) to the upload folder otherwise the full path stored in the references will contain a double slash (e.g. “uploads/pictures//stuff.png”). | Proc. |
prepend_tname | boolean | [internal_type = db ONLY] Will prepend the table name to the stored relations (so instead of storing "23" you will store e.g. "tt_content_23"). | Proc. |
dontRemapTablesOnCopy | string (list of tables) | [internal_type = db ONLY] A list of tables which should not be remapped to the new element uids if the field holds elements that are copied in the session. | Proc. |
show_thumbs | boolean | Show thumbnails for the field in the TCEform | Display |
size | integer | Height of the selector box in TCEforms. | Display |
autoSizeMax | integer | If set, then the height of element listing selector box will automatically be adjusted to the number of selected elements, however never less than "size" and never larger than the integer value of "autoSizeMax" itself (takes precedence over "size"). So "autoSizeMax" is the maximum height the selector can ever reach. | Display |
selectedListStyle | string | If set, this will override the default style of element selector box (which is “width:200px”). | Display |
multiple | boolean | Allows the same item more than once in a list. If used with bidirectional MM relations it must be set for both the native and foreign field configuration. Also, with MM relations in general you must use a UID field in the join table, see description for “MM” | Display / Proc. |
maxitems | integer > 0 | Maximum number of items in the selector box. (Default = 1) | Display / Proc? |
minitems | integer > 0 | Minimum number of items in the selector box. (Default = 0) | Display / Proc? |
disable_controls | string | Disables sub-controls inside "group" control. Comma-separated list of values. Possible values are: browser (disables browse button for list control), list (disables list and browse button, but not delete button), upload (disables upload control) and delete (disables the delete button). See example image below. NOTE: if you use the delete button when the list is disabled, all entries in the list will be deleted.
| Display / Proc. |
wizards | array | [See section later for options] | Display |
The "Insert records" content element can be used to reference records from the "tt_content" table (and possibly others, like "tt_news" in the screenshot below):
The corresponding TCA code:
'records' => array(
'label' => 'LLL:EXT:cms/locallang_ttc.xml:records',
'config' => array(
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tt_content',
'size' => '5',
'maxitems' => '200',
'minitems' => '0',
'show_thumbs' => '1',
'wizards' => array(
'suggest' => array(
'type' => 'suggest',
),
),
),
),
Note in particular how the "internal_type" of the group field is set to "db". Then the allowed tables is defined as "tt_content" (Content Elements table). This could very well be a list of tables which means you can mix references as you like!
The limit is set to a maximum of 200 references and thumbnails should be displayed, if possible. Finally a suggest wizard is added.
In this case it wouldn't have made sense to use a "select" type field since the situation implies that records might be found all over the system in a table which could potentially carry thousands of entries. In such a case the right thing to do is to use the "group" field so you have the Element Browser available for selector of the records.
You will often see "group" type fields used when a reference to another page is required. This makes sense since pages can hardly be presented effectively in a big selector box and thus the Element Browser that follows the "group" type fields is useful. An example is the "General Record Storage page" reference:
The configuration looks like:
'storage_pid' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_tca.php:storage_pid',
'config' => array(
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages',
'size' => '1',
'maxitems' => '1',
'minitems' => '0',
'show_thumbs' => '1',
'wizards' => array(
'suggest' => array(
'type' => 'suggest',
),
),
),
),
Notice how "maxitems" is used to ensure that only one relation is created despite the ability of the "group" type field to create multiple references.
Attaching files to a database record is also achieved with group-type fields:
Notice how all the image names end with "_0" and some number. This happens because all files attached to records through a group-type field are copied to a location defined by the "uploadfolder" setting in the configuration (see below). When a file is referenced several times, it is also copied several times. TYPO3 automatically appends a number so that each reference is unique.
'image' => array(
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.images',
'config' => array(
'type' => 'group',
'internal_type' => 'file',
'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
'max_size' => $GLOBALS['TYPO3_CONF_VARS']['BE']['maxFileSize'],
'uploadfolder' => 'uploads/pics',
'show_thumbs' => '1',
'size' => '3',
'maxitems' => '200',
'minitems' => '0',
'autoSizeMax' => 40,
),
),
Notice how the "group" type is defined to contain files. Next the list of allowed file extensions are defined (here, taking the default list of image types for TYPO3). A maximum size (in kilobytes) for files is also defined. The "uploadfolder" property indicates that all files will be copied to the "/uploads/pics" folder. Notice that this path is relative to the PATH_site of TYPO3, one directory below PATH_typo3.
Since the "group" element allows to store references to multiple elements we might want to look at how these references are stored internally.
There are two main methods for this:
Stored in a comma list
Stored with a join table (MM relation)
The default and most wide spread method is the comma list.
In the comma list the token "," is used to separate the values. In addition the pipe sign "|" is used to separate value from label value when delivered to the interface. Therefore these tokens are not allowed in reference values, not even if the MM method is used.
When storing references as a comma list the values are simply stored one after another, separated by a comma in between (with no space around!). The database field type is normally a varchar, text or blob field in order to handle this.
From the examples above the four Content Elements will be stored as "26,45,49,1" which is the UID values of the records. The images will be stored as their filenames in a list like "DSC_7102_background.jpg,DSC_7181.jpg,DSC_7102_background_01.jpg".
Since "db" references can be stored for multiple tables the rule is that uid numbers without a table name prefixed are implicitly from the first table in the allowed table list! Thus the list "26,45,49,1" is implicitly understood as "tt_content_26,tt_content_45,tt_content_49,tt_content_1". That would be equally good for storage, but by default the "default" table name is not prefixed in the stored string. As an example, lets say you wanted a relation to a Content Element and a Page in the same list. That would look like "tt_content_26,pages_123" or alternatively "26,pages_123" where "26" implicitly points to a "tt_content" record given that the list of allowed tables were "tt_content,pages".
Using the MM method you have to create a new database table which you configure with the key "MM". The table must contain a field, "uid_local" which contains the reference to the uid of the record that contains the list of elements (the one you are editing). The "uid_foreign" field contains the uid of the reference record you are referring to. In addition a "tablename" and "sorting" field exists if there are references to more than one table.
Lets take the examples from before and see how they would be stored in an MM table:
uid_local | uid_foreign | tablename | sorting |
|---|---|---|---|
[uid of the record you are editing] | 26 | tt_content | 1 |
[uid of the record you are editing] | 45 | tt_content | 2 |
[uid of the record you are editing] | 49 | tt_content | 3 |
[uid of the record you are editing] | 1 | tt_content | 4 |
Or for "tt_content_26,pages_123":
uid_local | uid_foreign | tablename | sorting |
|---|---|---|---|
[uid of the record you are editing] | 26 | tt_content | 1 |
[uid of the record you are editing] | 123 | pages | 2 |
Or for "DSC_7102_background.jpg,DSC_7181.jpg,DSC_7102_background_01.jpg":
uid_local | uid_foreign | tablename | sorting |
|---|---|---|---|
[uid of the record you are editing] | DSC_7102_background.jpg | N/A | 1 |
[uid of the record you are editing] | DSC_7181.jpg | N/A | 2 |
[uid of the record you are editing] | DSC_7102_background_01.jpg | N/A | 3 |
In t3lib/ the class "t3lib_loaddbgroup" is designed to transform the stored reference list values into an array where all uids are paired with the right table name. Also, this class will automatically retrieve the list of MM relations. In other words, it provides an API for getting the references from "group" elements into a PHP array regardless of storage method.
Regardless of storage method, the reference list has to be "enriched" with proper title values when given to TCEforms for rendering. In particular this is important for database records. Passing the list "26,45,49,1" will not give TCEforms a chance to render the titles of the records.
The t3lib/ class "t3lib_transferdata" is doing such transformations (among other things) and this is how the transformation happens:
Int. type: | In Database: | When given to TCEforms: |
|---|---|---|
"db" | 26,45,49,1 | tt_content_26|%20adfs%20asdf%20asdf%20,tt_content_45|This%20is%20a%20test%20%28copy%203%29,tt_content_49|%5B...%5D,tt_content_1|%5B...%5D |
"file" | DSC_7102_background.jpg,DSC_7181.jpg,DSC_7102_background_01.jpg | DSC_7102_background.jpg|DSC_7102_background.jpg,DSC_7181.jpg|DSC_7181.jpg,DSC_7102_background_01.jpg|DSC_7102_background_01.jpg |
The syntax is:
[ref. value]|[ref. label rawurlencoded],[ref. value]|[ref. label rawurlencoded],....
Values are transferred back to the database as a comma separated list of values without the labels but if labels are in the value they are automatically removed.
Alternatively you can also submit each value as an item in an array; TCEmain will detect an array of values and implode it internally to a comma list. (This is used for the "select" type, in renderMode "singlebox" and "checkbox").
When a new file is attached to a record the TCE will detect the new file based on whether it has a path prefixed or not. New files are copied into the upload folder that has been configured and the final value list going into the database will contain the new filename of the copy.
If images are removed from the list that is detected by simply comparing the original file list with the one submitted. Any files not listed anymore are deleted.
Examples:
Current DB value | Submitted data from TCEforms | New DB value | Processing done |
|---|---|---|---|
first.jpg,second.jpg | first.jpg,/www/typo3/fileadmin/newfile.jpg,second.jpg | first.jpg,newfile_01.jpg,second.jpg | /www/typo3/fileadmin/newfile.jpg was copied to "/uploads/[some-dir]/newfile_01.jpg". The filename was appended with "_01" because another file with the name "newfile.jpg" already existed in the location. |
first.jpg,second.jpg | first.jpg | first.jpg | "/uploads/[some-dir]/second.jpg" was deleted from the location. |
This type will just show the value of the field in the backend. The field is not editable.
Key | Datatype | Description |
|---|---|---|
type | string | [Must be set to "none"] |
pass_content | boolean | If set, then content from the field is directly outputted in the <div> section. Otherwise the content will be passed through htmlspecialchars() and possibly nl2br() if there is configuration for rows. Be careful to set this flag since it allows HTML from the field to be outputted on the page, thereby creating the possibility of XSS security holes. |
rows | integer | If this value is greater than 1 the display of the non-editable content will be shown in a <div> area trying to simulate the rows/columns known from a "text" type element. |
cols | integer | See "rows" and "size" |
fixedRows | boolean | If this is set the <div> element will not automatically try to fit the content length but rather respect the size selected by the value of the "rows" key. |
size | integer | If rows is less than one, the "cols" value is used to set the width of the field and if "cols" is not found, then "size" is used to set the width. The measurements corresponds to those of "input" and "text" type fields. |
Can be saved/updated through TCE but the value is not evaluated in any way and the field has no rendering in the TCEforms.
You can use this to send values directly to the database fields without any automatic evaluation. But still the update gets logged and the history/undo function will work with such values.
Since there is no rendering mode for this field type it is specifically fitted for direct API usage with the TCEmain class.
Key | Datatype | Description |
|---|---|---|
type | string | [Must be set to "passthrough"] |
Allows you to render a whole form field by a user function or class method.
Key | Datatype | Description |
|---|---|---|
type | string | [Must be set to "user"] |
userFunc | string | Function or method reference. If you want to call a function, just enter the function name. The function name must be prefixed "user_" or "tx_". If you want to call a method in a class, enter "[classname]->[methodname]". The class name must be prefixed "user_" or "tx_". Two arguments will be passed to the function/method: The first argument is an array (passed by reference) which contains the current information about the current field being rendered. The second argument is a reference to the parent object (an instance of the t3lib_TCEforms class). The array with the current information will contain any parameters declared with the "parameters" property described below. Notice: The class must be registered with the TYPO3 autoloader. It's also possible to include it manually, but using the autoloader is the preferred way. |
parameters | array | Array that will be passed as is to the userFunc as the "parameters" key of the first argument received by the user function. See example below. |
noTableWrapping | boolean | If set, then the output from the user function will not be wrapped in the usual table - you will have to do that yourself. |
This field is rendered by custom PHP code:
The configuration in TCA is as simple as this:
'tx_examples_special' => array (
'exclude' => 0,
'label' => 'LLL:EXT:examples/locallang_db.xml:fe_users.tx_examples_special',
'config' => array (
'type' => 'user',
'size' => '30',
'userFunc' => 'EXT:examples/class.tx_examples_tca.php:tx_examples_tca-> specialField',
'parameters' => array(
'color' => 'blue'
)
)
),
This is how the corresponding PHP class looks like:
class tx_examples_tca {function specialField($PA, $fObj) {$color = (isset($PA['parameters']['color'])) ? $PA['parameters']['color']:'red';
$formField = '<div style="padding: 5px; background-color: ' . $color . ';">';$formField .= '<input type="text" name="' . $PA['itemFormElName'] . '"';
$formField .= ' value="' . htmlspecialchars($PA['itemFormElValue']) . '"';
$formField .= ' onchange="' . htmlspecialchars(implode('', $PA['fieldChangeFunc'])) . '"';$formField .= $PA['onFocus'];
$formField .= ' /></div>';
return $formField;
}
}
This is not the place to dig into more details about user-defined forms. By this example you can start yourself up but you will have to figure out by yourself what options are available in the $PA array and how to use them.
Note in particular how the "parameters" array declared in the TCA configuration can be retrieved as part of the first argument ($PA) received by the method invoked.
Rendering a FlexForm element - essentially this consists in a hierarchically organized set of fields which will have their values saved into a single field in the database, stored as XML.
Key | Datatype | Description |
|---|---|---|
type | string | [Must be set to "flex"] |
ds_pointerField | string | Field name(s) in the record which point to the field where the key for “ds” is found. Up to two field names can be specified comma separated. |
ds | array | Data Structure(s) defined in an array. Each key is a value that can be pointed to by “ds_pointerField”. Default key is “default” which is what you should use if you do not have a “ds_pointerField” value of course. If you specified more than one ds_pointerField, the keys in this “ds” array should contain comma-separated value pairs where the asterisk * matches all values (see the example below). If you don't need to switch for the second ds_pointerField, it's also possible to use only the first ds_pointerField's value as a key in the "ds" array without necessarily suffixing it with ",*" for a catch-all on the second ds_pointerField. For each value in the array there are two options:
Example with XML directly entered: 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'list_type', 'ds' => array( 'default' => ' <T3DataStructure> <ROOT> <type>array</type> <el> <xmlTitle> <TCEforms> <label>The Title:</label> <config> <type>input</type> <size>48</size> </config> </TCEforms> </xmlTitle> </el> </ROOT> </T3DataStructure> ', ) ) Example with XML in external file: (File reference is relative) 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'list_type', 'ds' => array( 'default' => 'FILE:EXT:mininews/flexform_ds.xml', ) ) Example using two ds_pointerFields (as used for tt_content.pi_flexform since TYPO3 4.2.0): 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'list_type,CType', 'ds' => array( 'default' => 'FILE:...', 'tt_address_pi1,list' => 'FILE:EXT:tt_address/pi1/flexform.xml', // DS for list_type=tt_address_pi1 and CType=list '*,table' => 'FILE:EXT:css_styled_content/flexform_ds.xml', // DS for CType=table, no matter which list_type value 'tx_myext_pi1' => 'FILE:EXT:myext/flexform.xml', // DS for list_type=tx_myext_pi1 without specifying a CType at all ) ) |
ds_tableField | string | Contains the value “[table]:[field name]” from which to fetch Data Structure XML. “ds_pointerField” is in this case the pointer which should contain the uid of a record from that table. This is used by TemplaVoila extension for instance where a field in the tt_content table points to a TemplaVoila Data Structure record: 'tx_templavoila_flex' => array( 'exclude' => 1, 'label' => '...', 'displayCond' => 'FIELD:tx_templavoila_ds:REQ:true', 'config' => array( 'type' => 'flex', 'ds_pointerField' => 'tx_templavoila_ds', 'ds_tableField' => 'tx_templavoila_datastructure:dataprot', ) ), |
ds_pointerField_searchParent | string | Used to search for Data Structure recursively back in the table assuming that the table is a tree table. This value points to the “pid” field. See “templavoila” for example - uses this for the Page Template. |
ds_pointerField_searchParent_subField | string | Points to a field in the “rootline” which may contain a pointer to the “next-level” template. See “templavoila” for example - uses this for the Page Template. |
Basically the configuration for a FlexForm field is all about pointing to the Data Structure which will contain form rendering information in the application specific tag “<TCEforms>”.
For general information about the backbone of a Data Structure, please see the <T3DataStructure> chapter in the Data Formats section.
FlexForms create a form-in-a-form. The content coming from this form is still stored in the associated database field - but as an XML structure (stored by t3lib_div::array2xml())!
The “TCA” information needed to generate the FlexForm fields are found inside a <T3DataStructure> XML document. When you configure a FlexForm field in a Data Structure (DS) you can use basically all column types documented here for TCA. The limitations are:
“unique” and “uniqueInPid” evaluation is not available
You cannot nest FlexForm configurations inside of FlexForms.
Charset follows that of the current backend (since TYPO3 4.7, the only accepted character encoding is UTF-8. When storing FlexForm information in external files, make sure that they are using UTF-8 too).
For FlexForms the DS is extended with a tag, “<TCEforms>” which define all settings specific to the FlexForms usage.
Also a few meta tag features are used.
Sometimes it may be necessary to reload flexform if content of the field in the flexform is changed. This is accomplished by adding “<onChange>reload</onChange>” inside <TCEforms>. A typical example for that is a field that defines operational modes for an extension. When the mode changes, a flexform may need to show a new set of fields. By combining the <onChange> tag for mode fields with <displayCond> tag for other fields, it is possible to create truly dynamic flexforms.
Notice that changing the mode does not delete hidden field values of the flexform. Always use the “mode” field to determine which parameters to use.
The tables below document the extension elements:
“Array” Elements:
Element | Description | Child elements |
|---|---|---|
<meta> | Can contain application specific meta settings. For FlexForms this means a definition of how languages are handled in the form. | <langChildren> <langDisable> |
<[application tag]> | In this case the application tag is “<TCEforms>” | A direct reflection of a ['columns']['field name']['config'] PHP array configuring a field in TCA. As XML this is expressed by array2xml()'s output. See example below. |
<ROOT><TCEforms> | For <ROOT> elements in the DS you can add application specific information about the sheet that the <ROOT> element represents. | <sheetTitle> <sheetDescription> <sheetShortDescr> |
“Value” Elements:
Element | Format | Description |
|---|---|---|
<langDisable> | boolean, 0/1 | If set, then handling of localizations is disabled. Otherwise FlexForms will allow editing of additional languages than the default according to “sys_languages” table contents. The language you can select from is the language configured in “sys_languages” but they must have ISO country codes set - see example below. |
<langChildren> | boolean, 0/1 | If set, then localizations are bound to the default values 1-1 (“value” level). Otherwise localizations are handled on “structure level” |
<sheetTitle> | string or LLL reference | Specifies the title of the sheet. |
<sheetDescription> | string or LLL reference | Specifies a description for the sheet shown in the flexform. |
<sheetShortDescr> | string or LLL reference | Specifies a short description of the sheet used in the tab-menu. |
FlexForms always resolve sheet definitions in a Data Structure. If only one sheet is defined that must be the “sDEF” sheet (default). In that case no tab-menu for sheets will appear (see examples below).
When saving FlexForm elements the content is stored as XML using t3lib_div::array2xml() to convert the internal PHP array to XML format. The structure is as follows:
“Array” Elements:
Element | Description | Child elements |
|---|---|---|
<T3FlexForms> | Document tag | <meta> <data> |
<meta> | Meta data for the content. For instance information about which sheet is active etc. | <currentSheetId> <currentLangId> |
<data> | Contains the data; sheets, language sections, field and values | <sheet> |
<sheet> | Contains the data for each sheet in the form. If there are no sheets, the default sheet “<sDEF>” is always used. | <sDEF> <s_[sheet keys]> |
<sDEF> <[sheet keys]> | For each sheet it contains elements for each language. If <meta><langChildren> is false then all languages are stored on this level, otherwise only the <lDEF> tag is used. | <lDEF> <l[ISO language code]> |
<lDEF> <[language keys]> | For each language the fields in the form will be available on this level. | <[field name]> |
<[field name]> | For each field name there is at least one element with the value, <vDEF>. If <meta><langChildren> is true then there will be a <v*> tag for each language holding localized values. | <vDEF> <v[ISO language code]> |
<currentLangId> | Numerical array of language ISO codes + “DEF” for default which are currently displayed for editing. | <n[0-x]> |
“Value” Elements:
Element | Format | Description |
|---|---|---|
<vDEF> <v[ISO language code]> | string | Content of the field in default or localized versions |
<currentSheetId> | string | Points to the currently shown sheet in the DS. |
The extension “examples” provides some sample FlexForms. The “simple FlexForm” plugin provides a very basic configuration with just a select-type field to choose a page from the “pages” table.
The DS used to render this field is found in the file “flexform_ds1.xml” inside the “examples” extension. Notice the <TCEforms> tags:
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:examples/locallang_db.xml: examples.pi_flexform.sheetGeneral</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<pageSelector>
<TCEforms>
<label>LLL:EXT:examples/locallang_db.xml: examples.pi_flexform.pageSelector</label>
<config>
<type>select</type>
<items type="array">
<numIndex index="0" type="array">
<numIndex index="0">LLL:EXT:examples/locallang_db.xml:examples.pi_flexform.choosePage</numIndex>
<numIndex index="1">0</numIndex>
</numIndex>
</items>
<foreign_table>pages</foreign_table>
<foreign_table_where>ORDER BY title</foreign_table_where>
<minitems>0</minitems>
<maxitems>1</maxitems>
</config>
</TCEforms>
</pageSelector>
</el>
</ROOT>
</sDEF>
</sheets>
</T3DataStructure>
It's clear that the contents of <TCEforms> is a direct reflection of the field configurations we normally set up in the $TCA array.
The Data Structure for this FlexForm is loaded in the “pi_flexform” field of the “tt_content” table by adding the following to the ext_tables.php file of the “examples” extension:
$TCA['tt_content']['types']['list']['subtypes_addlist'][$_EXTKEY . '_pi1'] = 'pi_flexform';
t3lib_extMgm::addPiFlexFormValue($_EXTKEY . '_pi1', 'FILE:EXT:examples/flexform_ds1.xml');
In the first line the tt_content field “pi_flexform” is added to the display of fields when the Plugin type is selected and set to “examples_pi1”. In the second line the DS xml file is configured to be the source of the FlexForm DS used.
If we browse the definition for the “pi_flexform” field in “tt_content” using the Admin > Configuration module, we can see the following:
As you can see there are quite a few extensions that have added pointers to their Data Structures. Towards the bottom we can find the one we have just been looking at.
In this example we create a FlexForm field with two “sheets”. Each sheet can contain a separate FlexForm structure. We build it up on top of the previous example, so the first sheet still has a select-type field related to the “pages” table. In the second sheet, we add a simple input field and a text field.
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:examples/locallang_db.xml: examples.pi_flexform.sheetGeneral</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<pageSelector>
<TCEforms>
<label>LLL:EXT:examples/locallang_db.xml: examples.pi_flexform.pageSelector</label>
<config>
<type>select</type>
<items type="array">
<numIndex index="0" type="array">
<numIndex index="0">LLL:EXT:examples/locallang_db.xml:examples.pi_flexform.choosePage</numIndex>
<numIndex index="1">0</numIndex>
</numIndex>
</items>
<foreign_table>pages</foreign_table>
<foreign_table_where>ORDER BY title</foreign_table_where>
<minitems>0</minitems>
<maxitems>1</maxitems>
</config>
</TCEforms>
</pageSelector>
</el>
</ROOT>
</sDEF>
<s_Message>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT: examples/locallang_db.xml:examples.pi_flexform.s_Message</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<header>
<TCEforms>
<label>LLL:EXT: examples/locallang_db.xml:examples.pi_flexform.header</label>
<config>
<type>input</type>
<size>30</size>
</config>
</TCEforms>
</header>
<message>
<TCEforms>
<label>LLL:EXT: examples/locallang_db.xml:examples.pi_flexform.message</label>
<config>
<type>text</type>
<cols>40</cols>
<rows>5</rows>
</config>
</TCEforms>
</message>
</el>
</ROOT>
</s_Message>
</sheets>
</T3DataStructure>
The part that is different from the first Data Structure is highlighted in bold. The result from this configuration is a form which looks like this:
This looks very much like the first example, but notice the second tab. Clicking on “Message”, we can access the second sheet which shows some other fields:
If you look at the XML stored in the database field “pi_flexform” this is how it looks:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="pageSelector">
<value index="vDEF">9</value>
</field>
</language>
</sheet>
<sheet index="s_Message">
<language index="lDEF">
<field index="header">
<value index="vDEF">My Header</value>
</field>
<field index="message">
<value index="vDEF">And my message.
On several lines.</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
Notice how the data of the two sheets are separated (sheet names highlighted in bold above).
Creating a RTE in FlexForms is done by adding “defaultExtras” content to the <TCEforms> tag:
<TCEforms>
<config>
<type>text</type>
<cols>48</cols>
<rows>5</rows>
</config>
<label>Subtitle</label>
<defaultExtras>richtext[*]:rte_transform[mode=ts_css]</defaultExtras>
</TCEforms>
FlexForms allows you to handle translations of content in two ways. But before you can enable those features you have to install the extension “static_info_tables” which contains country names and ISO-language codes which are the ones by which FlexForms stores localized content:
Then you must configure languages in the database:
And finally, you have to make sure that each of these languages points to the right ISO code:
By default, you will not see any changes. Indeed if you look at the example XML displayed above, you will notice the following line, at the top, in the “meta” section:
<langDisable>1</langDisable>
This means that translation of the FlexForm is disabled. In the example above, the FlexForm is part of a content element. That content element can still be translated as usual. What we're going to look at below is how a FlexForm field may end up containing its own translations. There are two methods for this.
The first localization method just requires to change the “langDisable” flag mentioned above to 0:
<langDisable>0</langDisable>
This means that translations are now allowed for that FlexForm. This is how it looks like:
The data XML in the data base looks like this:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="pageSelector">
<value index="vDEF">9</value>
</field>
</language>
<language index="lDE">
<field index="pageSelector">
<value index="vDEF"></value>
</field>
</language>
<language index="lEN">
<field index="pageSelector">
<value index="vDEF"></value>
</field>
</language>
</sheet>
<sheet index="s_Message">
<language index="lDEF">
<field index="header">
<value index="vDEF">My Header</value>
</field>
<field index="message">
<value index="vDEF">And my message.
On several lines.</value>
</field>
</language>
<language index="lDE">
<field index="header">
<value index="vDEF">Hallo!</value>
</field>
<field index="message">
<value index="vDEF">Das is auf Deutsch!</value>
</field>
</language>
<language index="lEN">
<field index="header">
<value index="vDEF"></value>
</field>
<field index="message">
<value index="vDEF"></value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
Note how each language is stored separately at a level above the “field” level. Each language tag carries an attribute identifying the language like “lDE” or “lEN”.
In the first method of localization each language can potentially contain a differently structured data set. This is possible because as soon as a DS defines sections with array objects inside the number of objects can be individual!
The second method of localization handles each language on the value level instead, thus requiring a translation for each and every field in the default language! You enable this by setting the “langChildren” tag to “1” in the “meta” section:
<meta>
<langDisable>0</langDisable>
<langChildren>1</langChildren>
</meta>
The editing form will now look like this:
You can see how all translation fields for the “Header” are grouped together with the default header. Likewise for the “Message” field.
The difference is also seen in the <T3FlexForms> content:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3FlexForms>
<data>
<sheet index="sDEF">
<language index="lDEF">
<field index="pageSelector">
<value index="vDEF"></value>
<value index="vDE"></value>
<value index="vEN"></value>
<value index="vDE.vDEFbase"></value>
<value index="vEN.vDEFbase"></value>
</field>
</language>
</sheet>
<sheet index="s_Message">
<language index="lDEF">
<field index="header">
<value index="vDEF">My header</value>
<value index="vDE">Hallo!</value>
<value index="vEN"></value>
<value index="vDE.vDEFbase">My header</value>
<value index="vEN.vDEFbase">My header</value>
</field>
<field index="message">
<value index="vDEF">And my message.
On several lines.</value>
<value index="vDE">Das is auf Deutsch!</value>
<value index="vEN"></value>
<value index="vDE.vDEFbase">And my message.
On several lines.</value>
<value index="vEN.vDEFbase">And my message.
On several lines.</value>
</field>
</language>
</sheet>
</data>
</T3FlexForms>
In this case, there's only on “language” tag per sheet and all values are repeated with a language index attribute to tell them apart.
The additional “value” tags with an index attribute like “vDE.vDEFbase” are used to store the previous value that the field contained, so that a translation diff view can be displayed:
NOTICE: The two localization methods are NOT compatible! You cannot suddenly change from the one method to the other without having to do some conversion of the data format. That is obvious when you look at how the two methods also require different data structures underneath!
Inline-Relational-Record-Editing (IRRE) offers a way of directly editing parent-child-relations in one backend view. New child records are created using AJAX calls to prevent a reload of the complete backend view. This type was first integrated in TYPO3 4.1.
Please note that IRRE does not fully work in conjunction with versioning. Only 1:n relationships are supported in workspaces (since TYPO3 4.5).
Note
TCAdefaults.<table>.pid = <page id> can be used to define the pid of new child records. Thus, it's possible to have special storage folders on a per-table-basis.
Key | Datatype | Description | Scope |
|---|---|---|---|
type | string | [Must be set to "inline"] | Display / Proc. |
foreign_table | string (table name) | [Must be set, there is no type “inline” without a foreign table]The table name of the child records is defined here. The table must be configured in $TCA. See the other related options below. | Display / Proc. |
appearance | array | Has information about the appearance of child-records, namely:
| Display |
behaviour | array | Has information about the behavior of child-records, namely:
| Display / Proc. |
customControls | array | (Since TYPO3 4.7) Numerical array containing definitions of custom header controls for IRRE fields. This makes it possible to create special controls by calling user-defined functions (userFuncs). Each item in the array item must be an array itself, with at least on key "userFunc" pointing to the user function to call. The userFunc string is defined as usual in TYPO3 as [file-reference":"]["&"]class/function["->"method-name], e.g. EXT:myext/class.tx_myext_myclass:tx_myext_myclass->myUserFuncMethod For more details, see the implementation in "t3lib/class.t3lib_tceforms_inline.php" and search for "customControls". | Display |
foreign_field | string | The foreign_field is the field of the child record pointing to the parent record. This defines where to store the uid of the parent record. | Display / Proc. |
foreign_label | string | If set, it overrides the label set in $TCA[<foreign_table>]['ctrl']['label'] for the inline-view. | Display / Proc. |
foreign_selector | string | A selector is used to show all possible child records that could be used to create a relation with the parent record. It will be rendered as a multi-select-box. On clicking on an item inside the selector a new relation is created.The foreign_selector points to a field of the foreign_table that is responsible for providing a selector-box – this field on the foreign_table usually has the type “select” and also has a “foreign_table” defined. | Display / Proc. |
foreign_sortby | string | Define a field on the child record (or on the intermediate table) that stores the manual sorting information. It is possible to have a different sorting, depending from which side of the relation we look at parent or child. | Display / Proc. |
foreign_default_sortby | string | If a field name for foreign_sortby is defined, then this is ignored. Otherwise this is used as the “ORDER BY” statement to sort the records in the table when listed. | Display |
foreign_table_field | string | The foreign_table_field is the field of the child record pointing to the parent record. This defines where to store the table name of the parent record. On setting this configuration key together with foreign_field, the child record knows what its parent record is – so the child record could also be used on other parent tables.This issue is also known as “weak entity”.Do not confuse with foreign_table or foreign_field. It has its own behavior. | Display / Proc. |
foreign_unique | string | Field which must be unique for all children of a parent record. Example: Say you have two tables, products, your parent table, and prices, your child table (products) can have multiple prices. The prices table has a field called customer_group, which is a selector box. Now you want to be able to specify prices for each customer group when you edit a product, but of course you don't want to specify contradicting prices for one product (i.e. two different prices for the same customer_group). That's why you would set foreign_unique to the field name “customer_group”, to prevent that two prices for the same customer group can be created for one product. | Display / Proc. |
MM | string (table name) | Means that the relation to the records of "foreign_table" is done with a M-M relation with a third "join" table. That table typically has three columns:
The field which is configured as “inline” is not used for data-storage any more but rather it's set to the number of records in the relation on each update, so the field should be an integer. Notice: Using MM relations you can ONLY store real relations for foreign tables in the list - no additional string values or non-record values (so no attributes). | Proc. |
foreign_table_match | array | (Since TYPO3 4.7) Array of field-value pairs to both insert and match against when writing/reading IRRE relations. Using the match fields, it is possible to re-use the same child table in more than one field of the parent table by using a match field with different values for each of the use cases. Example Imagine you have a parent table called "company" and a child table called "persons". Now, if you want the company table to have two fields of type "inline", one called "employees" and one called "customers", both containing "persons". Then you could use a (hidden) field called "role" on the child (person) table to keep them apart. The match TCA configuration of the parent table would then look like this: $TCA['ty_myext_company'] = array ( ... 'columns' => array ( ... 'employees' => array ( 'config' => array ( 'type' => 'inline', 'foreign_table' => 'ty_myext_person', 'foreign_field' => 'company', 'foreign_match_fields' => array( 'role' => 'employee', ), ), ), 'customers' => array ( 'config' => array ( 'type' => 'inline', 'foreign_table' => 'ty_myext_person', 'foreign_field' => 'company', 'foreign_match_fields' => array( 'role' => 'customer', ), ), ), ), ... ); | Proc. |
foreign_types | array | (Since TYPO3 4.7) This can be used to control which fields of the child table are displayed. You can override the "showitem", etc. settings of the child table here, by supplying an override for the "types" array of that table. For details on how the types array is constructed, see the chapter "['types'][key] section" later in this manual. | Display |
size | integer | Height of the selector box in TCEforms. | Display |
autoSizeMax | integer | If set, then the height of multiple-item selector boxes (maxitem > 1) will automatically be adjusted to the number of selected elements, however never less than "size" and never larger than the integer value of "autoSizeMax" itself (takes precedence over "size"). So "autoSizeMax" is the maximum height the selector can ever reach. | Display |
maxitems | integer > 0 | Maximum number of items in the selector box. Defaults to 100000. Note that this is different from types "select" and "group" which default to 1. | Display / Proc |
minitems | integer > 0 | Minimum number of items in the selector box. (Default = 0) | Display |
symmetric_field | string | This works like foreign_field, but in case of using bidirectional symmetric relations. symmetric_field defines in which field on the foreign_table the uid of the “other” parent is stored. | Display / Proc. |
symmetric_label | string | If set, it overrides the label set in $TCA[<foreign_table>]['ctrl']['label'] for the inline-view and only if looking to a symmetric relation from the “other” side. | Display / Proc. |
symmetric_sortby | string | This works like foreign_sortby, but in case of using bidirectional symmetric relations. Each side of a symmetric relation could have its own sorting, so symmetric_sortby defines a field on the foreign_table where the sorting of the “other” side is stored. | Display / Proc. |
This combines companies with persons (employees) using a comma separated list, so no “foreign_field” is used here.
$TCA['company'] = array(
'ctrl' => ...,
'interface' => ...,
'feInterface' => ...,
'columns' => array(
'hidden' => ...,
'employees' => array(
'exclude' => 1,
'label' => 'LLL:EXT:myextension/locallang_db.xml:company.employees',
'config' => array(
'type' => 'inline',
'foreign_table' => 'person',
'maxitems' => 10,
'appearance' => array(
'collapseAll' => 1,
'expandSingle' => 1,
),
),
),
),
'types' => ...
'palettes' => ...
);
This example combines companies with persons (employees) using an intermediate table. It is also possible to add attributes to every relation – in this example, an attribute “jobtype” on the “person_company” table is defined. It is also possible to look at the relation from both sides (parent and child).
$TCA['person'] = array( 'columns' => array( 'employers' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person.employers', 'config' => array( 'type' => 'inline', 'foreign_table' => 'person_company', 'foreign_field' => 'person', 'foreign_label' => 'company', ), ), ),);
$TCA['company'] = array( 'columns' => array( 'employees' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:company.employees', 'config' => array( 'type' => 'inline', 'foreign_table' => 'person_company', 'foreign_field' => 'company', 'foreign_label' => 'person', ), ), ),);
$TCA['person_company'] = array( 'columns' => array( 'person' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.person', 'config' => array( 'type' => 'select', 'foreign_table' => 'person', 'size' => 1, 'minitems' => 0, 'maxitems' => 1, ), ), 'company' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.company', 'config' => array( 'type' => 'select', 'foreign_table' => 'company', 'size' => 1, 'minitems' => 0, 'maxitems' => 1, ), ), 'jobtype' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person_company.jobtype', 'config' => array( 'type' => 'select', 'items' => array( array('Project Manager (PM)', '0'), array('Chief Executive Officer (CEO)', '1'), array('Chief Technology Officer (CTO)', '2'), ), 'size' => 1, 'maxitems' => 1, ), ), ),);
This example combines two persons with each other – imagine they are married. One person on the first side is the husband, and one person on the other side is the wife (or generally “spouse” in the example below). Symmetric relations combine object of the same with each other and it does not depend, from which side someone is looking to the relation – so the husband knows it's wife and the wife also know it's husband.
Sorting could be individually defined for each of the both sides (perhaps this should not be applied to a wife-husband-relationship in real life).
$TCA['person'] = array( 'columns' => array( 'employers' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person.employers', 'config' => array( 'type' => 'inline', 'foreign_table' => 'person_symmetric', 'foreign_field' => 'person', 'foreign_sortby' => 'sorting_person', 'foreign_label' => 'spouse', 'symmetric_field' => 'spouse', 'symmetric_sortby' => 'sorting_spouse', 'symmetric_label' => 'person', ), ), ),);
$TCA['person_symmetric'] = array( 'columns' => array( 'person' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.person', 'config' => array( 'type' => 'select', 'foreign_table' => 'person', 'size' => 1, 'minitems' => 0, 'maxitems' => 1, ), ), 'spouse' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.spouse', 'config' => array( 'type' => 'select', 'foreign_table' => 'person', 'size' => 1, 'minitems' => 0, 'maxitems' => 1, ), ), 'someattribute' => array( 'label' => 'LLL:EXT:myextension/locallang_db.xml:person_symmetric.someattribute', 'config' => array( 'type' => 'input', ), ), 'sorting_person' => array( 'config' => array( 'type' => 'passthrough', ), ), 'sorting_spouse' => array( 'config' => array( 'type' => 'passthrough', ), ), ),);
You have to add at least one entry in the "types"-configuration before any of the configured fields from the ['columns'] section will show up in TCEforms.
Let's take the internal notes (sys_note) as an example. The input form looks like this:
It corresponds to the following “types” configuration:
'types' => array(
'0' => array('showitem' => 'category;;;;2-2-2, author, email, personal, subject;;;;3-3-3, message'))
The key "showitem" lists the order in which to define the fields: "category, author, email, personal, subject, message".
The power of the "types"-configuration becomes clear when you want the form composition of a record to depend on a value from the record. Let's look at the “dummy” table from the “examples” extension. The “ctrl” section of its TCA looks like this:
$TCA['tx_examples_dummy'] = array(
'ctrl' => array(
'title' => 'LLL:EXT:examples/locallang_db.xml:tx_examples_dummy',
'label' => 'title',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'type'=> 'record_type',
'default_sortby' => 'ORDER BY title',
'delete' => 'deleted',
'enablecolumns' => array(
'disabled' => 'hidden',
),
'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY) . 'tca.php',
'iconfile' => t3lib_extMgm::extRelPath($_EXTKEY) . 'icon_tx_examples_dummy.gif',
)
);
The line in bold indicates that the field called “record_type” will used to indicate the “type” of any given record of the table. Let's look at how this field is defined:
'record_type' => array(
'exclude' => 0,
'label' => 'LLL:EXT:examples/locallang_db.xml:tx_examples_dummy.record_type',
'config' => array(
'type' => 'select',
'items' => array(
array('LLL:EXT:examples/locallang_db.xml:tx_examples_dummy.record_type.0', 0),array('LLL:EXT:examples/locallang_db.xml:tx_examples_dummy.record_type.1', 1),array('LLL:EXT:examples/locallang_db.xml:tx_examples_dummy.record_type.2', 2),)
)
),
There's nothing unusual here. It's a pretty straightforward select field, with three options. Finally, in the “types” section, we defined what fields should appear and in what order for every value of the “type” field:
'types' => array(
'0' => array('showitem' => 'hidden, record_type, title, some_date '),'1' => array('showitem' => 'record_type, title '),'2' => array('showitem' => 'title, some_date, hidden, record_type '),),
The result if the following display when type “Normal” is chosen:
Changing to type “Short” reloads the form and displays the following:
And finally, type “Weird” also shows all fields, but in a different order:
If no "type" field is defined the type value will default to "0" (zero). If the type value (coming from a field or being zero by default) does not point to a defined index in the "types"-configuration, the configuration for key "1" will be used by default.
Notice: You must not show the same field more than once in the editing form. If you do, the field will not detect the value properly.
Key | Datatype | Description |
|---|---|---|
showitem | string (list of field configuration sets) | Required. Configuration of the displayed order of fields in TCEforms. The whole string is divided by tokens according to a - unfortunately - complex ruleset.
Notice: Instead of a real field name you can insert "--div--" and you should have a divider line shown. However this is not rendered by default. If you set the dividers2tabs option (see ['ctrl'] section), each –div-- will define a new tab. Furthermore using a value "newline" for Part 3, will start a newline with this tab. Example: 'types' => array( '0' => array('showitem' => 'hidden;;;;1-1-1, title;;;;2-2-2, poem, filename;;;;3-3-3, season;;;;4-4-4, weirdness, color, --div--;LLL:EXT:examples/locallang_db.xml:tx_examples_haiku.images, image1, image2, image3, image4, image5'), ), Another special field name, '--palette--', will insert a link to a palette (of course you need to specify a palette and title then...) |
subtype_value_field | string (field name) | Field name, which holds a value being a key in the 'subtypes_excludelist' array. This is used to specify a secondary level of 'types' - basically hiding certain fields of those found in the types-configuration, based on the value of another field in the row. Example (from sysext/cms/tbl_tt_content.php): 'subtype_value_field' => 'list_type', 'subtypes_excludelist' => array( '3' => 'layout', '2' => 'layout', '5' => 'layout', ... '21' => 'layout' ), |
subtypes_excludelist | array | See "subtype_value_field". Syntax: “[field value]” => “[comma-separated list of fields (from the main types-config) which are excluded]” |
subtypes_addlist | array | A list of fields to add when the "subtype_value_field" matches a key in this array. See "subtype_value_field". Syntax: “[value]” => “[ comma-separated list of fields which are added] Notice: that any transformation configuration used by TCE will NOT work because that configuration is visible for the TCEforms class only during the drawing of fields. In other words any configuration in this list of fields will work for display only.” |
bitmask_value_field | string (field name) | Field name, which holds a value being the integer (bit-mask) for the 'bitmask_excludelist_bits' array. It works much like 'subtype_value_field' but excludes fields based on whether a bit from the value field is set or not. See 'bitmask_excludelist_bits'; [+/-] indicates whether the bit [bit-number] is set or not. Example: 'bitmask_value_field' => 'active', 'bitmask_excludelist_bits' => array( '-0' => 'tmpl_a_subpart_marker,tmpl_a_description', '-1' => 'tmpl_b_subpart_marker,tmpl_b_description', '-2' => 'tmpl_c_subpart_marker,tmpl_c_description' ) |
bitmask_excludelist_bits | array | See "bitmask_value_field" “[+/-][bit-number]” => “[comma-separated list of fields (from the main types-config) excluded]” |
"Palettes" represent a way to move less frequently used form fields out of sight. Palettes are groups of field which are associated with another field in the main form. When this field is activated the palette fields are displayed. In the backend, “palettes” are known as "secondary options".
Let's add a palette to the example from the previous section. The palette itself is defined like this:
'palettes' => array(
'1' => array('showitem' => 'enforce_date'),),
Now we change the “types” configuration to link the palette to the “some_date” field:
'0' => array('showitem' => 'hidden, record_type, title, some_date;;1 '),When a palette exists, an icon appears next to the relevant field:
Clicking on this icon, the palette is revealed:
Palette display can be activated permanently by checking the “Show secondary options” box at the bottom of any forms screen:
Note
This checkbox may be hidden per TSConfig, so it may not appear all the time.
Key | Datatype | Description |
|---|---|---|
showitem | string (list of field names) | Required. Configuration of the displayed order of fields in the palette. Remember that a field name must not appear in more than one palette and not more than one time!. E.g. 'hidden,starttime,endtime' |
canNotCollapse | boolean | If set, then this palette is not allowed to 'collapse' in the TCEforms-display. This basically means that if "Show secondary options" is not on, this palette is still displayed in the main form and not linked with an icon. |
isHiddenPalette | boolean | (Since TYPO3 4.7) If set, then this palette will never be shown, but the fields of the palette are technically rendered as hidden elements in the TCEForm. This is sometimes useful when you want to set a field's value by JavaScript from another user-defined field. You can also use it along with the IRRE (TCA type "inline") foreign_selector feature if you don't want the relation field to be displayed (it must be technically present and rendered though, that's why you should put it to a hidden palette in that case). |
All fields in a palette are shown on a single line. Since TYPO3 4.3, it is possible to place them on several lines by using the --linebreak-- keyword.
















































