Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Eigene Versandarten in Magento 2: Grundlagen

Eigene Versandarten in Magento 2: Grundlagen

~6 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026

Kapitel 62-65 haben eine Zahlungsart Schritt für Schritt über eine moderne, komponierte Adapter-Facade gebaut. Versandarten ("Carrier" in Magentos eigener Terminologie) laufen technisch anders - näher am alten AbstractMethod-Weg aus Kapitel 62, aber mit eigenen Besonderheiten.

AbstractCarrier und CarrierInterface

Jede Versandart erbt von Magento\Shipping\Model\Carrier\AbstractCarrier und implementiert CarrierInterface - bis Magento 2.4.8 gibt es dafür kein Adapter-Facade-Pendant wie bei Zahlungsarten. Der Methodencode lebt weiterhin in einer klassischen protected-Property ($_code), nicht in einer per di.xml-const-Argument injizierten Konstante. Zwei Methoden sind Pflicht:

  • collectRates(RateRequest $request) - die eigentliche Kalkulation, liefert entweder ein befülltes Magento\Shipping\Model\Rate\Result-Objekt (Kapitel 68) oder false, wenn die Versandart für diese Anfrage nicht infrage kommt.
  • getAllowedMethods() - ein assoziatives Array aller von diesem Carrier angebotenen Methodencodes, u. a. von der Admin-Konfigurationsseite und Vergleichs-Tools wie Table Rate genutzt, unabhängig davon, ob collectRates() im konkreten Request überhaupt etwas zurückliefert.
app/code/Mironsoft/Loyalty/Model/Carrier/FreeShippingByPoints.php (Gerüst)
<?php

declare(strict_types=1);

namespace Mironsoft\Loyalty\Model\Carrier;

use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Rate\Result;

/**
 * Skeleton only - chapter 67 fills in the business logic. Note the carrier code
 * lives in a plain protected property, not a class constant fed through di.xml
 * like the payment facade in chapter 62: shipping carriers have no Adapter-style
 * facade equivalent, even in Magento 2.4.8 - AbstractCarrier is still the only,
 * property-based way in.
 */
class FreeShippingByPoints extends AbstractCarrier implements CarrierInterface
{
    /**
     * Carrier code, referenced by carriers/mironsoft_loyalty_freeshipping/* config paths.
     */
    protected $_code = 'mironsoft_loyalty_freeshipping';

    /**
     * Calculates shipping rates for the given request. Required by CarrierInterface.
     *
     * @param RateRequest $request Shipping rate request
     * @return Result|bool
     */
    public function collectRates(RateRequest $request)
    {
        // see chapter 67
    }

    /**
     * Returns the codes and titles of all shipping methods this carrier can offer.
     * Required by AbstractCarrier, used e.g. by the admin's "Applicable Countries"
     * comparison tooling.
     *
     * @return string[]
     */
    public function getAllowedMethods(): array
    {
        return ['freeshipping' => $this->getConfigData('name')];
    }
}

Registrierung über das model-Feld in config.xml

Genau wie bei der Zahlungsart aus Kapitel 62 bestimmt kein di.xml-virtualType, welche Klasse für einen Carrier-Code instanziiert wird, sondern ein model-Konfigurationswert unter carriers/<code>/model in etc/config.xml - dieselbe Registrierungs-Idee, nur unter einem anderen Config-Wurzelknoten (carriers statt payment):

app/code/Mironsoft/Loyalty/etc/config.xml (Ausschnitt, ergänzt Kapitel 62)
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <carriers>
            <mironsoft_loyalty_freeshipping>
                <active>0</active>
                <model>Mironsoft\Loyalty\Model\Carrier\FreeShippingByPoints</model>
                <name>Kostenloser Versand durch Punkte</name>
                <title>Mironsoft Loyalty</title>
                <points_cost>200</points_cost>
                <sallowspecific>0</sallowspecific>
                <sort_order>10</sort_order>
            </mironsoft_loyalty_freeshipping>
        </carriers>
    </default>
</config>

Tipp: Magento\Shipping\Model\Config::getActiveCarriers() liest genau diese carriers/*/active- und carriers/*/model-Werte aus und instanziiert jeden aktiven Carrier über den ObjectManager - konzeptionell derselbe Mechanismus wie Magento\Payment\Helper\Data::getMethodInstance() bei Zahlungsarten, nur ohne den zusätzlichen Adapter/ValueHandlerPool-Umweg aus Kapitel 62.

Achtung: sallowspecific und specificcountry sind keine kosmetischen Zusatzfelder - sie steuern, ob eine Versandart überhaupt an bestimmte Länder liefern darf, und werden von AbstractCarrier::checkAvailableShipCountries() ausgewertet. Fehlen sie in system.xml (Kapitel 67), lässt sich die Länderbeschränkung im Admin schlicht nicht konfigurieren, auch wenn der PHP-Code sie später korrekt auswertet.

Mit Grundlagen und Registrierung geklärt, baut Kapitel 67 die eigentliche Geschäftslogik: kostenloser Versand, freigeschaltet durch ausreichend Treuepunkte.