Drupal Commerce

  • Drupal 8: Change Commerce Product Variation URL to SKU

    To pull this off, we need to write a custom module. Let's name our module commerce_variation_sku. In our commerce_variation_sku.module file, we need implement the hook hook_entity_type_build to change the entity class and entity storage class to our custom classes. /** * Implements hook_entity_type_build(). */ function commerce_variation_sku_entity_type_build(array &$entity_types) { if (isset($entity_types['commerce_product_variation'])) { $entity_types['commerce_product_variation']->setClass('Drupal\commerce_variation_sku\Entity\ProductVariation'); $entity_types['commerce_product_variation']->setStorageClass('Drupal\commerce_variation_sku\ProductVariationStorage'); } } Next, we create our custom entity class that will extend the original entity class. <?php namespace Drupal\commerce_variation_sku\Entity; use Drupal\Core\Url; use Drupal\commerce_product\Entity\ProductVariation as ProductVariationBase; class ProductVariation extends ProductVariationBase { /** * {@inheritdoc} */ public function toUrl($rel = 'canonical', array $options = []) { // Product variation URLs depend on the parent product. if (!$this->getProductId()) { // RouteNotFoundException tells EntityBase::uriRelationships() // to skip this product variation's link relationships. throw new RouteNotFoundException(); } // StringFormatter assumes 'revision' is always a valid link template. if (in_array($rel, ['canonical', 'revision'])) { $route_name = 'entity.commerce_product.canonical'; $route_parameters = [ 'commerce_product' => $this->getProductId(), ]; $options += [ 'query' => [ 'sku' => $this->getSku(), ], 'entity_type' => 'commerce_product', 'entity' => $this->getProduct(), // Display links by default based on the current language. 'language' => $this->language(), ]; return new Url($route_name, $route_parameters, $options); } else { return parent::toUrl($rel, $options); } } }   Then we create our custom entity storage class that again extends the original entity storage class. <?php namespace Drupal\commerce_variation_sku; use Drupal\commerce_product\Entity\ProductInterface; use Drupal\commerce_product\ProductVariationStorage as ProductVariationStorageBase; /** * Defines the product variation storage. */ class ProductVariationStorage extends ProductVariationStorageBase { /** * {@inheritdoc} */ public function loadFromContext(ProductInterface $product) { $current_request = $this->requestStack->getCurrentRequest(); if ($sku = $current_request->query->get('sku')) { $variation = $this->loadBySku($sku); if (in_array($variation->id(), $product->getVariationIds())) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ if ($variation->isPublished() && $variation->access('view')) { return $variation; } } } return $product->getDefaultVariation(); } } Last step is to clear your cache and you're good to go 😀