Eigene Felder an Produkt, Kategorie oder Kunde anhängen
Eigene Felder an Produkt, Kategorie oder Kunde anhängen
~8 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
Kapitel 8 hat das Muster an einem Produktbeispiel eingeführt. Dieses Kapitel zeigt drei konkrete, in der Praxis besonders häufige Erweiterungspunkte im Detail - inklusive der jeweiligen Stolperfallen bei $value.
Kategorie: eigenes Banner-Feld
extend type CategoryInterface {
mironsoft_banner_image: String
@resolver(class: "Mironsoft\\GraphqlDemo\\Model\\Resolver\\Category\\BannerImage")
@doc(description: "URL of a custom marketing banner shown above the category grid")
}Anders als bei Produkten heißt der Basistyp hier bewusst CategoryInterface, nicht Category - Magento nennt seine Typen nicht immer konsistent, ein Blick in die Introspection (Kapitel 3) oder in vendor/magento/module-catalog-graph-ql/etc/schema.graphqls schafft hier schnell Klarheit, bevor extend type ins Leere läuft.
<?php
declare(strict_types=1);
namespace Mironsoft\GraphqlDemo\Model\Resolver\Category;
use Magento\Catalog\Model\Category;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
/**
* Resolves the custom mironsoft_banner_image field on categories.
*/
class BannerImage implements ResolverInterface
{
/**
* Reads the mironsoft_banner_image attribute off the resolved category model.
*
* @param Field $field Resolved GraphQL field configuration
* @param mixed $context Resolver context
* @param ResolveInfo $info GraphQL resolve tree info
* @param array|null $value Parent CategoryInterface resolver's value
* @param array|null $args Arguments passed to this field
* @return string|null
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
?array $value = null,
?array $args = null
): ?string {
/** @var Category|null $category */
$category = $value['model'] ?? null;
$bannerImage = $category?->getData('mironsoft_banner_image');
return is_string($bannerImage) && $bannerImage !== ''
? $bannerImage
: null;
}
}Kunde: eigene Präferenz auslesen
CustomerOutput - der Rückgabetyp der customer-Query - ist ein besonders sensibler Erweiterungspunkt, weil er praktisch immer personenbezogene Daten trägt. Der Resolver bekommt hier nicht automatisch die eigene Kunden-ID mitgeliefert - er muss sie explizit aus dem Context lesen, genau wie später die geschützte Favoriten-Mutation in Kapitel 18:
extend type CustomerOutput {
mironsoft_newsletter_topic: String
@resolver(class: "Mironsoft\\GraphqlDemo\\Model\\Resolver\\Customer\\NewsletterTopic")
@doc(description: "The customer's preferred newsletter topic")
}Auch hier landet in der Praxis meist ein Wert aus $value['model'] (dem geladenen \Magento\Customer\Model\Customer) im Resolver - Magentos eigener CustomerOutput-Resolver liefert das geladene Kundenmodell bereits unter diesem Schlüssel weiter.
Wann lohnt sich ein neues EAV-Attribut statt eines GraphQL-Feldes?
Bei Produkten und Kategorien liegt die Versuchung nahe, jedes neue Feld direkt als eigenes EAV-Attribut über eav_attribute anzulegen und per Admin-Formular pflegbar zu machen. Das lohnt sich, wenn der Wert tatsächlich redaktionell im Adminbereich gepflegt werden soll (siehe die Admin-Grids-&-Formulare-Serie). Für rein berechnete Werte - etwa mironsoft_badge_text aus Kapitel 8, das aus vorhandenen Daten abgeleitet wird - reicht ein reiner GraphQL-Resolver ohne eigenes Datenbank-Attribut völlig aus.
Achtung: extend type auf einem Core-Typ, der intern per Batch-Resolver arbeitet (z. B. Preisfelder bei Produkten), kann bei einem naiven, nicht-batchenden eigenen Feld schnell zum N+1-Flaschenhals werden - eine Liste von 50 Produkten löst dann 50 einzelne zusätzliche Datenbankabfragen für das eigene Feld aus. Kapitel 20 zeigt am Veranstaltungen-Projekt, wie sich das mit Batch-Resolvern vermeiden lässt - dasselbe Muster funktioniert auch für erweiterte Core-Typen.
Kapitel 10 schließt Block 3 ab und geht noch einmal grundlegend auf jeden der vier Parameter von resolve() ein - Wissen, das für die eigene Veranstaltungen-API ab Block 4 vorausgesetzt wird.