Zum Inhalt springen

MM-Relation in Repository realisieren

Erstellt am 30. Mai 2011 · 1 Antwort · letzte Antwort am 14. Juni 2011

Tags: Kategorien, Datenbank, Frage

nexuss ·

Hallo Typo3 Fans,
ich bin gerade dabei eine Extension auf Basis von Extbase zu bauen. Es kommt eine MM-Relation vor. Doch genau hier ist das Problem.

Zur Erläuterung:
Produkte können einer oder mehreren Kategorien zugeordnet werden.

Folgende Tabellen habe ich (Auszug):

CREATE TABLE tx_myextensionkey_domain_model_category (
	...
	
	products int(11) DEFAULT '0' NOT NULL,

	...
);

CREATE TABLE tx_myextensionkey_domain_model_product (
	...
	
	categories int(11) DEFAULT '0' NOT NULL,

	...
);

CREATE TABLE tx_myextensionkey_category_products_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,
	sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL,

	...
);

Im TCA steht (Auszug):

$TCA['tx_myextensionkey_domain_model_category'] = array(
	...
	'columns' => array(		
		...
		'products' => array(
			'exclude' => 0,
			'label'   => 'LLL:EXT:myextensionkey/Resources/Private/Language/locallang_db.xml:tx_myextensionkey_domain_model_category.products',
			'config' => array(
				'type' => 'select',				
				'size' => 10,
				'minitems' => 0,
				'maxitems' => 9999,
				'autoSizeMax' => 10,
				'multiple' => 0,				
				'foreign_table' => 'tx_myextensionkey_domain_model_product',
				'MM' => 'tx_myextensionkey_category_products_mm',
				'MM_opposite_field' => 'categories',
			)
		),		
		...		
	),
);

$TCA['tx_myextensionkey_domain_model_product'] = array(
	...
	'columns' => array(		
		...
		'categories' => array(
			'exclude' => 0,
			'label'   => 'LLL:EXT:myextensionkey/Resources/Private/Language/locallang_db.xml:tx_myextensionkey_domain_model_product.categories',
			'config' => array(
				'type' => 'select',
				'size' => 10,
				'minitems' => 0,
				'maxitems' => 9999,
				'autoSizeMax' => 10,
				'multiple' => 0,				
				'foreign_table' => 'tx_myextensionkey_domain_model_category',
				'MM' => 'tx_myextensionkey_category_products_mm',
			)
		),		
		...		
	),
);

Jetzt möchte ich im Repository die korrekte Abfrage erstellen, damit in der jeweiligen Kategorie die verknüpften Produkte gelistet werden. Aber wie?

Ich habe es schon mit folgendem Join versucht:

public function findProductsByCategory() {

	$query = $this->createQuery();
	$qomFactory = Tx_Extbase_Dispatcher::getPersistenceManager()->getBackend()->getQomFactory();
		
	$categoriesSelector = $query->getSource();
	$mmSelector = $qomFactory->selector(null, 'tx_myextensionkey_category_products_mm');
	$productsSelector = $qomFactory->selector(null, 'tx_myextensionkey_domain_model_product');		
	$AMMJoinCondition = $qomFactory->equiJoinCondition(
		$mmSelector->getSelectorName(), 'uid_local',
		$productsSelector->getSelectorName(), 'uid'
	);
	$MMBJoinCondition = $qomFactory->equiJoinCondition(
		$mmSelector->getSelectorName(), 'uid_foreign',
		$categoriesSelector->getSelectorName(), 'uid'
	);		
	$query->setSource(
		$qomFactory->join(
			$productsSelector,
			$qomFactory->join(
				$mmSelector,
				$categoriesSelector,
				Tx_Extbase_Persistence_QueryInterface::JCR_JOIN_TYPE_INNER,
					$MMBJoinCondition
			),
			Tx_Extbase_Persistence_QueryInterface::JCR_JOIN_TYPE_INNER,
			$AMMJoinCondition
		)
	);
	$query->setOrderings(array('title' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
	return $query->execute();		
}

Der funktioniert aber nicht. Da ist laut Bugtracker noch der Wurm drinne (Bug #10212, http://forge.typo3.org/issues/10212).

Hat jemand einen guten Tip auf Lager? Wäre toll.

Viele Grüße
Thomas

nexuss ·

Ok, ich habs soweit.

Es ist zwar im Join ein Bug enthalten, aber MM-Ralationen kann man sehr praktisch wie folgt ohne Join durchführen:

Zuerst habe ich im Model folgendes eingetragen:

<?php

...

/**
 * Categories
 */
class Tx_myextensionkey_Domain_Model_Category extends Tx_Extbase_DomainObject_AbstractEntity {

   ...

   /**
    * The products of the Cateogy
    *
    * @var Tx_Extbase_Persistence_ObjectStorage<Tx_myextensionkey_Domain_Model_Product>
    * @lazy
    * @cascade remove
    */
    protected $products;

    ...
?>

und im Repository dann:

<?php

...

/**
 * Repository for Tx_myextensionkey_Domain_Model_Product
 */
class Tx_myextensionkey_Domain_Repository_ProductRepository extends Tx_Extbase_Persistence_Repository {	

    ...

    /**
     * Finds products by the specified category
     *
     * @param string $product
     * @param Tx_myextensionkey_Domain_Model_Category $category The category the product must refer to
     * @return Tx_Extbase_Persistence_QueryResultInterface The products
     */
    public function findProductsByCategory(Tx_myextensionkey_Domain_Model_Category $category) {	
        $query = $this->createQuery();		
        $query->matching($query->contains('categories', $category->getUid()));
        $query->setOrderings(array('title' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
        return $query->execute();
    }	
}

...

?>

Und siehe da, alles wird so angezeigt wie es soll.

Gruß
Tom