Artikelanzahl in Kategorie

Hallo,
gibt es ein Feature um die tatsächliche Anzahl der Artikel in einer Kategorie und allen Unterkategorien zu ermitteln?
A
|—B
| |—C
| | |—Prod1
| | |—Prod2
| | |—Prod3
| |
| |—D
| | |—Prod1
| | |—Prod2
| |
| |—Prod1
| |—Prod2

Also #Prod©=3;#Prod(D)=2;#Prod(B)=7;#Prod(A)=7

Auf C und D ist es natürlich klar, Oxid würde auf B natürlich nur 2 liefern und auf A 0.

Viele Grüße und vielen Dank für evtl. Tipps
Stephan

nein, es werden immer nur die artikel in der jeweiligen kategorie berechnet, nicht weiter nach oben/unten vererbt.

dafür müsstest du ein modul bauen.

Hi kalina!

Du müsstest wirklich ein eigenes kleines Modul schreiben. Ich habe das grad mal ausprobiert und folgende rekursive Funktion gebaut:


public function getAllArtsInCatNum($sCatID) {
        $oDb = oxDb::getDb(ADODB_FETCH_ASSOC);
        
        $oArticle = oxNew('oxarticle');
        
        $sSelect = "SELECT COUNT(*) AS count FROM oxobject2category "
            . " LEFT JOIN {$oArticle->getViewName()} ON {$oArticle->getViewName()}.oxid=oxobject2category.oxobjectid "
            . " WHERE oxcatnid='{$sCatID}' AND {$oArticle->getSqlActiveSnippet()}";
            
        $oRs = $oDb->execute($sSelect);
        
        $iCount = $oRs->fields['count'];
        
        $sSubCatSelect = "SELECT oxid FROM oxcategories WHERE oxparentid='{$sCatID}'";
        
        $oRs = $oDb->execute($sSubCatSelect);
        while(!$oRs->EOF) {
           $iCount += $this->getAllArtsInCatNum($oRs->fields['oxid']);
           $oRs->moveNext(); 
        }
        
        return $iCount;
    }

Das funktioniert bei mir ganz gut. Durch die SQL-Selects läuft es erheblich performanter als wenn man über die Wrapper-Klassen von OXID geht.

Wenn du Fragen hast, wie man das ganze in ein Modul gießt, sag noch mal Bescheid.

Schöne Grüße
Lukas


einscommerce - OXID Enterprise Solution Partner

http://www.einscommerce.com

Hallo Lukas,
sehr schön und sehr elegant.
Ich habe es natürlich schon gestern mit einer Erweiterung des alist Controllers umgesetzt, ohne Rekursion, nur schnell Q&D und einem rudimentären Break, sollte er eine Endlosschleife durchlaufen:

public function getDeepCount() {
		//DB Connect
		$oDB = oxDb::getDb( true );
		$oCat = $this->getActiveCategory();
		$catid=$oCat->oxcategories__oxid->value;
		//Alle direkten Unterkategorien
		$sql_mycheck="select oxid from oxcategories where oxparentid='$catid';";
		$res_mycheck=$oDB->execute($sql_mycheck);
		$aDone=array();
		array_push($aDone,$catid);
		$aTodo=array();
		if ($res_mycheck&&$res_mycheck->RecordCount()>0) {
			while(!$res_mycheck->EOF){
				$sOxid=$res_mycheck->fields[0];
				array_push($aDone,$sOxid);
				array_push($aTodo,$sOxid);
				$res_mycheck->moveNext();
			}
		}
		/* print_r($aTodo); */
		$ibreak=0;
		while(count($aTodo)>0) {
			$workid=array_shift($aTodo);
			$sql_mycheck_sub="select oxid from oxcategories where oxparentid='$workid';";
			$res_mycheck_sub=$oDB->execute($sql_mycheck_sub);
			if ($res_mycheck_sub&&$res_mycheck_sub->RecordCount()>0) {
				while(!$res_mycheck_sub->EOF){
					if($ibreak>15000) { /*wir laufen in einer endlosschleife */ break;}
					$sOxid=$res_mycheck_sub->fields[0];
					array_push($aDone,$sOxid);
					array_push($aTodo,$sOxid);
					$res_mycheck_sub->moveNext();
					$ibreak++;
				}
			}
		}
		/* print_r($aDone); */
		$sql_suff="";
		foreach ($aDone as $id) {
			$sql_suff.="'".$id."',";
		}
		$sql_suff=substr($sql_suff,0,-1);
		$sql_mycount="select oxobjectid from oxobject2category,oxarticles where oxobject2category.oxcatnid in ($sql_suff) and oxarticles.oxid=oxobject2category.oxobjectid;";
		$res_mycount=$oDB->execute($sql_mycount);
		$iMyCount=0;
		if($res_mycount&&$res_mycount->RecordCount()>0) {
			$iMyCount=$res_mycount->RecordCount();
		}
		return $iMyCount;
	}

Hat auch ganz prima funktioniert.
LG
Stephan

Ja cool! Hast du denn auch mit drin, dass keine inaktiven Artikel mitgezählt werden? Hab ja das getSQLActiveSnippet() verwendet.


einscommerce - OXID Enterprise Solution Partner
http://www.einscommerce.com

Hi, nein. Ich brauche alle, auch die inaktiven :slight_smile:
sonst einfach um oxactive=1 erweitern, also

$sql_mycount="select oxobjectid from oxobject2category,oxarticles where oxobject2category.oxcatnid in ($sql_suff) and oxarticles.oxid=oxobject2category.oxobjectid and oxarticles.oxactive=1;"; 

Ja lieber das Snippet verwenden, weil da ist die ganze “Aktiv/Inaktiv”-Logik drin: oxactive = 1, oxstock > 0, oxstockflag = X usw.


einscommerce - OXID Enterprise Solution Partner
http://www.einscommerce.com