Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
typo3 extbase categories
<?php
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
$_EXTKEY,
'tx_mymodels_domain_model_mymodel'
);
#
# Table structure for table 'tx_mymodels_domain_model_mymodel'
#
CREATE TABLE tx_mymodels_domain_model_mymodel (
categories int(11) unsigned DEFAULT '0' NOT NULL,
);

To use Extbase CategoryRepository, to work with Categories on our model we need to:

Add in ext_tables.sql, in our model, the categories field categories int(11) unsigned DEFAULT '0' NOT NULL, Make your model categorizable, by adding bellow snipet in ext_tables.php

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable(
    $_EXTKEY,
    'tx_mymodels_domain_model_mymodel'
);

Create own Category model and CategoryRepository by extending extabase Category and CategoryRepository

namespace MyVendor\MyModels\Domain\Model;
class Category extends \TYPO3\CMS\Extbase\Domain\Model\Category {}
namespace MyVendor\MyModels\Domain\Repository;
class CategoryRepository extends \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository {}

In your MyModelController inject CategoryRepository

/**
 * CategoryRepository
 *
 * @var \MyVendor\MyModels\Domain\Repository\CategoryRepository
 * @inject
 */
protected $categoryRepository = null;

Add to your model categories field with getters and setters

/**
 * categories
 *
 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MyVendor\MyModels\Domain\Model\Category>
 * @lazy
 */
protected $categories;

/**
 * Get categories
 *
 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MyVendor\MyModels\Domain\Model\Category>
 */
public function getCategories()
{
    return $this->categories;
}

/**
 * Set categories
 *
 * @param  \TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories
 * @return void
 */
public function setCategories($categories)
{
    $this->categories = $categories;
}

In Configuration\TypoScript\setup.txt map back your model to extbase category table

plugin.tx_mymodels.persistence.classes {
	MyVendor\MyModels\Domain\Model\Category {
		mapping {
			recordType = 0
			tableName = sys_category
		}
	}
}

Use this way:

// gets all categories, all across the site
$categoryRepository->findAll();

// gets categories for this model
$myModel->getCategories();

// get all models for specific category
$collection = \TYPO3\CMS\Frontend\Category\Collection\CategoryCollection::load(
        $categoryId,
        TRUE,
        'tx_mymodels_domain_model_mymodel',
        'categories'
);

If you want to take categories records only from a sys folder you need to configure repository:

defaultQuerySettings->setRespectStoragePage(true)
defaultQuerySettings->setStoragePageIds($storagePageIds); 
<?php
/**
* categories
*
* \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
* @lazy
*/
protected $categories;
/**
* MyModel constructor.
*/
function __construct()
{
$this->categories = new ObjectStorage();
}
/**
* Get categories
*
* @return ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>
*/
public function getCategories()
{
return $this->categories;
}
/**
* Set categories
*
* @param ObjectStorage $categories
* @return void
*/
public function setCategories($categories)
{
$this->categories = $categories;
}
@exotec

This comment has been minimized.

Copy link

commented Jun 14, 2018

very useful. many thanks

@marteb

This comment has been minimized.

Copy link

commented Aug 3, 2018

Very useful summary!

Is this still the recommended way to do it? Especially, where does the part from ext_tables.php now belong to since ext_tables.php is deprecated?

@stigfaerch

This comment has been minimized.

Copy link

commented Aug 22, 2018

@marteb
Put it in /Configuration/TCA/Overrides/tx_yourtable.php

@Schweriner

This comment has been minimized.

Copy link

commented Aug 23, 2018

You may add @var to line 5 of MyModel.php to prevent an error:

* @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\Category>

@izirikovic

This comment has been minimized.

Copy link

commented Aug 27, 2018

Really useful. Thank you.

One question: I implemented this into my custom extension, and everything seems to work fine. But, in some cases the error message appears in the frontend: 'ColumnMap for property "categories" of class "XXX" is missing'.
Think this line returns an error: "$constraints[] = $query->equals('categories.uid', intval($settings["categoriesList"]));"
Once the cache is cleared everything is working, but after few hours an error appear again.

In general, everything is implemented based on your example. Do you have any hint, how to resolve this issue?

@schnoedet

This comment has been minimized.

Copy link

commented Aug 28, 2018

Same here, works fine but after few hours the categories disappear. The error is: Could not find class definition for name "Vendor\Extname\Domain\Model\Category". After clearing the cache everything is ok. My Typoversion is 8.7.18

@ste101

This comment has been minimized.

Copy link

commented Mar 20, 2019

Thank you very much.

I got the problem that only uid and pid was set. Other fields where empty.
Than I changed all
<\MyVendor\MyModels\Domain\xxx\Categoryxxx>
to
\TYPO3\CMS\Extbase\Domain\xxx\Categoryxxx>
and removed Category model and CategoryRepository and it worked as expected.

@exotec

This comment has been minimized.

Copy link

commented Mar 23, 2019

I got also a strange behaviour in TYPO3 8.7.24 like schnoedet describes above.
If no user is logged in the backend, the categories not shown in FE. After login to the backend and clear the caches the categories shown in FE. But after a while, again no categories are shown in the FE.

UPDATE

I have in the TCA of my model, for the field categories, implemented the code from Georg Ringers EXT:news and it works. I can clear the caches, log out from the BE and the categories are available in the FE.

        'categories' => [
            'exclude' => true,
            'label' => $ll . 'tx_news_domain_model_news.categories',
            'config' => [
                'type' => 'select',
                'renderType' => 'selectTree',
                'treeConfig' => [
                    'dataProvider' => \GeorgRinger\News\TreeProvider\DatabaseTreeDataProvider::class,
                    'parentField' => 'parent',
                    'appearance' => [
                        'showHeader' => true,
                        'expandAll' => true,
                        'maxLevels' => 99,
                    ],
                ],
                'MM' => 'sys_category_record_mm',
                'MM_match_fields' => [
                    'fieldname' => 'categories',
                    'tablenames' => 'tx_geevents_domain_model_event',
                ],
                'MM_opposite_field' => 'items',
                'foreign_table' => 'sys_category',
                'foreign_table_where' => ' AND (sys_category.sys_language_uid = 0 OR sys_category.l10n_parent = 0) ORDER BY sys_category.sorting',
                'size' => 10,
                'minitems' => 0,
                'maxitems' => 99,
                'behaviour' => [
                    'allowLanguageSynchronization' => true,
                ],
            ]
        ],
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.