Multiple display fields from associated models

Right.

I am using the newest version. CakePHP 3.8. I have a few tables associated which itself is associated with other models. In the tables that have, for example, the fields: (id, type_id, category_id), I would like to do something that brings up the following when calling $this->find(‘list’) etc: (1) Personal (type-id) - Category name (category-id)

I have tried creating a behavior but I can’t get it to work. I even tried playing with creating virtual fields but its not working as intended and its rather messy. I declared a function in a behavior (MultipleDisplayField) which am working on but the function is not being called and that is with or without the implementedMethods being declared in the behavior class.

This is the ugliness I came up with in the entity class for the table

protected function _getTypeCategory()
{
$entityTable = \Cake\ORM\TableRegistry::getTableLocator()->get(‘CategoriesTypes’);
$loaded = $entityTable->loadInto($this, [‘Types’, ‘Categories’]);
return
‘(’.$this->id.’)’. ’ - ‘.
$loaded->type->name . ’ (’.$loaded->type->id.’) - ‘.
$loaded->category->name . ’ - (’.$loaded->category->id.’)’;
}

In the table class I have this: $this->setDisplayField(‘type_category’);

As you can see, its not pretty. I would like to have it done in a behavior. Can anyone help with this?

Thanks in advance.

What is wrong with using a virtual field?

You don’t want to query every time someone accesses the virtual field. Try creating a custom finder method that always adds contain() with ‘Users’ and ‘Categories’.

https://book.cakephp.org/3/en/orm/retrieving-data-and-resultsets.html#custom-finder-methods

It’s seems you have a classic “many to many” relationship [1]. If you set-up the models accordingly [2] then accessing the relations should become rather easy.

I am creating an online platform and am using the bake console to write most of the code so using a behavior would be better suitable for what I need. The table has two foreign keys and BTM relationship so what I need is when I do a find(‘list’) on the model which contains the two fks for the BTM I need the data displayed to be the data from the associated models. I had got this to work in the past but for some reason am not getting it to work with the newest version of the framework. Thanks for the reply but I don’t think a custom finder is what I need.

Assessing the data is not the problem. The models are associated correctly. When doing a find(‘list’) on the linking model I as the displayed data (setDisplayField etc ) I would need the data from the associated model to be displayed (not just the id from lets say category_id, I would like to set the display field like this: (model.id) - AssociatedModel1.name ( AssociatedModel1.id) - AssociatedModel2.name ( AssociatedModel2.id). That way I would know straight away what exactly the linking table is associated with etc. It would be nice this was already built in the framework but as I am aware I don’t think it is so am trying to write a behavior that will do it. Any help much appreciated. Thanks for the reply.

Oh, I misunderstood. Personally I wouldn’t want to evaluate that through multiple associated tables at runtime on every request. Just store it. Create a new field in the table (e.g. title). Whenever the category-ID or type-ID changes update that field on the save. Set that field as displayField. But I’m not sure what we are doing here and why.

If that is the problem you want solve I say you’re looking for the wrong solution with displayField. This should be possible through ->find(... without all this trickery.

Schlaefer, Thanks. I have a database with many complex association. For example:

categories, types
categories_types (id, category_id, type_id)
feature_groups (id, feature_id, …)
categories_types_feature_groups (id, categories_type_id, feature_group_id)

So in the above, CategoriesTypes is associated with FeatureGroups, so when I go to add a new entry into “categories_types_feature_groups” I want to be to see not just the ID from the categories_types table but instead this: (id - category.name(category.id) - type.name (type.id)); I think I may have to look at the design for the database.

I think I understand it little bit better now. From the top of my head maybe start from here:

        $list = $this->CategoryTypes->find('list', [
            'valueKey' => function($categoryType) {
                return $categoryType->get('id')
                    . ' - ' . $categoryType->categories->get('name') 
                    . ' - ' . $categoryType->types->get('name');
            }
        ])->contain(['Categories', 'Types'])->toList();

https://book.cakephp.org/3/en/orm/retrieving-data-and-resultsets.html#customize-key-value-output

The variable/property names are probably all wrong, but you get the idea.