Zum Inhalt springen

[Beginner] Hilfe bei SQL-Abfrage von Artikel mit mehreren Kategorien

Erstellt am 16. November 2006 · 7 Antworten · letzte Antwort am 4. November 2007

Tags: Kategorien, Datenbank, Frage

feelx ·

Hallo Leute

Ich habe das Video-Tutorial zur Erstellung einer eigenen Extension anhand Kaspars CD-Album durchgearbeitet.

Dachte, das ist toll, ich könnte es gleich abwandeln für einen eigenen Bedarf!

Wie beim Tut habe ich eine Tabelle Products und eine Tabelle mit Kategorien.

Nun stecke ich aber fest, weil ich (anders als beim Album) einen Artikel (CD) habe, der mehrere Kategorien haben kann (1:n).

Per default vom Kickstarter wird ja wie folgt abgefragt:

function getFieldContent($fN)	{
  switch($fN) {
     default:
       return $this->internal['currentRow'][$fN];		     
     break;
  }
}

Das spuckt die UIDs der Kateogrien kommasepariert aus (<p>9,12,15</p>)

Wiederum anhand des Tut's habe ich den o.g. SWITCH um eine CASE Anweisung erweitert, damit der Titel der Category und nicht die UID ausgegeben wird:

case 'category':
  if (!count($this->categoryCache))	{
	$query = 'SELECT * FROM user_test_productcategory WHERE pid=121'.$this->cObj->enableFields('user_test_productcategory');
	
         $res = mysql(TYPO3_db,$query);
         while($row=mysql_fetch_assoc($res)) {
         $this->categoryCache[$row['uid']]=$row;
	}
}

return htmlspecialchars($this->categoryCache[$this->internal['currentRow']['category']]['name']);

Das klappt auch, wenn "category" nur eine 1:1 beziehung hat. Aber durch das ganze SQL/While Zeug bin ich verwirrt. :o Bin mit PHP ohnehin ned so fit - aber man fängt ja immer mal irgendwo an ;-)

Kann mir jemand helfen, den oberen Teil so abzuändern, dass die SELECT Anweisung, bzw. auch die While Bedingung für 1:n Beziehungen möglich wird? 🙂

Hoffe mein Problem ist klar geworden.

Vielen Dank im Voraus.

edit
BTW: die oben stehende SELECT anweisung habe ich mit PID=121 abgeändert, weil ich entgegen des Beispiels auf einen StorageFolder zugreifen will. Das klappt so auch... später möchte ich dieses '121' durch einen Wert $Conf-Array ersetzen... das nur zur Info.... o.O

feelx ·

Danke Steffen für deine Antwort...

Das mit den Wrapper-Classes habe ich im Codeguidline zwar gesehen - aber hab mich halt an das Video Tut gehalten, weil ich ohnehin noch nicht sehr fit im Thema bin.

Das meinst du genau mit "Umhängetabellen mit (mm)" ? Meinst du sog. Lookup- oder Abfragetabellen? Gäbe es dafür irgendwo ein Beispiel?

Wäre mir sehr geholfen... 😃

steffenk ·

wenn Du im Kickstarter die Verknüfung zu den Kategorien mit "True M-M relations" angelegt hast, was für den Fall richtig wäre, dann erzeugt er Dir diese Umhängetabelle. Am besten Du schaust Dir die in phpMyAdmin an. Es ist eine reine Umhängetabelle mit den verknüpften uid's.

Um die Abfragen mit diesen Tabellen zu erleichtern, muss man die joins nicht selber basteln, sondern kann sich der mm-wrapper-funktion bedienen:

function exec_SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
feelx ·

ah danke jetzt wirds klarer...

Eine kleine Erfolgsmeldung - das "umsteigen" auf DBAL aus dem Video Tutorial hat problemlos geklappt, im Falle wo 1:1 Relation besteht:

		case 'category':
			 if (!count($this->categoryCache))	{

		$select_fields = '*';
		$from_table = 'user_test_productcategory';
		$where_clause = 'pid=121'.$this->cObj->enableFields('user_test_productcategory');
			
		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy=''.$orderBy=''.$limit='');
				
			while ($row=$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
				$this->categoryCache[$row['uid']]=$row;
				}
			}
			return htmlspecialchars($this->categoryCache[$this->internal['currentRow']['category']]['productcategory']);
		break;

Was aber leider nicht klappt, ist die Abfrage bei diesen Feldern wo mehrere Werte zulässig sind (hier industries => Branchen, wo ein Produkt eingesetzt werden kann...)

Ich vermute das Problem ja bei der Abfrage generell ;(

	//---------- INDUSTRIES
			case 'industries':
			 if (!count($this->industryCache))	{

		$select = '*';
		$local_table = 'user_test_product';
		$mm_table = 'user_test_product_industries_mm';
		$foreign_table = 'user_test_industries';
		$whereClause = 'pid=121'.$this->cObj->enableFields('user_test_industries');
			
		$res = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause,$groupBy=''.$orderBy=''.$limit='');
				
			while ($row=$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
				$this->industryCache[$row['uid']]=$row;
				}
			}
		
			return htmlspecialchars($this->industryCache[$this->internal['currentRow']['industries']]['industries']);
		break;

Das gibt dann ein Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource #angry# #paralyzed# :o

steffenk ·

in solchen Fällen hilft ein

t3lib_div::debug($GLOBALS['TYPO3_DB']->SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause,$groupBy=''.$orderBy=''.$limit=''));
feelx ·

Hallo nochmals!

Ich setze das Problem mal auf "gelöst", da das erstellen einer Lookup-Tabelle (True m-m Relation) wohl der Knackpunkt war. Mit einer modifizierten Query Anweisung komme ich weiter.
Ich setze das Problem mal auf gelöst und poste später noch die korrekte Lösung für meinen Fall.

Speziellen Dank an SteffenK 😃 :p

update
Musste das gelöst leider wegnehmen - funktioniert leider bis jetzt nicht...

roki18 ·

Hallo,

ich bin über dem gleichen Problem gesessen und denke, dass ich es gelöst habe.
Im Tutorial wird einzelnen CD-Alben jeweils eine Kategorie zugeordnet, im Beispiel von feelx aber jeweils einem Produkt möglicherweise auch mehrere Kategorien. Bei dieser 1:n-Zuordnung funktioniert die Darstellung des Kategorientitels nicht.

Meine Lösungsidee ist folgende:
In function getFieldContent($fN) enthält $this->internal['currentRow'][$fN] bei einer 1:n-Zuordnung mehrere durch Kommas getrennte Zahlen, z.B. 2,1, also die UIDs der Kategorien.
Ich lasse daher die in $this->internal['currentRow'][$fN] enthaltenen Zahlen in ein Array schreiben und gehe dann das Array schrittweise durch. Somit erhalte ich für jede UID einen Rückgabewert. Diese füge ich zusammen und das wars.

Ich bin kein guter PHP-Programmierer, daher kann man das Ganze mit Sicherheit auch eleganter lösen, aber so sieht die entscheidende CASE-Anweisung in der genannten Funktion aus:

case 'category':

$inhalt_von_category = $this->internal['currentRow'][$fN];
$mehrere_kategorien = "0";
if (eregi(',', $inhalt_von_category))  {
	$results = explode( ",", $inhalt_von_category);
	$num_fields = count($results);
	$mehrere_kategorien = "1";
}
switch ($mehrere_kategorien) {
	case "0":
		if (!count($this->$categoryCache))	{
			$select_fields = '*';
			$from_table = 'NAME_DER_TABELLE_MIT_DEN_KATEGORIEN';
			$where_clause = intval($GLOBALS["TSFE"]).$this->cObj->enableFields('NAME_DER_TABELLE_MIT_DEN_KATEGORIEN');
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy=''.$orderBy=''.$limit='');
			while ($row=$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
				$this->categoryCache[$row['uid']]=$row;
			}
		$rueckgabe = htmlspecialchars($this->categoryCache[$this->internal['currentRow'][$fN]]['kategorietitel']);
		return $rueckgabe;
		}
	
	break;
	case "1":
	for ($zaehler = 1; $zaehler <= $num_fields; $zaehler++) {
		$this->internal['currentRow'][$fN] = $results[$zaehler-1];
		if (!count($this->$categoryCache))	{
			$select_fields = '*';
			$from_table = 'NAME_DER_TABELLE_MIT_DEN_KATEGORIEN';
			$where_clause = intval($GLOBALS["TSFE"]).$this->cObj->enableFields('NAME_DER_TABELLE_MIT_DEN_KATEGORIEN');
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy=''.$orderBy=''.$limit='');
			while ($row=$GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
				$this->categoryCache[$row['uid']]=$row;
			}
		$rueckgabe .= htmlspecialchars($this->categoryCache[$this->internal['currentRow'][$fN]]['kategorietitel']).",<br />";
		}
	}
		$rueckgabe = substr($rueckgabe, 0, (strlen($rueckgabe)-7));
		return $rueckgabe;
	break;
}

break;

Viele Grüße

roki18