Magento Rest(e) API – Token holen und Kategorien in Magento anlegen

Nach einem Wochenende zum Kopflüften geht es wieder an die Arbeit – und somit geht es auch weiter mit der Magento Rest(e)-API. Angefangen hatte ich mit den Grundlagen zu Magento. Die weiteren Posts folgen dann Stück für Stück, am Ende werde ich noch ein kurzes Fazit der ganzen Aktion ziehen.

Token holen

Noch die einfachste der Aufgaben – API abfragen mit Benutzernamen und Passwort an das Backend und sich merken, wie der Token ausschaut.

$baseUrl = "http://mein.host.irgendwo/rest/";
$username = "admin";
$pass = "meinPW";

$ch = curl_init($baseUrl . "/V1/integration/admin/token");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array("username" => $username, "password" => $pass)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
$token = curl_exec($ch);
$token = json_decode($token);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer '.$token));

Soweit so einfach, es folgt der nächste Schritt…

Kategorien anlegen

Das Anlegen der Kategorien ist schon etwas schwieriger – immerhin sind diese nicht so flach wie die Attribute sondern unterliegen einer Baumstruktur. Geht man davon aus, dass man die gleiche Struktur ja auch in einem entsprechenden eigenen Verwaltungswerkzeug bzw. einer Datenbank pflegt, so kann man diese einfach durchiterieren. Es hat sich dabei bewährt rekursiv mit einer Tiefensuche (depth-first) zu arbeiten, da man dann immer die Referenz des Elternknotens noch leicht greifbar hat.

Um so schwieriger wird es jedoch, eine einmal eingetragene Struktur zu aktualisieren, da man keine Referenz auf das eigene Datenmodell in Form einer id oder etwas anderem hat. Hier muss man sich mühsam die Kategorien zusammen suchen und dann immer über die Kombination “elternid + Kindname” arbeiten. Schade das es nicht einfacher geht. Und auch in diesem Fall gibt es mal wieder eine magic-number – in diesem Fall die 2 als Wert für die DefaultCategory. Besser müsste man ja sagen Default-Category-Root, denn es ist der Einstiegspunkt in den “Default”-Kategorien-Baum. Man muss noch ein wenig mitschreiben was man tatsächlich gefunden hat und welche Kategorien aus Magento nicht mehr benötigt werden.

function compareMagentoRecursive($parentIdDb = null,$parentMagento = 2){
        $backend = $this->getBackendCategoriesForParentFromDb($parentIdDb);
        $magento = $this->getMagentoCategoryByParent($parentMagento);
        $usedMagentoCats = array();
        foreach ($backend as $id => $category){
            foreach ($magento as $magCat){
                if($magCat->name == $category['name']){
                    $this->mapping[$id] = $magCat->id;
                    $usedMagentoCats[$magCat->id]=$magCat->id;
                    $this->compareMagentoRecursive($id,$magCat->id);
                }
            }
            if(!isset($this->mapping[$id])){
                $this->createMagentoCat($category,$parentMagento);
            }
        }
        $this->removeMagentoCatsNotInList($magento,$usedMagentoCats);
    }

Der REST-Aufruf für die Elemente einer Kategorie lautet wie folgt:

function getMagentoCategoryByParent($parentId = 2)
    {
    curl_setopt($this->curl, CURLOPT_URL, $baseUrl . "/V1/categories?rootCategoryId=".$parentId. "&depth=1");
    curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, "GET");
    $levelContent = json_decode(curl_exec($this->curl));
    return $levelContent->children_data;
}

Löschen einer Kategorie in Magento ist vergleichsweise einfach wenn man die Id kennt:

curl_setopt($this->curl, CURLOPT_URL, $baseUrl. "/V1/categories/".$category->id);
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, "DELETE");
$result = curl_exec($this->curl);

Ebenso das Anlegen einer Kategorie

function createMagentoCat($backendCat,$magentoParent){
        $cat = json_encode(
                array( "category" =>
                    array(
                            'parentId' => $magentoParent,
                            'name' => $backendCat['name'],
                            'isActive' => true,
                            'IncludeInMenu' => true,
                        )
                )
            );
        curl_setopt($this->curl, CURLOPT_URL, $baseUrl . "/V1/categories");
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $cat);
        curl_exec($this->curl);
}

Kombiniert man das alles entsprechend, so kann man recht schnell einen Kategoriebaum in Magento anlegen und ihn anhand einer Vorgabe aktualisieren. Es ist dabei unerheblich ob in einer Kategorie bereits Produkte enthalten sind. Diese Verknüpfung entfernt Magento beim Löschen der Kategorie automatisch. Das geschieht unschöner Weise in der Business-Logik von Magento, ich würde es deutlich bevorzugen, wenn es direkt auf Basis der Foreign-Keys in der Datenbank (Stichwort: on delete cascade) erfolgen würde. Aber so lange es funktioniert soll es mir ja recht sein.