The goal of a module I'm currently developing is to add a custom image type called "opengraph_image". I added a new EAV attribute though my InstallData.php script which works fine. When I now login into the Magento2 backend and alter a product I can choose the image type "opengraph_image" while uploading or editing product images.
However, on the frontend I would like to display this image. Therefore I created a etc/view.xml file in my module with the following content:
<?xml version="1.0"?>
<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Esites_SEO:etc/custom.xsd">
<media>
<images module="Magento_Catalog">
<image id="opengraph_image" type="opengraph_image">
<width>265</width>
<height>265</height>
</image>
</images>
</media>
</view>
But now I get the following error:
Invalid XML in file /var/www/html/vhosts/magento2/app/code/Esites/SEO/etc/view.xml:
Element 'image', attribute 'type': [facet 'enumeration'] The value 'opengraph_image' is not an element of the set {'thumbnail', 'small_image', 'image', 'swatch_image', 'swatch_thumb'}.
Line: 5
Element 'image', attribute 'type': 'opengraph_image' is not a valid value of the local atomic type.
Line: 5
The reason is it doesn't seem to load my custom.xsd located in: app/code/Esites/SEO/etc/custom.xsd where I define the opengraph_image. Instead it seems to just load it's default XSD file: vendor/magento/framework/Config/etc/view.xsd
The content of my custom.xsd is a copy (for testing purposes) of this original view.xsd where I added the following on line 75:
<xs:enumeration value="opengraph_image"/>
The frontend does work without errors if I include the line above in the original view.xsd file. I followed the documentation on: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/build/XSD-XML-validation.html and my paths are build according to the information on that page. Cache is cleared multiple times.
What am I missing?
4 Answers 4
Magento2 loads default view.xsd because ConfigView Reader using lib/internal/Magento/Framework/Config/SchemaLocator.php and it returns default view.xsd
$this->schema = $urnResolver
->getRealPath('urn:magento:framework:Config/etc/view.xsd');`
I was able to override it by follow steps below:
- Create new extension for example Magento_SampleMinimal
Create the plugin definition in
{MODULE}/etc/di.xml<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Framework\Config\SchemaLocator"> <plugin name="SampleMinimal_SchemaLocator" type="Magento\SampleMinimal\Model\Plugin\SchemaLocator" sortOrder="1"/> </type> </config>Create plugin in {MODULE}/Model/Plugin/SchemaLocator.php
<?php namespace Magento\SampleMinimal\Model\Plugin; use Magento\TestFramework\ObjectManager; class SchemaLocator { /** * After Get Schema * * @param \Magento\Framework\Config\SchemaLocator $schemaLocator * @param string $result * @return array */ public function afterGetSchema(\Magento\Framework\Config\SchemaLocator $schemaLocator, $result) { $result = sprintf(realpath(__DIR__ . '/../../etc/view.xsd')); return $result; } }Update For Magento 2.0. version
- Copy
lib/internal/Magento/Framework/Config/etc/view.xsdto{MODULE}/etc/view.xsd
For Magento 2.1. version,
Copy Vendor/Magento/Framework/Config/etc/view.xsd to {MODULE}/etc/view.xsd
* Edit {MODULE}/etc/view.xsd and add new type of media_attribute
-
Are you serious.. Is this the only way? Seems overkill, and probably ridiculous that you can't add your own image without overwriting core XSDErfan– Erfan2017年07月05日 10:11:57 +00:00Commented Jul 5, 2017 at 10:11
-
That's the right solution. Thanks heaps for that Yaroslav.medina– medina2017年12月04日 22:51:54 +00:00Commented Dec 4, 2017 at 22:51
-
This is great thank you! However, I would recommend writing the Plugin around
Magento\Framework\Config\Dom\UrnResolveras there are places that use it directly instead of going throughSchemaLocator.quickshiftin– quickshiftin2018年11月20日 22:37:59 +00:00Commented Nov 20, 2018 at 22:37
There is a simpler way than Yaroslav's answer. It is possible to change the constructor parameters to SchemaLocator in your module's di.xml. Like:
<type name="Magento\Framework\Config\SchemaLocator" >
<arguments>
<argument name="realPath" xsi:type="string">urn:magento:module:VendorName_ModuleName:etc/view.xsd</argument>
</arguments>
</type>
No need for a Plugin.
-
Beware, that solution works only if you have $realPath as argument in SchemaLocator. Depends on Magento 2 version.Pol Ravalitera– Pol Ravalitera2019年06月07日 13:36:09 +00:00Commented Jun 7, 2019 at 13:36
This seems to be a design flaw, in combination with a Magento 2 bug. I've created a bug report here: https://github.com/magento/magento2/issues/10161
If you're using the image builder directly in a template to output the opengraph_image, a better solution is to pass in custom attributes (using Magento\Catalog\Block\Product\ImageBuilder::setAttributes, or the third parameter of Magento\Catalog\Block\Product\View::getImage).
However, that won't work (given my bugreport), so you'll still have to override the ImageBuilder's create method to pass in those attributes to the Catalog Image Helper.
You don't need to modify or override view.xsd, this file is just for validation.
I've recently implemented a my solution by doing the following:
Create an image catalog attribute (let's say that the new attribute ID 162). Once you created the attribute you'll be able to apply it on any catalog image. Now you must apply to it the right model and front end visibility. You can do it programmatically or following this guide.
Open your database with phpMyAdmin or MySQL and try to mirror any system attribute like small_image
use magento2_database_name; SELECT * FROM `eav_attribute`; UPDATE `magento2_database_name`.`eav_attribute` SET `frontend_model` = 'Magento\\Catalog\\Model\\Product\\Attribute\\Frontend\\Image' WHERE `eav_attribute`.`attribute_id` =162; SELECT * FROM `catalog_eav_attribute`; UPDATE `magento2_database_name`.`catalog_eav_attribute` SET `is_visible` = '1', 'using_in_product_listing' = '1' WHERE `catalog_eav_attribute`.`attribute_id` =162;Go to
www_root/magento2_root/app/design/frontend/Theme/package/etc/view.xmland add your new image type:<image id="opengraph_image" type="opengraph_image"> <width>265</width> <height>265</height> </image>- Update template files by adding the new image type on
www_root/magento2_root/app/design/frontend/Theme/package/Magento_Catalog/templates/product/ - Clean your cache and you'll see it on front end.
It worked for me for a hover image on category product listing, hope this help.
-
thx 7ochem, It's my first real post.JROCA22– JROCA222017年02月18日 11:32:56 +00:00Commented Feb 18, 2017 at 11:32
-
This solution does not work as Magento is actively validating the XSDbarbazul– barbazul2017年05月23日 18:51:30 +00:00Commented May 23, 2017 at 18:51
-
@barbazul that's only if you're in developer mode if I recall correctly..Erfan– Erfan2017年07月06日 05:37:54 +00:00Commented Jul 6, 2017 at 5:37
-
@Erfan It could be. I haven't checked, honestly. But still, it is a sign that it's not how you are supposed to do it or that there is something wrong in that particular XSDbarbazul– barbazul2017年07月06日 15:17:45 +00:00Commented Jul 6, 2017 at 15:17
-
Maybe it's not the best practice but it worked for meJROCA22– JROCA222018年01月20日 15:00:58 +00:00Commented Jan 20, 2018 at 15:00
module="Magento_Catalog"tomodule="Esites_SEO"?