Add Videos to Magento Products Programmatically – How to

magento2magento2.2productvideo

I know this question has been asked before:

but I need something different.
The answers in the questions linked above suggest using some core methods that (all of them) load the full product and save the full product, either via repository or via the load/save deprecated methods.
I have a lot of products. Somewhere between 5k and 10k.
Going through all of them with load/save it is not really a viable option.

Any other suggestions?

Best Answer

I ended up doing it with the risky inserts directly into the tables.

the tables involved are (in this order)

  • catalog_product_entity_media_gallery
  • catalog_product_entity_media_gallery_value
  • catalog_product_entity_media_gallery_value_to_entity
  • catalog_product_entity_media_gallery_value_video

Pre-explanations: This should happen inside one class.
This class has these members that are added via constructor (di will take care of instantiating them)

// \Magento\Framework\App\ResourceConnection
private $resourceConnection;
// \Magento\Catalog\Api\ProductAttributeRepositoryInterface
private $attributeRepository;

Let's take the tables 1 by 1:

catalog_product_entity_media_gallery

$mediaAttributeId = $this->attributeRepository->get('media_gallery')->getAttributeId();
$image = 'someImage.jpg'; //This is the preview image of the video. the image needs to exist in `/media/catalog/product/`. I'm not going to cover how you add it there
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery');
$data = [
    'attribute_id' => $mediaAttributeId,
    'value' => $image,
    'media_type' => \Magento\ProductVideo\Model\Product\Attribute\Media\ExternalVideoEntryConverter::MEDIA_TYPE_CODE,
    'disabled' => 0
];
$this->resourceConnection->getConnection()->insert($table, $data);

Now remember the last added increment id because it is needed in the later inserts.

$valueId = $this->resourceConnection->getConnection()->lastInsertId();

catalog_product_entity_media_gallery_value

$storeId = the store id for witch the video is available. Use 0 for global;
$productId = the id of the product for which you add the video
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery_value');
$data = [
    'value_id' => $valueId, //the increment id from above
    'store_id' => $storeId,
    'entity_id' => $productId,
    'position' => 1, //any number goes here
    'disabled' => 0
];
$this->resourceConnection->getConnection()->insert($table, $data);

catalog_product_entity_media_gallery_value_to_entity

$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery_value_to_entity');
$data = [
    'value_id' => $valueId, // increment id from above
    'entity_id' => $productId, // product id from the step above
];
$this->resourceConnection->getConnection()->insert($table, $data);

catalog_product_entity_media_gallery_value_video

$videoUrl = 'url of the video from youtube or vimeo';  
$table = $this->resourceConnection->getTableName('catalog_product_entity_media_gallery_value_video');
$data = [
    'value_id' => $valueId, //saved increment id from above
    'store_id' => $storeId, // Store id from the steps above
    'provider' => '',
    'url' => $videoUrl,
    'title' => "Video title", //this is mandatory
    'description' => 'Video description', //this can be empty
    'metadata' => '' //I have no idea what this does
];
$this->resourceConnection->getConnection()->insert($table, $data);

That's it. Some reindexing may be needed.

Related Topic