.. You may want to use the usual include line. Uncomment and adjust the path. .. include:: ../Includes.txt .. role:: underline ========================================== User TCA types and bidirectional MM tables ========================================== :Author: Kasper Skårhøj :Created: 2002-11-01T00:32:00 :Changed: 2007-03-07T16:25:08 :Author: René Fritz :Email: r.fritz@colorcube.de :Info 3: :Info 4: .. _User-TCA-types-and-bidirectional-MM-tables: User TCA types and bidirectional MM tables ========================================== Extension Key: **mmforeign** Copyright 2006-2007, René Fritz, This document is published under the Open Content License available from http://www.opencontent.org/opl.shtml The content of this document is related to TYPO3 \- a GNU/GPL CMS/Framework available from www.typo3.com .. _Table-of-Contents: Table of Contents ----------------- **User TCA types and bidirectional MM tables 1** **Introduction 1** **Installation 2** **Developers section 2** **Configuration (bidirectional) 3** **Tutorial 3** **Known problems 5** **To-Do list 5** **Changelog 5** .. _Introduction: Introduction ------------ .. _What-does-it-do: What does it do? ^^^^^^^^^^^^^^^^ **With TYPO3 V4.1 this extension is not needed anymore to extended MM table handling for the standard field types like 'group' and 'select', used by DAM for example.** This extension change parts of the TYPO3 core (TCE) to allow the implementation of other field types than the default like input, select and group. While rendering of fields is already possible with a user function it is not the case for the database handling itself. TCE offers a standard set of fields types and that's it. Now you can implement your own field types, means the database handling of it. As example implementation of a field type this extension introduces the concept of bidirectional MM relations to the TYPO3 framework. NOTE: This extension is only useful for programmers who wish to implement own field types or bidirectional relations in their extension tables. This extension by itself do nothing until another extension use it. You should only go on reading this if you have some experience with extension programming. .. _Bidirectional-MM-relations: Bidirectional MM relations ^^^^^^^^^^^^^^^^^^^^^^^^^^ MM relations are already used in many extensions as a mean of establishing a “link” between two tables. For further reading about this see the `TYPO3 Core APIs section 4 `_ about the Table Configuration Array (TCA). Since I assume that you already have some knowledge about programming extensions for the TYPO3 framework I will not go into detail on how this works. .. _The-problem-at-hand: The problem at hand """"""""""""""""""" MM-relations in TYPO3s backend were only singledirectional. To explain what this means, take this example: You have two tables, **tx\_myext\_table1** and **tx\_myext\_table2** . In **tx\_myext\_table1** you have configured a field of type “select”. The item array of this select field is filled with records from t **x\_myext\_table2** by using an MM relation. For this purpose a third “join”-table **tx\_myext\_table1\_table2\_mm** is used. In order to find any relations TYPO3 expects the **tx\_myext\_table1\_table2\_mm** to contain the following fields: **uid\_local** - this points to the uid of the local table (tx\_myext\_table1). **uid\_foreign** – this points to the uid of the foreign table (tx\_myext\_table2). So far everything is good. You can view, edit and delete relations between the two tables - :underline:`but only from the local table´s point of view` . Now, what if you wanted to create a “select” field in the **tx\_myext\_table2** which was populated with records from the **tx\_myext\_table1** using the same “join” table ( **tx\_myext\_table1\_table2\_mm)** ? The short answer to that question is: You can't. To give you a real world example, take a look at the tt\_news extension. You can open a single tt\_news record and assign it to one or more categories. But you can't open a category and select which tt\_news records should be assigned to it. This is were this extension comes in. It allows you to create “select” and “group” fields that uses the uid\_local field in the “join” table to lookup records in the foreign table. .. _History: History ^^^^^^^ The code of this extension has some history. It was part of the DAM extension, needed to provide mm relations of DAM records to other tables like content elements. The code didn't made it into the 4.0 Version of TYPO3 mainly because nobody was able to review it. That's why it is put into it's own extension, which has some disadvantages (see section Installation). Mads Brunn published the extension “bidirectional” which basically provide the same functionality. That's why I borrowed his extension manual content and modified it to fit for this extension. The solution provided by this extension is a bit more flexible than “bidirectional” and has different configuration values, but it is also more complex. After all the code was transformed to a more flexible solution. Now there's an interface in TCE to implement own field types and the bidirectional solution is just an implementation of a new field type. .. _Installation: Installation ------------ There's nothing special to mention for installation, but the extension installs three XCLASSes the administrator should know about: - t3lib/class.t3lib\_transferdata.php - t3lib/class.t3lib\_tcemain.php Using XCLASS is a way of changing core functions with an extension. This can work without problems but shouldn't be used generally and is more like a workaround. When another extension installs an XCLASS for one of the mentioned files the whole functionality will break and database relations might be lost. In a previous version of this extension the bidirectional functionality was patched (XCLASS) directly into the TYPO3 core. Now the changes made by the XCLASSes are very small in comparison. That means the default behavior of TCE shouldn't be affected in any way. During installation one can choose to use the old XCLASSes which is deprecated! .. _Developers-section: Developers section ------------------ As said the extension provide an interface to allow the implementation of new TCE field types. An example implementation is included. A full documentation of the functionality can't be provided as it just too much to cover all topics. So this just an introduction. Implementing a field type for TCE means to provide functions for converting data from the database for usage in backend forms (TCEforms) and converting the submitted form data for database storage or even write the data to the database. In principle that can be done with a 'user' type in TCA and a user function for form rendering. But this will not work when database relations needs to be handled because the form data will be written to db as it is by TCE. That's where we need own functions when the default TCE fields don't provide the needed functionality. To activate a so called userProcessClass for a field you have to add an entry in TCA like following: :: 'config' => array ( 'userProcessClass' => 'EXT:mmforeign/class.tx_mmforeign_tce.php:tx_mmforeign_tce', A userProcessClass can (but don't must) provide following methods: :: renderRecord_procField() checkValue() copyRecord_procField() remapListedDBRecords_procField() For details have a look into the example implementation. The methods have similar names like the methods in TCEmain so it is possible to have a look into the core how field handling work there. Implementing all methods might not be needed, it depends on the data format (releations) and what's needed. For example renderRecord\_procField() could be excluded when the data format coming from the database is already in expected format or a needed transformation will be done in a TCEforms user function. When a method is not implemented the data will be passed through, which means it will not be touched by another TCE function. Another example could be that only form data processing is wanted. Then checkValue() have to be implemented. .. _Configuration-bidirectional: Configuration (bidirectional) ----------------------------- To enable the bidirectional MM handling for a field add in the TCA config section of the field: :: "userProcessClass" => "EXT:mmforeign/class.tx_mmforeign_tce.php:tx_mmforeign_tce", The extension works by extending the way you configure MM relations in the TCA for fields of type “select” and “group”. .. _generated: ((generated)) ^^^^^^^^^^^^^ .. _Addition-to-Core-API-ssection-4-2-9-columns-fieldname-config-TYPE-select-section-4-2-10-columns-fieldname-config-TYPE-group: Addition to Core API'ssection 4.2.9 ['columns'][fieldname]['config'] / TYPE: "select"section 4.2.10 ['columns'][fieldname]['config'] / TYPE: "group") """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. ### BEGIN~OF~TABLE ### .. _MM-foreign-select: MM\_foreign\_select ~~~~~~~~~~~~~~~~~~~ .. container:: table-row Key MM\_foreign\_select Datatype boolean Description If set the uid\_local field will be used to lookup foreign records instead of uid\_foreign. Scope Proc. .. _MM-match-fields: MM\_match\_fields ~~~~~~~~~~~~~~~~~ .. container:: table-row Key MM\_match\_fields Datatype array Description Defines field/value pairs that will be used for read and update queries of the MM table. :: 'MM_match_fields' => array('ident' => 'category'), Scope Proc. .. _MM-insert-fields: MM\_insert\_fields ~~~~~~~~~~~~~~~~~~ .. container:: table-row Key MM\_insert\_fields Datatype array Description Defines field/value pairs that will be written to the MM table when a relation is written. :: 'MM_insert_fields' => array('a_field' => 'a value'), Scope Proc. .. _MM-table-where: MM\_table\_where ~~~~~~~~~~~~~~~~ .. container:: table-row Key MM\_table\_where Datatype string Description This is a where clause which is included in MM table queries. Scope Proc. .. _prepend-tname: prepend\_tname ~~~~~~~~~~~~~~ .. container:: table-row Key prepend\_tname Datatype boolean Description If set the table name of the relation is stored in the MM tables field “tablenames”. Scope Proc. .. ###### END~OF~TABLE ###### .. _Tutorial: Tutorial -------- .. _Example-1-Adding-a-bidirectional-field-in-tt-news: Example 1: Adding a bidirectional field in tt\_news ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In this section I will go through an example of how to use bidirectional MM relations. This example extends the tt\_news extension by adding a bidirectional field to the tt\_news\_cat table. .. _Creating-the-field-in-the-database: Creating the field in the database """""""""""""""""""""""""""""""""" We start by creating the field in the database: :: # # Table structure for table 'tt_news_cat' # CREATE TABLE tt_news_cat ( tx_mmforeignexample_tt_news int(11) DEFAULT '0' NOT NULL ); .. _Configuring-the-field: Configuring the field """"""""""""""""""""" Next, we configure the field and adds it to the $TCA: :: 0: Array ( 4: "exclude" => 1, 5: "label" => "News in this category", 6: "config" => Array ( 7: "type" => "select", 8: "userProcessClass" => "EXT:mmforeign/class.tx_mmforeign_tce.php:tx_mmforeign_tce", 9: "foreign_table" => "tt_news", 10: "foreign_table_where" => "ORDER BY tt_news.crdate", 11: "size" => 10, 12: "minitems" => 0, 13: "maxitems" => 100, 14: "MM" => "tt_news_cat_mm", 15: "MM_foreign_select" => 1, 16: ) 17: ), 18: ); 19: t3lib_div::loadTCA("tt_news_cat"); 20: t3lib_extMgm::addTCAcolumns("tt_news_cat",$tempColumns,1); 21: t3lib_extMgm::addToAllTCAtypes("tt_news_cat","tx_mmforeignexample_tt_news;;;;1-1-1"); 22: ?> **Notice the syntax of line 8 and 15.** .. _Example-2-Using-additional-fields-in-MM-table: Example 2: Using additional fields in MM table ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Uncommented example that might not make real sense. Just to show how to use an additional field in MM tables. :: # # Table structure for table 'tx_example_item_mm' # CREATE TABLE tx_example_item_mm ( uid_local int(11) DEFAULT '0' NOT NULL, uid_foreign int(11) DEFAULT '0' NOT NULL, tablenames varchar(30) DEFAULT '' NOT NULL, ident varchar(30) DEFAULT '' NOT NULL, sorting int(11) unsigned DEFAULT '0' NOT NULL, KEY uid_local (uid_local), KEY uid_foreign (uid_foreign) ); :: $TCA['tx_example_item'] = array( ... 'columns' => array( 'category' => array( 'label' => 'Category:', 'config' => array ( 'type' => 'group', 'userProcessClass' => 'EXT:mmforeign/class.tx_mmforeign_tce.php:tx_mmforeign_tce', 'internal_type' => 'db', 'allowed' => 'tx_example_category', 'prepend_tname' => 1, 'MM' => 'tx_example_item_mm', 'MM_match_fields' => array('ident' => 'category'), 'size' => 3, 'maxitems' => 200, 'minitems' => 0, ) ), $TCA['tx_example_category'] = array( ... 'columns' => array( 'related' => array( 'label' => 'Category:', 'config' => array ( 'type' => 'group', 'userProcessClass' => 'EXT:mmforeign/class.tx_mmforeign_tce.php:tx_mmforeign_tce', 'internal_type' => 'db', 'allowed' => 'tx_example_item', 'prepend_tname' => 1, 'MM' => 'tx_example_item_mm', 'MM_foreign_select' => 1, 'MM_match_fields' => array('ident' => 'category'), 'size' => 3, 'maxitems' => 200, 'minitems' => 0, ) ), .. _Known-problems: Known problems -------------- .. _generated: ((generated)) ^^^^^^^^^^^^^ .. _t3lib-refindex: t3lib\_refindex """"""""""""""" The class of TYPO3 V4 don't work correctly with foreign MM relations (when core is patched). Means the relation is stored twice. This is because of a hash calculation including the sorting which makes no sense to me. Anyway t3lib\_refindex is unsupported and might produce unexpected results for userProcessClass fields. .. _To-Do-list: To-Do list ---------- \- Find somebody who will make this part of the core. .. _Changelog: Changelog --------- \- Implemented an interface in TCEmain and make 'bidirectional' use of it. Much cleaner. |img-1| User TCA types and bidirectional MM tables - 5 .. ######CUTTER_MARK_IMAGES###### .. |img-1| image:: img-1.png .. :align: left .. :border: 0 .. :height: 32 .. :id: Graphic1 .. :name: Graphic1 .. :vspace: 15 .. :width: 102