TYPO3 extbase & IRRE: add existing entries with 'foreign_selector'

I "kickstarted" an extension with the extbase extender that contains some 1: 1 and 1: n ratios. It automatically sets the field types to "inline" and displays a nice IRRE interface to the backend.

But by default it is not possible to select an existing entry, just create new ones.

enter image description here

I have found various explanations on how to achieve this with "foreign_selector", but they are all very sketchy. The function itself should work, see https://forge.typo3.org/issues/43239

Can anyone walk me through this or point me to a working example in TER? I could create a walkthrough from the example once I get it working.

PS TCA field config created with extension_builder

:

'myfield' => array(
    'exclude' => 1,
    'label' => 'LLL:EXT:myextension/Resources/Private/Language/locallang_db.xlf:tx_myextension_domain_model_myitem.myfield',
    'config' => array(
        'type' => 'inline',
        'foreign_table' => 'tx_myextension_domain_model_myfield',
        'foreign_field' => 'myitem',
        'maxitems'      => 9999,
        'appearance' => array(
            'collapseAll' => 0,
            'levelLinksPosition' => 'top',
            'showSynchronizationLink' => 1,
            'showPossibleLocalizationRecords' => 1,
            'showAllLocalizationLink' => 1
        ),
    ),
),

      

+3


source to share


1 answer


The main problem is that 1: n type IRRE relationships work like this: a child record contains the uid of its parent. So your tx_myext_domain_model_city table contains the UID of your (imaginary) tx_myext_domain_model_address.

Therefore, with the default setting, you will not be able to select a city multiple times, since it can have exactly one parent.

Therefore, you will need to use a relationship table for this field. This table should contain a uid field for address (uid_address) and city (uid_city):

CREATE TABLE tx_irreforeignselectordemo_address_city_mm (

    uid int(11) NOT NULL auto_increment,
    pid int(11) DEFAULT '0' NOT NULL,
    uid_address int(11) unsigned DEFAULT '0' NOT NULL,
    uid_city int(11) unsigned DEFAULT '0' NOT NULL,
    sorting int(11) unsigned DEFAULT '0' NOT NULL,

    PRIMARY KEY (uid),
    KEY parent (pid)
);

      

And these fields need to have TCA config (while the table itself can be hidden):

return array(
    'ctrl'      => array(
        'title'     => 'Relation table',
        'hideTable' => TRUE,
        'sortby'    => 'sorting',
    ),
    'columns'   => array(
        'uid_address' => Array(
            'label'  => 'Address',
            'config' => Array(
                'type'          => 'select',
                'foreign_table' => 'tx_irreforeignselectordemo_domain_model_address',
                'size'          => 1,
                'minitems'      => 0,
                'maxitems'      => 1,
            ),
        ),
        'uid_city'   => Array(
            'label'  => 'City',
            'config' => Array(
                'type'                => 'select',
                'foreign_table'       => 'tx_irreforeignselectordemo_domain_model_city',
                'foreign_table_where' => ' AND sys_language_uid IN (0,-1)',
                'size'                => 1,
                'minitems'            => 0,
                'maxitems'            => 1,
            ),
        ),
    ),
    'types'     => array(
        '0' => array('showitem' => 'uid_address,uid_city')
    ),
    'palettes'  => array()
);

      

Then you can configure the TCA of your address to make the IRRE field:

'type' => 'inline',
'foreign_table' => 'tx_yourext_address_city_mm',
'foreign_field' => 'uid_address',
'foreign_label' => 'uid_city',
'foreign_selector' => 'uid_city',
'foreign_unique' => 'uid_city',
'foreign_sortby' => 'sorting',

      

Note what foreign_unique

TYPO3 tells you that a city can only be selected once.

And you need to define the attitude from the other side (from your TCA city):



    'addresses' => array(
        'exclude' => 1,
        'label'   => 'Addresses',
        'config'  => array(
            'type' => 'inline',
            'foreign_table' => 'tx_irreforeignselectordemo_address_city_mm',
            'foreign_field' => 'uid_city',
            'foreign_label' => 'uid_address',
        ),
    ),

      

Once your configuration is complete, you can use it in the backend.

Since this is a non-standard MM relationship, Extbase won't be able to handle it by default. But we can compare this with the sys_file_reference table that was introduced in TYPO3 6. So we create an Extbase model for CityRelation with the properties "address" and "city" and map this model to our mm table:

config.tx_extbase.persistence.classes {
    Visol\Irreforeignselectordemo\Domain\Model\CityRelation {
        mapping {
            tableName = tx_irreforeignselectordemo_address_city_mm
            columns {
                uid_address.mapOnProperty = address
                uid_city.mapOnProperty = city
            }
        }
    }
}

      

Now in our address model, we define the city (or cities - you allow more than one choice) as an ObjectStorage of type CityRelation:

/**
 * Cities
 *
 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Visol\Irreforeignselectordemo\Domain\Model\CityRelation>
 */
protected $cities = NULL;

      

We now have a "cities" property that contains links to all the selected cities. You can iterate over them and use them:

<f:for each="{address.cities}" as="cityRelation">
  <li>{cityRelation.city.name}</li>
</f:for>

      

Since I couldn't find an all-in-one demo for this and was interested in the topic, I created a demo extension that does what I just described - based on Core and two extensions that deal with the topic: https://github.com/lorenzulrich/irreforeignselectordemo

Anyway, the solution is m: n (because 1: n won't work for the reasons stated above), so I decided to use "cities" instead of "cities". While this may not make sense for a city selection (as your post suggests), it may make sense for other possibilities. Feel free to replace "cities" with "city" and set maxItems in the inline configuration to one - then you have a 1: n view.

+7


source







All Articles