Ähnliche Produkte


#1

Woher nimmt der Shop die Information für “Ähnliche Produkte”?

Muss man die definieren? Wo?


#2

aus den attributen bzw. spezifikationen

im admin läßt sich die %zahl einstellen, die für die übereinstimmung herangezogen werden soll


#3

Oxid nimmt aber nur die Zuordnung der Hauptfelder, also nicht die Einträge die zu den Attributen gemacht werden, leider.


#4

[QUOTE=laramarco;28202]aus den attributen bzw. spezifikationen

im admin läßt sich die %zahl einstellen, die für die übereinstimmung herangezogen werden soll[/QUOTE]
OK, danke.


#5

Leider ist die Funktion aber wie ich schon mehrmals sagte fast unbrauchbar, denn er nimmt alle Artikel die das Attribut haben unabhängig vom Wert. Heist wenn deine Produkte das Attribut Farbe haben werden alle Artikel mit Farbe angezeigt egal ob Rot oder Blau oder Grün…


#6

Hier mal eine Verbesserung, nun werden auch die Werte der Attribute verglichen.

in oxarticle.php

alte Funktion:

protected function _getAttribsString(&$sAttribs, &$iCnt)
    {
        // we do not use lists here as we dont need this overhead right now
        $oDB = oxDb::getDb(true);
        $sSelect =  'select oxattrid from oxobject2attribute where oxobject2attribute.oxobjectid="'.$this->getId().'" ';
        $sAttribs = '';
        $blSep = false;
        $rs = $oDB->execute( $sSelect);
        $iCnt = 0;
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                if ( $blSep) {
                    $sAttribs .= ' or ';
                }
                $sAttribs .= 't1.oxattrid = '.$oDB->quote($rs->fields['oxattrid']).' ';
                $blSep = true;
                $iCnt++;
                $rs->moveNext();
            }
        }
    }

Neue Funktion:

protected function _getAttribsString(&$sAttribs, &$iCnt)
    {
        // we do not use lists here as we dont need this overhead right now
        $oDB = oxDb::getDb(true);
        $sSelect =  'select oxattrid, oxvalue from oxobject2attribute where oxobject2attribute.oxobjectid="'.$this->getId().'" ';
        $sAttribs = '';
        $blSep = false;
        $rs = $oDB->execute( $sSelect);
        $iCnt = 0;
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                if ( $blSep) {
                    $sAttribs .= ' or ';
                }
                $sAttribs .= 't1.oxattrid = '.$oDB->quote($rs->fields['oxattrid']).' and t1.oxvalue = '.$oDB->quote($rs->fields['oxvalue']).' ';
                $blSep = true;
                $iCnt++;
                $rs->moveNext();
            }
        }
    }

Gruß, Christian


#7

Mein erster Beitrag hier im Oxid Forum. :slight_smile:

@ csemisch

Klasse, der Code klappt. Jetzt werden wesentlich bessere “ähnliche Artikel” im Shop angezeigt; und wenn man auf 50% “Prozentsatz gleicher Attribute, damit Artikel ähnlich sind” im Admin stellt, werden sogar andere/ähnliche für den Kunden interessante Produkte angezeigt. Dies ist jedenfalls mein erster Eindruck nach kurzem Test.

Der Code zur Verbesserung der Vergleichsfunktion über Attribute steht nun seit über einem Jahr hier, warum hat niemand applaudiert?


#8

kann mal jemand helfen, in welchem ordner finde ich denn die datei.
danke für die bemühnungen.
freundlicher gruß vom niederrhein
horst


#9

die oxarticle.php? Findest Du im Verzeichnis /core.

Allerdings, beim nächsten Patch / Update wird diese Datei erneut überschrieben und die Änderung ist weg und sollte ggf. erneut nachgepflegt werden.

Oder Du bindest diese Änderung als Modul ein, ohne direkte Änderungen an der core-Datei.


#10

Hi zusammen,
habe den modifizierten Code von csemisch mit der 4.5.0 CE getestet, bringt aber leider keine besseren Resultate - scheint nach wie vor so, als ob nur die Attributbezeichnungen und nicht die tatsächlichen Attributwerte zum Vergleich herangezogen werden…

Hat jemand eine Idee, wie man das ganze so verfeinern könnte, dass es auch mit Version 4.5 klappt?

Vielen Dank!


#11

Habe inzwischen eine Lösung für Version 4.5CE gefunden!
Bei mir stehen die Attributwerte nicht in oxvalue sondern in oxvalue_1…
Damit funktioniert’s bestens:

    protected function _getAttribsString(&$sAttribs, &$iCnt)
    {
        // we do not use lists here as we dont need this overhead right now
        $oDB = oxDb::getDb(true);
        $sSelect =  'select oxattrid, oxvalue_1 from oxobject2attribute where oxobject2attribute.oxobjectid="'.$this->getId().'" ';
        $sAttribs = '';
        $blSep = false;
        $rs = $oDB->execute( $sSelect);
        $iCnt = 0;
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                if ( $blSep) {
                    $sAttribs .= ' or ';
                }
                $sAttribs .= 't1.oxattrid = '.$oDB->quote($rs->fields['oxattrid']).' and t1.oxvalue_1 = '.$oDB->quote($rs->fields['oxvalue_1']).' ';
                $blSep = true;
                $iCnt++;
                $rs->moveNext();
            }
        }
    }

#12

[QUOTE=thengl;70845]Habe inzwischen eine Lösung für Version 4.5CE gefunden!
Bei mir stehen die Attributwerte nicht in oxvalue sondern in oxvalue_1…
Damit funktioniert’s bestens:[/QUOTE]
Das ist aber eine spezielle Lösung nur für Dich…

Das grundlegende Problem ist, dass der Attributwert nicht [B]sprachabhängig [/B]geprüft wird…

Folgende Variante löst das, ist also auch für Mehrsprachigkeit geeignet:

  protected function _getAttribsString(&$sAttribs, &$iCnt)
  {
    // we do not use lists here as we dont need this overhead right now
    $oDB = oxDb::getDb(true);
    $value_field='oxvalue';
    $sSuffix = oxLang::getInstance()->getLanguageTag();
    if ($sSuffix)
    {
      $value_field.=$sSuffix;
    }
    $sSelect =  'select oxattrid, '.$value_field.' from oxobject2attribute where oxobject2attribute.oxobjectid="'.$this->getId().'" '.PHP_EOL;
    $sAttribs = '';
    $rs = $oDB->execute( $sSelect);
    $iCnt = 0;
    if ($rs != false && $rs->recordCount() > 0)
    {
      while (!$rs->EOF)
      {
        if ($sAttribs)
        {
            $sAttribs .= ' or ';
        }
        $sAttribs .= '(oxattrid = '.$oDB->quote($rs->fields['oxattrid']).' and '.$value_field.' = '.$oDB->quote($rs->fields[$value_field]).')'.PHP_EOL;
        $iCnt++;
        $rs->moveNext();
      }
    }
  }


#13

Hallo zusammen,

wie kann ich das für 4.7.x lösen?


#14

Da bei mir bei Ähnliche Produkte auch nichts passendes angezeigt wird, hätte ich die Funktion wie hier im Thread beschrieben verändert. Leider funktioniert das unter Version 4.7.6 nicht.

Möchte gerne dass die Attribut-Werte und nicht die Attribut-Titel herangezogen werden. Bei mir hat nämlich jeder Artikel die selben Attribut-Titel.

Hat vielleicht jemand einen Tipp?


    protected function _getAttribsString(&$sAttribs, &$iCnt)
    {
        // we do not use lists here as we dont need this overhead right now
        $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
        $sSelect =  'select oxattrid from oxobject2attribute where oxobject2attribute.oxobjectid='.$oDb->quote( $this->getId() );
        $sAttribs = '';
        $blSep = false;
        $rs = $oDb->select( $sSelect);
        $iCnt = 0;
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                if ( $blSep) {
                    $sAttribs .= ' or ';
                }
                $sAttribs .= 't1.oxattrid = '.$oDb->quote($rs->fields['oxattrid']).' ';
                $blSep = true;
                $iCnt++;
                $rs->moveNext();
            }
        }
    }

#15

Bitte nochmals ein Aufruf: Wie kann ich die “Ähnlichen Artikel” auch für für 4.7.x aufmotzen. Es sollen die Attribut Werte nicht die Attribut Bezeichnungen herangezogen werden.
Danke!


#16

hallo,

wie gross wäre der Aufwand um das für ce 4.8 anzupassen?


#17

Hi Leute,

ich weiß der letzte Beitrag ist schon ein paar Tage her, aber da auf die letzten beiden keiner geantwortet hat und für 4.7 und 4.8 eine Lösung gesucht wurde hier eine Lösung, die bei mir (4.8.3 und 4.8.4 getestet) funktioniert.

Im Grunde ist der Code von avenger (#12) noch immer funktionsfähig wenn man in der Zeile:

$oDB = oxDb::getDb(true);

eine kleine Änderung macht:

$oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );

[B]Das hat mir aber noch nicht gereicht. Warum?[/B]
Der Shop in dem ich die Anzeige anpassen wollte, hat viele Varianten und teilweise Attribute nur auf den Varianten gesetzt. Da aber Varianten in der Regel nicht in der Suche angezeigt werden, also das Feld OXISSEARCH auf 0 gesetzt ist, werden diese in der Berechnung nicht berücksichtigt (werden in der abschliessenden SQL ausgefiltert).

Darüber hinaus berücksichtigt der Code von avenger zwar Multilinguale Setups, allerdings auf einem Weg, den man in OXID eleganter gehen kann. Für die einzelnen Sprachen gibt es nun DB-Views, die man abfragen kann.

Dies führte zu drei Methoden, die ich für meine Zwecke verändert habe.
[B]Ob für euren Anwendungsfall alle Stellen angepasst werden müssen, kann man nicht pauschal sagen und muss von Fall zu Fall entschieden werden. Also bitte den Code nicht als “Allheilmittel” ansehen, sondern eher als Gedankenhilfe[/B]

[B]1) _getAttribsString[/B]
Hier werden die Attributnamen und (jetzt) auch die Werte des aktuellen Artikels aus der DB gezogen.


    protected function _getAttribsString(&$sAttribs, &$iCnt)
    {
        // we do not use lists here as we dont need this overhead right now
        $oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
        $sObj2AttView = getViewName('oxobject2attribute');

        $sSelect =  "select oxattrid, oxvalue from {$sObj2AttView} where oxobjectid='".$this->getId()."' ".PHP_EOL;
        $sAttribs = '';
        $rs = $oDB->execute( $sSelect);
        $iCnt = 0;
        if ($rs != false && $rs->recordCount() > 0)
        {
            while (!$rs->EOF)
            {
                if ($sAttribs)
                {
                    $sAttribs .= ' or ';
                }
                $sAttribs .= '(oxattrid = '.$oDB->quote($rs->fields['OXATTRID']).' and oxvalue = '.$oDB->quote($rs->fields['OXVALUE']).')'.PHP_EOL;
                $iCnt++;
                $rs->moveNext();
            }
        }
    }

[B]2. _getSimList[/B]
Hier wird aufgrund der Attribute eine Liste an Artikeln aufgebaut, die dem aktuellen Artikel ähnlich sind. Hier habe ich geändert, dass nicht die Varianten zurückgegeben werden, sondern deren Väter. Das verhindert, dass die Varianten aussortiert werden bzw - wenn die Varianten als Suchbar gesetzt sind - nicht nur Varianten von einem Artikel angezeigt werden:


    protected function _getSimList($sAttribs, $iCnt) {
        $myConfig = $this->getConfig();
        $oDb      = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
        $sArticleTable = $this->getViewName();
        $sObj2AttView = getViewName('oxobject2attribute');


        // #523A
        $iAttrPercent = $myConfig->getConfigParam( 'iAttributesPercent' )/100;
        // 70% same attributes
        if ( !$iAttrPercent || $iAttrPercent < 0 || $iAttrPercent > 1) {
            $iAttrPercent = 0.70;
        }
        // #1137V iAttributesPercent = 100 doesnt work
        $iHitMin = ceil( $iCnt * $iAttrPercent );

        // we do not use lists here as we don't need this overhead right now
        $aList= array();
        $sSelect =  "select oxobjectid, oxart.oxparentid, count(*) as cnt from {$sObj2AttView} as t1 LEFT JOIN {$sArticleTable} as oxart on (oxobjectid = oxart.oxid) where
                    ( $sAttribs )
                    and t1.oxobjectid != ".$oDb->quote( $this->oxarticles__oxid->value )."
                    group by t1.oxobjectid having count(*) >= $iHitMin ";
        $rs = $oDb->selectLimit( $sSelect, 50, 0 );
        $parents = array();
        if ($rs != false && $rs->recordCount() > 0) {
            while (!$rs->EOF) {
                $oxparentid = $rs->fields['OXPARENTID'];
                $oxobjectid = $rs->fields['OXOBJECTID'];

                if($oxparentid && $parents[$oxparentid] || !strcmp($oxobjectid,$this->oxarticles__oxid->value) || !strcmp($oxparentid,$this->oxarticles__oxid->value)) {
                    $rs->moveNext();
                    continue;
                }
                if($oxparentid){
                    $parents[$oxparentid] = 1;
                } else {
                    $parents[$oxobjectid] = 1;
                }
                $oTemp = new stdClass();    // #663
                $oTemp->cnt = $rs->fields['cnt'];
                $oTemp->id  = $oxobjectid;
                $oTemp->parent = $oxparentid;
                $aList[] = $oTemp;
                $rs->moveNext();
            }
        }
        return $aList;
    }

[B]3. _generateSimListSearchStr[/B]
Hier wird letztlich das finale SQL-Statement zusammengebaut. Auch hier muss nochmal berücksichtigt werden, welche Artikel nun Varianten und welche keine sind…

    
protected function _generateSimListSearchStr($sArticleTable, $aList) {
        $myConfig = $this->getConfig();
        $sFieldList = $this->getSelectFields();
        $sSearch = "select $sFieldList from $sArticleTable where ".$this->getSqlActiveSnippet()." and $sArticleTable.oxid in ( ";
        $blSep = false;
        $iCnt = 0;
        $oDb = oxDb::getDb();
        foreach ( $aList as $oTemp) {
            if ( $blSep) {
                $sSearch .= ',';
            }
            if($oTemp->parent) {
                $sSearch .= $oDb->quote($oTemp->parent);
            } else {
                $sSearch .= $oDb->quote($oTemp->id);
            }
            $blSep = true;
            if ( $iCnt >= $myConfig->getConfigParam( 'iNrofSimilarArticles' ) ) {
                break;
            }
            $iCnt++;
        }

        //#1741T
        //$sSearch .= ") and $sArticleTable.oxparentid = '' ";
        $sSearch .= ') ';

        // #524A -- randomizing articles in attribute list
        $sSearch .= ' order by rand() ';
        return $sSearch;
    }


#18

Hallo an alle,

Ich nutzte die CE 4.8.8, aber finde die Datei nicht in der ich die Änderungen vornehmen muss.

Ich hab /core durchsucht, aber keine oxarticle.php gefuden :confused:

Bitte um Hilfe

Beste Grüße
Jack52


#19

Alle Models liegen seit 4.7.0 / 5.0.0 im Verzeichnis application/models: https://www.oxid-esales.com/de/support-services/dokumentation-und-hilfe/oxid-eshop/releases/releases-2012/oxid-eshop-470500.html


#20

Super, habs gefunden!

Auch an die anderen davor, der Filter funktioniert nun echt gut!

Beste Grüße
Jack52