Add videos to products programatically
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.
I don't like to overrule Marius' opinion because the answer he's given is really excellent & actually works! However, if you or your company isn't so inclined to run direct SQL queries like that I'd suggest something more like this, using Magento 2's API:
$data = [
'entry' => [
'id' => null,
'media_type' => 'external-video',
'label' => null,
'position' => $IntToRepresentWhereInGalleryToPlaceIt,
'types' => ['image', 'small-image', 'thumbnail'],
'disabled' => false,
'content' => [
'base64_encoded_data' => base64_encode(file_get_contents($thumbnailimageUrl)),
'type' => 'image/jpeg',
'name' => '0.jpg'
],
'extension_attributes' => [
'video_content' => [
'media_type' => 'external-video',
'video_provider' => 'youtube',
'video_url' => $videoURL,
'video_title' => $videoTitle,
'video_description' => $videoDescription,
'video_metadata' => null //Don't know what this is for, add a value if you like
]
]
]
];
$ch = curl_init("http://YOURURL.COM/index.php/rest/V1/products/" . $YourProductSku . "/media");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . $MagentoIntegrationsAccessToken));
$response = curl_exec($ch);