2

I am using Commerce with Marketplace, and am using the Shipping module.

In my commerce marketplace, users become sellers via a custom form, where I create the store entity on submit. Currently, to attach a shipping method, it has to be done in commerce admin via a checkbox:

Shipping method admin screen

My marketplace can have an unlimited number of stores, making management of them via checkboxes unfeasible. How can I add a shipping method to a store? There's a table commerce_shipping_method__stores:

enter image description here

Can I simply make an insert into this table and set the stores_target_id value to the new store id after the new store is created?

1 Answer 1

2
+100

With custom module code, you can add a new store like this:

function mymodule_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  if ($entity instanceof Drupal\commerce_store\Entity\StoreInterface) {

      $sm_id = 1; // I can see Shipping Method ID is 1 from your table screenshot
      $shipping_method = Drupal\commerce_shipping\Entity\ShippingMethod::load($sm_id);
      $store_ids = $shipping_method->getStoreIds(); // get existing IDs
      $new_store_id = $entity->id(); // get new id
      $store_ids[] = $new_store_id; // add new to existing
      $shipping_method->setStoreIds($store_ids); // set
      $shipping_method->save();

  }

}

In the above code, when a store is created, it automatically adds it to the shipping method.


But if your question is to add already existing stores to the shipping method, then run this code only once:

      $sm_id = 1; // I can see Shipping Method ID is 1 from your table screenshot
      $shipping_method = Drupal\commerce_shipping\Entity\ShippingMethod::load($sm_id);
      $store_ids = [1, 2, 3, 4, 5, 6]; // Array of all the store IDs that belong to this shipping method.
      $shipping_method->setStoreIds($store_ids); // set
      $shipping_method->save();

The better API solution

Thanks to 4k4's answer I was able to commeup with a more efficient solution.

function mymodule_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  if ($entity instanceof Drupal\commerce_store\Entity\StoreInterface) {

      $sm_id = 1; // I can see Shipping Method ID is 1 from your table screenshot
      $shipping_method = Drupal\commerce_shipping\Entity\ShippingMethod::load($sm_id);
      $new_store_id = $entity->id(); // get new id
      $shipping_method->{'stores'}[] = $new_store_id; // appends new store to existing list.
      $shipping_method->save();

  }

}

Manual Solution

Quick follow up, do I have to load all the stores at once? When I have 1000+ stores and more, that seems like it will be a little resource intensive. Is it possible to just add the new store?

At this point, you wouldn't want to use the entity API and do Drupal\commerce_shipping\Entity\ShippingMethod::load as this would contain all the 1000+ store IDs, you will have to manually DB query & insert:

function mymodule_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  if ($entity instanceof Drupal\commerce_store\Entity\StoreInterface) {

    $sm_id = 1; // Shipping Method ID
    $connection = \Drupal::database();

    $query = $connection->select('commerce_shipping_method__stores', 'csms');
    $query->range(0, 1)
      ->orderBy('delta', 'DESC')
      ->condition('csms.entity_id', $sm_id)
      ->addField('csms', 'delta');
    $last_delta = $query->execute()->fetchField();
    $new_delta = $last_delta + 1;
    $new_store_id = $entity->id(); // new store ID

    $insert = $connection->insert('commerce_shipping_method__stores')
      ->fields([
        'entity_id' => $sm_id,
        'stores_target_id' => $new_store_id,
        'revision_id' => $sm_id,
        'delta' => $new_delta,
        'bundle' => 'commerce_shipping_method',
        'langcode' => 'en',
      ])
      ->execute();

    $storage = \Drupal::entityTypeManager()
      ->getStorage('commerce_shipping_method');
    $storage->resetCache([$sm_id]); // Flush Cache

  }

}
2
  • Quick follow up, do I have to load all the stores at once? When I have 1000+ stores and more, that seems like it will be a little resource intensive. Is it possible to just add the new store?
    – vintorg
    Aug 18, 2020 at 23:10
  • Good point, updated answer.
    – No Sssweat
    Aug 19, 2020 at 3:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.