Login / Status
developer.Resource
Home . Documentation . Document Library . Tutorials
Sponsors
hosted by punkt.deTYPO3 and Open Source MagazineAOE Media

1.5. $TCA: The [columns] section

This section configures how Typo3 handles each field; which kind of form element it should be rendered as and which further properties are assigned. This configuration should definitely be consistent with the actual database field receiving the value. Of course, you cannot expect an ordinary input field accepting textual content to cleanly submit it into an integer database field! However it does not generate a warning - just the wrong value.

The INPUT type:

            // Title is set up as an ordinary input-field, one line.        "title" => Array (            "label" => "Image title:|Billedtitel:|Bildtitel:",            "config" => Array (                "type" => "input",                "size" => "40",                "max" => "80",                "eval" => "trim"            )        ),

This renders a traditional INPUT element. In this case with the relative size of “40”. The real value is compensated depending on browser so the fields appear equally wide in various operating systems and browsers.

The eval value “trim” signifies that the value is stripped from whitespace in both ends before it's submitted. This is required with varchar database fields as MySQL strips whitespace anyway.

You can configure some more options, in particular you can configure the field to evaluate a date and/or time input. This is the case with the photodate field which is configured like this:

            // Photo date        "photodate" => Array (            "label" => "Date:|Dato:|Datum:",            "config" => Array (                "type" => "input",                "size" => "7",                "max" => "20",                "eval" => "date",                "checkbox" => "0",                "default" => "0"            )        ),

The TEXT type:

        "description" => Array (            "label" => "Image description:|Billedbeskrivelse:|Bildbeschreibung:",            "config" => Array (                "type" => "text",                "cols" => "48",                    "rows" => "5"            )        ),

This renders a textarea field. The columns are once again a relative messure conpensated based on browser and client OS.

You can also configure the field to turn wrapping OFF or use the Rich Text Editor!

The CHECK type:

        "hidden" => Array (            "label" => $LANG_GENERAL_LABELS["disable"],            "config" => Array (                "type" => "check"            )        ),

This renders a checkbox. Notice how the labels from the field is cleverly taken from the LANG_GENERAL_LABELS array which holds a lot of generally used label-names translated into all the system languages.

You can also configure checkboxes to present a whole array of checkboxes (up to 10) where each represents a bit in the integerfield which must receive the value. Here's an example from tables.php (tt_content.text_properties):

        "text_properties" => Array (            "exclude" => 1,            "label" => "Properties:",            "config" => Array (                "type" => "check",                "items" => Array (                        Array("Bold", ""),                    Array("Italics", ""),                    Array("Underline", ""),                    Array("Uppercase", "")                ),                "cols" => 4            )        ),

This is rendered like this in the forms:

The GROUP type / file:

        "images" => Array (            "label" => $LANG_GENERAL_LABELS["image"],            "config" => Array (                "type" => "group",                "internal_type" => "file",                "allowed" => "gif,jpg,jpeg,png",        // Allowed extensions                "max_size" => "1000",            // Max 1000 kb pr. image                "uploadfolder" => "uploads/photomarathon",                "show_thumbs" => "1",        // Yes, show thumbnails in backend                "size" => "3",                // The image list box is 3 items high                "maxitems" => "6",            // Max 6 images pr. record!                "minitems" => "0"            // Min 0 images.            )        ),

This configures the field to receive images. As you can probably spot, you can configure 1) which file types, 2) their maximun kb-size, 3) where they should be put and 4) the maximum and/or minimum number of files required.

The TCE (Typo Core Engine, t3lib_tcemain class) takes care of all the file handling (although you must follow certain guidelines when you're submitting files.)

In the backend interface it looks like this:

... and adding images is so easy using the Element Browser:

The filenames are (by default) stored as a comma separated list of filenames, typically in a BLOB field.

The content of the “user_photomarathon.image” field is

372046.jpg,p020_f.jpg

The GROUP type / db:

        "fe_cruser_id" => Array (            "label" => "Front End Owner:|Website-bruger ejer:|Frontend Besitzer:",            "config" => Array (                "type" => "group",                "internal_type" => "db",                "allowed" => "fe_users",                "size" => "1",                "maxitems" => "1",                "minitems" => "0",                "show_thumbs" => "1"            )        )

This element is a sister to the GROUP/file type from above. But instead of containing references to filenames, it contains references to records. You can even configure the field to mix records from various tables if you wish.

In the Photo Marathon example this configuration holds the reference to the user, who created the record:

... and likewise you can browse for records with the Element Browser:

Looking at the actual content of the field, this is what we see:

2

A number, pointing to the fe_user record. In this case the field can contain only this one record, because the database field is an integer.

Looking at another example, the tt_content.records field from tables.php is configured like this:

  "records" => Array (      "label" => "Items:",      "config" => Array (          "type" => "group",          "internal_type" => "db",           "allowed" => 
                “tt_content,tt_address,tt_links,tt_board,tt_guest,tt_calender,tt_products,tt_news",          "size" => "5",          "maxitems" => "200",          "minitems" => "0",          "show_thumbs" => "1"      )  ),

... and on the page “/Intro/Another site.../More lists a.../Records/” the element “Various records inserted” looks like this:

The content of the tt_content.record field in this case looks like:

tt_calender_7,tt_news_1,tt_products_3,tt_address_5,tt_calender_3,tt_products_2,tt_board_1,tt_products_5,tt_guest_2,tt_address_1,tt_address_2,tt_rating_1

This is uid-numbers prepended with the tablenames.

Making real MM relations

The above examples shows how to make MM (many-to-many) relations in a straight forward manner - a list of comma separated values - but also a database designwise discouraged way; You should use an intermedia table instead if you want to do it “right”.

About relations, 1-M (one-to-many) and M-1 (many-to-one) signifies a relation where one record is related to many other records. For instance the pid - pages.uid relation ship is a such; A record can belong to one and only one page. The Photo Marathon fe_cruser_id field is also such a relation; It's an integer field point to one and only one owner user - however this user may have other user_photomarathon records pointing to him (which makes it a “many” relation).

M-M relations are like with the content element type “Insert records” where we wish any number of content elements to be able to link to any - maybe even the same element twice! - record from other tables regardless of existing relations.

The newly added sys_dmail_group table actually represents such a relationship in the field sys_dmail_group.static_list. This field is actually just a dummy placeholder - the real relations to tt_address and fe_users elements are done through an intermediate table, sys_dmail_group_mm. This is the field configuration (taken from tables.php):

        "static_list" => Array (            "label" => "Recipients:",            "config" => Array (                "type" => "group",                "internal_type" => "db",                    "allowed" => "tt_address,fe_users",                    "MM" => "sys_dmail_group_mm",                "size" => "20",                "maxitems" => "100000",                "minitems" => "0",                "show_thumbs" => "1"            )        ),

The table “sys_dmail_group_mm” looks like this:

CREATE TABLE sys_dmail_group_mm (
   uid_local int(11) unsigned DEFAULT '0' NOT NULL,
   uid_foreign int(11) unsigned DEFAULT '0' NOT NULL,
   tablenames varchar(30) NOT NULL,
   sorting int(11) unsigned DEFAULT '0' NOT NULL,
   KEY uid_local (uid_local),
   KEY uid_foreign (uid_foreign)
);

  • uid_local holds the uid number of the sys_dmail_group record

  • uid_foreign holds the uid number of either the tt_address or fe_users record, which is determined by...

  • ... the tablenames field which is either set to “tt_address” or “fe_users”

  • Finally sorting is used to denote the order of the records.

Whether you use real relations (for a more correct data structure than the lists) or the comma-list principle, the proces of adding and removing records is totally the same in the backend interface! It's all managed inside the t3lib_tcemain class! In fact the submission of the order of records is always done as a list.

The table, tt_news, also features such a relationship, but with only one table, tt_news, involved which eliminates the user of the “tablename” field in the relation table:

CREATE TABLE tt_news_related_mm (
   uid_local int(11) unsigned DEFAULT '0' NOT NULL,
   uid_foreign int(11) unsigned DEFAULT '0' NOT NULL,
   sorting int(11) unsigned DEFAULT '0' NOT NULL,
   KEY uid_local (uid_local),
   KEY uid_foreign (uid_foreign)
);

The TCA config looks like this for tt_news.related:

        "related" => Array (            "exclude" => 1,                "label" => "Related news:",            "config" => Array (                "type" => "group",                "internal_type" => "db",                    "allowed" => "tt_news",                    "MM" => "tt_news_related_mm",                "size" => "5",                "maxitems" => "200",                "minitems" => "0",                "show_thumbs" => "1"            )        ),

Finally you can also use an intermediate table with files, so each file is registered with a record where the uid_foreign is a varchar with the filename rather than an integer pointing to the foreign record. This is the example structure found in t3lib/install/example_MM_relationTables.sql:

CREATE TABLE tt_content_media_mm (
  uid_local int(11) unsigned NOT NULL default '0',
  uid_foreign varchar(60) NOT NULL default '',
  sorting int(11) unsigned NOT NULL default '0',
  KEY uid_local (uid_local),
  KEY uid_foreign (uid_foreign)
);

The “exclude” fields

Did you notice in tables.php that certain fields has a flag set, “exclude=1”? For instance the tt_news.related field as shown above:

        "related" => Array (            "exclude" => 1,                "label" => "Related news:",             ....

When this option is set, the field is not available for non-admin users by default. Rather it must be specifically enabled by selecting the field in the list of “Allowed excludefields” in the setup of backend usergroups:

The default view; The “Links”  field is the last in the form:

Then adding the “News: Related news” to the list of “Allowed excludefields”...

... and then the user (being a member of that group) has instant access to the field:

Notice: It's better to define a field “exclude” if you're in doubt! If you specify that option later, you'll have to edit alll your usergroups which should keep access. Setting the value by default will on the other hand allow you to just remove the flag if you suddenly realize that there is generally no need to restrict certain users from accessing this field!