ConfigurableProduct: How to get the configurable products out of stock?
I want to show the all attributes from my configurable product on my select. I followed this tutorial: Magento 2.2 How to show out of stock in configurable product, with some changes and fixes.
Well, my module is like this now:
Vendor/ConfigurableProduct/etc/di.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoSwatchesBlockProductRendererConfigurable" type="VendorConfigurableProductBlockProductViewTypeConfigurable" />
<preference for="MagentoConfigurableProductModelConfigurableAttributeData" type="VendorConfigurableProductModelRewriteConfigurableAttributeData" />
<preference for="MagentoConfigurableProductHelperData" type="VendorConfigurableProductHelperData" />
</config>
Vendor/ConfigurableProduct/Block/ConfigurableProduct.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductBlock;
use MagentoFrameworkViewElementTemplate;
class ConfigurableProduct extends Template
{
protected $_storeManager;
public function __construct(
MagentoFrameworkViewElementTemplateContext $context,
array $data =
){
parent::__construct($context, $data);
$this->_storeManager = $context->getStoreManager();
}
}
Vendor/ConfigurableProduct/Block/Product/View/Type/Configurable.php
<?php
namespace VendorConfigurableProductBlockProductViewType;
uses...
class Configurable extends MagentoSwatchesBlockProductRendererConfigurable
{
public function beforeSetTemplate(
MagentoSwatchesBlockProductRendererConfigurable $subject,
$template
) {
return ['Vendor_ConfigurableProduct::configurable.phtml'];
}
public function beforeSetName(MagentoCatalogModelProduct $subject, $name)
{
return ['(' . $name . ')'];
}
public function __construct(
Context $context,
ArrayUtils $arrayUtils,
EncoderInterface $jsonEncoder,
Data $helper,
CatalogProduct $catalogProduct,
CurrentCustomer $currentCustomer,
PriceCurrencyInterface $priceCurrency,
ConfigurableAttributeData $configurableAttributeData,
SwatchData $swatchHelper,
Media $swatchMediaHelper,
array $data =
){
$this->swatchHelper = $swatchHelper;
$this->swatchMediaHelper = $swatchMediaHelper;
parent::__construct(
$context,
$arrayUtils,
$jsonEncoder,
$helper,
$catalogProduct,
$currentCustomer,
$priceCurrency,
$configurableAttributeData,
$swatchHelper,
$swatchMediaHelper,
$data
);
}
public function getJsonConfig()
{
$store = $this->getCurrentStore();
$currentProduct = $this->getProduct();
$regularPrice = $currentProduct->getPriceInfo()->getPrice('regular_price');
$finalPrice = $currentProduct->getPriceInfo()->getPrice('final_price');
$options = $this->helper->getOptions($currentProduct, $this->getAllowProducts());
$attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options);
$config = [
'attributes' => $attributesData['attributes'],
'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()),
'optionPrices' => $this->getOptionPrices(),
'optionStock' => $this->getOptionStocks(),
'prices' => [
'oldPrice' => [
'amount' => $this->_registerJsPrice($regularPrice->getAmount()->getValue()),
],
'basePrice' => [
'amount' => $this->_registerJsPrice(
$finalPrice->getAmount()->getBaseAmount()
),
],
'finalPrice' => [
'amount' => $this->_registerJsPrice($finalPrice->getAmount()->getValue()),
],
],
'productId' => $currentProduct->getId(),
'chooseText' => __('Choose an Option...'),
'images' => isset($options['images']) ? $options['images'] : ,
'index' => isset($options['index']) ? $options['index'] : ,
];
if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) {
$config['defaultValues'] = $attributesData['defaultValues'];
}
$config = array_merge($config, $this->_getAdditionalConfig());
return $this->jsonEncoder->encode($config);
}
/*-----------------------custom code----------------------*/
protected function getOptionStocks()
{
$stocks = ;
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$stockObject=$objectManager->get('MagentoCatalogInventoryApiStockRegistryInterface');
foreach ($this->getAllowProducts() as $product) {
$productStockObj = $stockObject->getStockItem($product->getId());
$isInStock = $productStockObj['is_in_stock'];
$stocks[$product->getId()] = ['stockStatus' => $isInStock];
}
return $stocks;
}
public function getAllowProducts()
{
if (!$this->hasAllowProducts()){
$skipSaleableCheck = 1;
$products = $skipSaleableCheck ?
$this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null) :
$this->getProduct()->getTypeInstance()->getSalableUsedProducts($this->getProduct(), null);
$this->setAllowProducts($products);
}
return $this->getData('allow_products');
}
public function getAllowAttributes()
{
return $this->getProduct()->getTypeInstance()->getConfigurableAttributes($this->getProduct());
}
}
> Vendor/ConfigurableProduct/Helper/Data.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductHelper;
use MagentoCatalogModelProduct;
/**
* Class Data
* Helper class for getting options
*
*/
class Data extends MagentoConfigurableProductHelperData
{
/**
* Get Options for Configurable Product Options
*
* @param MagentoCatalogModelProduct $currentProduct
* @param array $allowedProducts
* @return array
*/
public function getOptions($currentProduct, $allowedProducts)
{
$options = ;
foreach ($allowedProducts as $product) {
$productId = $product->getId();
$images = $this->getGalleryImages($product);
if ($images) {
foreach ($images as $image) {
$options['images'][$productId] =
[
'thumb' => $image->getData('small_image_url'),
'img' => $image->getData('medium_image_url'),
'full' => $image->getData('large_image_url'),
'caption' => $image->getLabel(),
'position' => $image->getPosition(),
'isMain' => $image->getFile() == $product->getImage(),
];
}
}
foreach ($this->getAllowAttributes($currentProduct) as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$productAttributeId = $productAttribute->getId();
$attributeValue = $product->getData($productAttribute->getAttributeCode());
$options[$productAttributeId][$attributeValue] = $productId;
$options['index'][$productId][$productAttributeId] = $attributeValue;
}
}
return $options;
}
/**
* Get allowed attributes
*
* @param MagentoCatalogModelProduct $product
* @return array
*/
public function getAllowAttributes($product)
{
return $product->getTypeInstance()->getConfigurableAttributes($product);
}
}
Vendor/ConfigurableProduct/Model/Rewrite/ConfigurableAttributeData.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductModelRewrite;
use MagentoCatalogModelProduct;
use MagentoConfigurableProductModelProductTypeConfigurableAttribute;
class ConfigurableAttributeData extends MagentoConfigurableProductModelConfigurableAttributeData
{
protected $eavConfig;
public function __construct(MagentoEavModelConfig $eavConfig)
{
$this->eavConfig = $eavConfig;
}
/**
* Get product attributes
*
* @param Product $product
* @param array $options
* @return array
*/
public function getAttributesData(Product $product, array $options = )
{
$defaultValues = ;
$attributes = ;
$attrs = $product->getTypeInstance()->getConfigurableAttributes($product);
foreach ($attrs as $attribute) {
$attributeOptionsData = $this->getAttributeOptionsData($attribute, $options);
if ($attributeOptionsData) {
$productAttribute = $attribute->getProductAttribute();
$attributeId = $productAttribute->getId();
$attributes[$attributeId] = [
'id' => $attributeId,
'code' => $productAttribute->getAttributeCode(),
'label' => $productAttribute->getStoreLabel($product->getStoreId()),
'options' => $attributeOptionsData,
'position' => $attribute->getPosition(),
];
$defaultValues[$attributeId] = $this->getAttributeConfigValue($attributeId, $product);
}
}
return [
'attributes' => $attributes,
'defaultValues' => $defaultValues,
];
}
public function getAttributeOptionsData($attribute, $config)
{
$attributeOptionsData = ;
$attributeId = $attribute->getAttributeId();
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$eavModel = $objectManager->create('MagentoCatalogModelResourceModelEavAttribute');
$attr = $eavModel->load($attributeId);
$attributeCode=$eavModel->getAttributeCode();
$attribute = $this->eavConfig->getAttribute('catalog_product', $attributeCode);
$options = $attribute->getSource()->getAllOptions();
foreach ($options as $attributeOption) {
$optionId = $attributeOption['value'];
$attributeOptionsData = [
'id' => $optionId,
'label' => $attributeOption['label'],
'products' => isset($config[$attribute->getAttributeId()][$optionId])
? $config[$attribute->getAttributeId()][$optionId]
: ,
];
}
return $attributeOptionsData;
}
/**
* Retrieve configurable attributes data
*
* @param MagentoCatalogModelProduct $product
* @return MagentoConfigurableProductModelProductTypeConfigurableAttribute
*/
public function getConfigurableAttributes($product)
{
MagentoFrameworkProfiler::start(
'CONFIGURABLE:' . __METHOD__,
['group' => 'CONFIGURABLE', 'method' => __METHOD__]
);
if (!$product->hasData($this->_configurableAttributes)) {
$configurableAttributes = $this->getConfigurableAttributeCollection($product);
$this->extensionAttributesJoinProcessor->process($configurableAttributes);
$configurableAttributes->orderByPosition()->load();
$product->setData($this->_configurableAttributes, $configurableAttributes);
}
MagentoFrameworkProfiler::stop('CONFIGURABLE:' . __METHOD__);
return $product->getData($this->_configurableAttributes);
}
}
Vendor/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options.wrapper">
<action method='setTemplate'>
<argument name="template" xsi:type="string">Vendor_ConfigurableProduct::configurable.phtml</argument>
</action>
<!--<argument name="class" xsi:type="string">VendorConfigurableProductBlockProductViewTypeConfigurable</argument>-->
</referenceBlock>
</body>
</page>
Vendor/ConfigurableProduct/view/frontend/templates/configurable.phtml
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var $block VendorConfigurableProductBlockProductViewTypeConfigurable */
$_product = $block->getProduct();
$_attributes = $block->decorateArray($block->getAllowAttributes());
?>
<!-- TODO: custom layout -->
<?php if ($_product->isSaleable() && count($_attributes)):?>
<?php foreach ($_attributes as $_attribute): ?>
<div class="field configurable required">
<label class="label" for="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>">
<span><?= $block->escapeHtml($_attribute->getProductAttribute()->getStoreLabel()) ?></span>
</label>
<div class="control">
<select name="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-selector="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-validate="{required:true}"
id="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>"
class="super-attribute-select">
<option value=""><?= /* @escapeNotVerified */ __('Choose an Option...') ?></option>
</select>
</div>
</div>
<?php endforeach; ?>
<script type="text/x-magento-init">
{
"#product_addtocart_form": {
"configurable": {
"spConfig": <?= /* @escapeNotVerified */ $block->getJsonConfig() ?>,
"gallerySwitchStrategy": "<?php /* @escapeNotVerified */ echo $block->getVar('gallery_switch_strategy',
'Magento_ConfigurableProduct') ?: 'replace'; ?>"
}
}
}
</script>
<?php endif;?>
And my system log ever shows:
[2019-01-16 13:02:01] main.CRITICAL: Invalid method MagentoCatalogBlockProductViewInterceptor::decorateArray
So, I can't override the configurable.phtml file, because the Magento Interceptors can't load the decorateArray method.
And before, I need get the configurable products out of stock in my select, like this image:
But I don't know where the method to override this and get all product attributes
magento2 module configurable-product overrides
New contributor
add a comment |
I want to show the all attributes from my configurable product on my select. I followed this tutorial: Magento 2.2 How to show out of stock in configurable product, with some changes and fixes.
Well, my module is like this now:
Vendor/ConfigurableProduct/etc/di.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoSwatchesBlockProductRendererConfigurable" type="VendorConfigurableProductBlockProductViewTypeConfigurable" />
<preference for="MagentoConfigurableProductModelConfigurableAttributeData" type="VendorConfigurableProductModelRewriteConfigurableAttributeData" />
<preference for="MagentoConfigurableProductHelperData" type="VendorConfigurableProductHelperData" />
</config>
Vendor/ConfigurableProduct/Block/ConfigurableProduct.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductBlock;
use MagentoFrameworkViewElementTemplate;
class ConfigurableProduct extends Template
{
protected $_storeManager;
public function __construct(
MagentoFrameworkViewElementTemplateContext $context,
array $data =
){
parent::__construct($context, $data);
$this->_storeManager = $context->getStoreManager();
}
}
Vendor/ConfigurableProduct/Block/Product/View/Type/Configurable.php
<?php
namespace VendorConfigurableProductBlockProductViewType;
uses...
class Configurable extends MagentoSwatchesBlockProductRendererConfigurable
{
public function beforeSetTemplate(
MagentoSwatchesBlockProductRendererConfigurable $subject,
$template
) {
return ['Vendor_ConfigurableProduct::configurable.phtml'];
}
public function beforeSetName(MagentoCatalogModelProduct $subject, $name)
{
return ['(' . $name . ')'];
}
public function __construct(
Context $context,
ArrayUtils $arrayUtils,
EncoderInterface $jsonEncoder,
Data $helper,
CatalogProduct $catalogProduct,
CurrentCustomer $currentCustomer,
PriceCurrencyInterface $priceCurrency,
ConfigurableAttributeData $configurableAttributeData,
SwatchData $swatchHelper,
Media $swatchMediaHelper,
array $data =
){
$this->swatchHelper = $swatchHelper;
$this->swatchMediaHelper = $swatchMediaHelper;
parent::__construct(
$context,
$arrayUtils,
$jsonEncoder,
$helper,
$catalogProduct,
$currentCustomer,
$priceCurrency,
$configurableAttributeData,
$swatchHelper,
$swatchMediaHelper,
$data
);
}
public function getJsonConfig()
{
$store = $this->getCurrentStore();
$currentProduct = $this->getProduct();
$regularPrice = $currentProduct->getPriceInfo()->getPrice('regular_price');
$finalPrice = $currentProduct->getPriceInfo()->getPrice('final_price');
$options = $this->helper->getOptions($currentProduct, $this->getAllowProducts());
$attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options);
$config = [
'attributes' => $attributesData['attributes'],
'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()),
'optionPrices' => $this->getOptionPrices(),
'optionStock' => $this->getOptionStocks(),
'prices' => [
'oldPrice' => [
'amount' => $this->_registerJsPrice($regularPrice->getAmount()->getValue()),
],
'basePrice' => [
'amount' => $this->_registerJsPrice(
$finalPrice->getAmount()->getBaseAmount()
),
],
'finalPrice' => [
'amount' => $this->_registerJsPrice($finalPrice->getAmount()->getValue()),
],
],
'productId' => $currentProduct->getId(),
'chooseText' => __('Choose an Option...'),
'images' => isset($options['images']) ? $options['images'] : ,
'index' => isset($options['index']) ? $options['index'] : ,
];
if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) {
$config['defaultValues'] = $attributesData['defaultValues'];
}
$config = array_merge($config, $this->_getAdditionalConfig());
return $this->jsonEncoder->encode($config);
}
/*-----------------------custom code----------------------*/
protected function getOptionStocks()
{
$stocks = ;
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$stockObject=$objectManager->get('MagentoCatalogInventoryApiStockRegistryInterface');
foreach ($this->getAllowProducts() as $product) {
$productStockObj = $stockObject->getStockItem($product->getId());
$isInStock = $productStockObj['is_in_stock'];
$stocks[$product->getId()] = ['stockStatus' => $isInStock];
}
return $stocks;
}
public function getAllowProducts()
{
if (!$this->hasAllowProducts()){
$skipSaleableCheck = 1;
$products = $skipSaleableCheck ?
$this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null) :
$this->getProduct()->getTypeInstance()->getSalableUsedProducts($this->getProduct(), null);
$this->setAllowProducts($products);
}
return $this->getData('allow_products');
}
public function getAllowAttributes()
{
return $this->getProduct()->getTypeInstance()->getConfigurableAttributes($this->getProduct());
}
}
> Vendor/ConfigurableProduct/Helper/Data.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductHelper;
use MagentoCatalogModelProduct;
/**
* Class Data
* Helper class for getting options
*
*/
class Data extends MagentoConfigurableProductHelperData
{
/**
* Get Options for Configurable Product Options
*
* @param MagentoCatalogModelProduct $currentProduct
* @param array $allowedProducts
* @return array
*/
public function getOptions($currentProduct, $allowedProducts)
{
$options = ;
foreach ($allowedProducts as $product) {
$productId = $product->getId();
$images = $this->getGalleryImages($product);
if ($images) {
foreach ($images as $image) {
$options['images'][$productId] =
[
'thumb' => $image->getData('small_image_url'),
'img' => $image->getData('medium_image_url'),
'full' => $image->getData('large_image_url'),
'caption' => $image->getLabel(),
'position' => $image->getPosition(),
'isMain' => $image->getFile() == $product->getImage(),
];
}
}
foreach ($this->getAllowAttributes($currentProduct) as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$productAttributeId = $productAttribute->getId();
$attributeValue = $product->getData($productAttribute->getAttributeCode());
$options[$productAttributeId][$attributeValue] = $productId;
$options['index'][$productId][$productAttributeId] = $attributeValue;
}
}
return $options;
}
/**
* Get allowed attributes
*
* @param MagentoCatalogModelProduct $product
* @return array
*/
public function getAllowAttributes($product)
{
return $product->getTypeInstance()->getConfigurableAttributes($product);
}
}
Vendor/ConfigurableProduct/Model/Rewrite/ConfigurableAttributeData.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductModelRewrite;
use MagentoCatalogModelProduct;
use MagentoConfigurableProductModelProductTypeConfigurableAttribute;
class ConfigurableAttributeData extends MagentoConfigurableProductModelConfigurableAttributeData
{
protected $eavConfig;
public function __construct(MagentoEavModelConfig $eavConfig)
{
$this->eavConfig = $eavConfig;
}
/**
* Get product attributes
*
* @param Product $product
* @param array $options
* @return array
*/
public function getAttributesData(Product $product, array $options = )
{
$defaultValues = ;
$attributes = ;
$attrs = $product->getTypeInstance()->getConfigurableAttributes($product);
foreach ($attrs as $attribute) {
$attributeOptionsData = $this->getAttributeOptionsData($attribute, $options);
if ($attributeOptionsData) {
$productAttribute = $attribute->getProductAttribute();
$attributeId = $productAttribute->getId();
$attributes[$attributeId] = [
'id' => $attributeId,
'code' => $productAttribute->getAttributeCode(),
'label' => $productAttribute->getStoreLabel($product->getStoreId()),
'options' => $attributeOptionsData,
'position' => $attribute->getPosition(),
];
$defaultValues[$attributeId] = $this->getAttributeConfigValue($attributeId, $product);
}
}
return [
'attributes' => $attributes,
'defaultValues' => $defaultValues,
];
}
public function getAttributeOptionsData($attribute, $config)
{
$attributeOptionsData = ;
$attributeId = $attribute->getAttributeId();
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$eavModel = $objectManager->create('MagentoCatalogModelResourceModelEavAttribute');
$attr = $eavModel->load($attributeId);
$attributeCode=$eavModel->getAttributeCode();
$attribute = $this->eavConfig->getAttribute('catalog_product', $attributeCode);
$options = $attribute->getSource()->getAllOptions();
foreach ($options as $attributeOption) {
$optionId = $attributeOption['value'];
$attributeOptionsData = [
'id' => $optionId,
'label' => $attributeOption['label'],
'products' => isset($config[$attribute->getAttributeId()][$optionId])
? $config[$attribute->getAttributeId()][$optionId]
: ,
];
}
return $attributeOptionsData;
}
/**
* Retrieve configurable attributes data
*
* @param MagentoCatalogModelProduct $product
* @return MagentoConfigurableProductModelProductTypeConfigurableAttribute
*/
public function getConfigurableAttributes($product)
{
MagentoFrameworkProfiler::start(
'CONFIGURABLE:' . __METHOD__,
['group' => 'CONFIGURABLE', 'method' => __METHOD__]
);
if (!$product->hasData($this->_configurableAttributes)) {
$configurableAttributes = $this->getConfigurableAttributeCollection($product);
$this->extensionAttributesJoinProcessor->process($configurableAttributes);
$configurableAttributes->orderByPosition()->load();
$product->setData($this->_configurableAttributes, $configurableAttributes);
}
MagentoFrameworkProfiler::stop('CONFIGURABLE:' . __METHOD__);
return $product->getData($this->_configurableAttributes);
}
}
Vendor/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options.wrapper">
<action method='setTemplate'>
<argument name="template" xsi:type="string">Vendor_ConfigurableProduct::configurable.phtml</argument>
</action>
<!--<argument name="class" xsi:type="string">VendorConfigurableProductBlockProductViewTypeConfigurable</argument>-->
</referenceBlock>
</body>
</page>
Vendor/ConfigurableProduct/view/frontend/templates/configurable.phtml
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var $block VendorConfigurableProductBlockProductViewTypeConfigurable */
$_product = $block->getProduct();
$_attributes = $block->decorateArray($block->getAllowAttributes());
?>
<!-- TODO: custom layout -->
<?php if ($_product->isSaleable() && count($_attributes)):?>
<?php foreach ($_attributes as $_attribute): ?>
<div class="field configurable required">
<label class="label" for="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>">
<span><?= $block->escapeHtml($_attribute->getProductAttribute()->getStoreLabel()) ?></span>
</label>
<div class="control">
<select name="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-selector="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-validate="{required:true}"
id="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>"
class="super-attribute-select">
<option value=""><?= /* @escapeNotVerified */ __('Choose an Option...') ?></option>
</select>
</div>
</div>
<?php endforeach; ?>
<script type="text/x-magento-init">
{
"#product_addtocart_form": {
"configurable": {
"spConfig": <?= /* @escapeNotVerified */ $block->getJsonConfig() ?>,
"gallerySwitchStrategy": "<?php /* @escapeNotVerified */ echo $block->getVar('gallery_switch_strategy',
'Magento_ConfigurableProduct') ?: 'replace'; ?>"
}
}
}
</script>
<?php endif;?>
And my system log ever shows:
[2019-01-16 13:02:01] main.CRITICAL: Invalid method MagentoCatalogBlockProductViewInterceptor::decorateArray
So, I can't override the configurable.phtml file, because the Magento Interceptors can't load the decorateArray method.
And before, I need get the configurable products out of stock in my select, like this image:
But I don't know where the method to override this and get all product attributes
magento2 module configurable-product overrides
New contributor
add a comment |
I want to show the all attributes from my configurable product on my select. I followed this tutorial: Magento 2.2 How to show out of stock in configurable product, with some changes and fixes.
Well, my module is like this now:
Vendor/ConfigurableProduct/etc/di.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoSwatchesBlockProductRendererConfigurable" type="VendorConfigurableProductBlockProductViewTypeConfigurable" />
<preference for="MagentoConfigurableProductModelConfigurableAttributeData" type="VendorConfigurableProductModelRewriteConfigurableAttributeData" />
<preference for="MagentoConfigurableProductHelperData" type="VendorConfigurableProductHelperData" />
</config>
Vendor/ConfigurableProduct/Block/ConfigurableProduct.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductBlock;
use MagentoFrameworkViewElementTemplate;
class ConfigurableProduct extends Template
{
protected $_storeManager;
public function __construct(
MagentoFrameworkViewElementTemplateContext $context,
array $data =
){
parent::__construct($context, $data);
$this->_storeManager = $context->getStoreManager();
}
}
Vendor/ConfigurableProduct/Block/Product/View/Type/Configurable.php
<?php
namespace VendorConfigurableProductBlockProductViewType;
uses...
class Configurable extends MagentoSwatchesBlockProductRendererConfigurable
{
public function beforeSetTemplate(
MagentoSwatchesBlockProductRendererConfigurable $subject,
$template
) {
return ['Vendor_ConfigurableProduct::configurable.phtml'];
}
public function beforeSetName(MagentoCatalogModelProduct $subject, $name)
{
return ['(' . $name . ')'];
}
public function __construct(
Context $context,
ArrayUtils $arrayUtils,
EncoderInterface $jsonEncoder,
Data $helper,
CatalogProduct $catalogProduct,
CurrentCustomer $currentCustomer,
PriceCurrencyInterface $priceCurrency,
ConfigurableAttributeData $configurableAttributeData,
SwatchData $swatchHelper,
Media $swatchMediaHelper,
array $data =
){
$this->swatchHelper = $swatchHelper;
$this->swatchMediaHelper = $swatchMediaHelper;
parent::__construct(
$context,
$arrayUtils,
$jsonEncoder,
$helper,
$catalogProduct,
$currentCustomer,
$priceCurrency,
$configurableAttributeData,
$swatchHelper,
$swatchMediaHelper,
$data
);
}
public function getJsonConfig()
{
$store = $this->getCurrentStore();
$currentProduct = $this->getProduct();
$regularPrice = $currentProduct->getPriceInfo()->getPrice('regular_price');
$finalPrice = $currentProduct->getPriceInfo()->getPrice('final_price');
$options = $this->helper->getOptions($currentProduct, $this->getAllowProducts());
$attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options);
$config = [
'attributes' => $attributesData['attributes'],
'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()),
'optionPrices' => $this->getOptionPrices(),
'optionStock' => $this->getOptionStocks(),
'prices' => [
'oldPrice' => [
'amount' => $this->_registerJsPrice($regularPrice->getAmount()->getValue()),
],
'basePrice' => [
'amount' => $this->_registerJsPrice(
$finalPrice->getAmount()->getBaseAmount()
),
],
'finalPrice' => [
'amount' => $this->_registerJsPrice($finalPrice->getAmount()->getValue()),
],
],
'productId' => $currentProduct->getId(),
'chooseText' => __('Choose an Option...'),
'images' => isset($options['images']) ? $options['images'] : ,
'index' => isset($options['index']) ? $options['index'] : ,
];
if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) {
$config['defaultValues'] = $attributesData['defaultValues'];
}
$config = array_merge($config, $this->_getAdditionalConfig());
return $this->jsonEncoder->encode($config);
}
/*-----------------------custom code----------------------*/
protected function getOptionStocks()
{
$stocks = ;
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$stockObject=$objectManager->get('MagentoCatalogInventoryApiStockRegistryInterface');
foreach ($this->getAllowProducts() as $product) {
$productStockObj = $stockObject->getStockItem($product->getId());
$isInStock = $productStockObj['is_in_stock'];
$stocks[$product->getId()] = ['stockStatus' => $isInStock];
}
return $stocks;
}
public function getAllowProducts()
{
if (!$this->hasAllowProducts()){
$skipSaleableCheck = 1;
$products = $skipSaleableCheck ?
$this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null) :
$this->getProduct()->getTypeInstance()->getSalableUsedProducts($this->getProduct(), null);
$this->setAllowProducts($products);
}
return $this->getData('allow_products');
}
public function getAllowAttributes()
{
return $this->getProduct()->getTypeInstance()->getConfigurableAttributes($this->getProduct());
}
}
> Vendor/ConfigurableProduct/Helper/Data.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductHelper;
use MagentoCatalogModelProduct;
/**
* Class Data
* Helper class for getting options
*
*/
class Data extends MagentoConfigurableProductHelperData
{
/**
* Get Options for Configurable Product Options
*
* @param MagentoCatalogModelProduct $currentProduct
* @param array $allowedProducts
* @return array
*/
public function getOptions($currentProduct, $allowedProducts)
{
$options = ;
foreach ($allowedProducts as $product) {
$productId = $product->getId();
$images = $this->getGalleryImages($product);
if ($images) {
foreach ($images as $image) {
$options['images'][$productId] =
[
'thumb' => $image->getData('small_image_url'),
'img' => $image->getData('medium_image_url'),
'full' => $image->getData('large_image_url'),
'caption' => $image->getLabel(),
'position' => $image->getPosition(),
'isMain' => $image->getFile() == $product->getImage(),
];
}
}
foreach ($this->getAllowAttributes($currentProduct) as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$productAttributeId = $productAttribute->getId();
$attributeValue = $product->getData($productAttribute->getAttributeCode());
$options[$productAttributeId][$attributeValue] = $productId;
$options['index'][$productId][$productAttributeId] = $attributeValue;
}
}
return $options;
}
/**
* Get allowed attributes
*
* @param MagentoCatalogModelProduct $product
* @return array
*/
public function getAllowAttributes($product)
{
return $product->getTypeInstance()->getConfigurableAttributes($product);
}
}
Vendor/ConfigurableProduct/Model/Rewrite/ConfigurableAttributeData.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductModelRewrite;
use MagentoCatalogModelProduct;
use MagentoConfigurableProductModelProductTypeConfigurableAttribute;
class ConfigurableAttributeData extends MagentoConfigurableProductModelConfigurableAttributeData
{
protected $eavConfig;
public function __construct(MagentoEavModelConfig $eavConfig)
{
$this->eavConfig = $eavConfig;
}
/**
* Get product attributes
*
* @param Product $product
* @param array $options
* @return array
*/
public function getAttributesData(Product $product, array $options = )
{
$defaultValues = ;
$attributes = ;
$attrs = $product->getTypeInstance()->getConfigurableAttributes($product);
foreach ($attrs as $attribute) {
$attributeOptionsData = $this->getAttributeOptionsData($attribute, $options);
if ($attributeOptionsData) {
$productAttribute = $attribute->getProductAttribute();
$attributeId = $productAttribute->getId();
$attributes[$attributeId] = [
'id' => $attributeId,
'code' => $productAttribute->getAttributeCode(),
'label' => $productAttribute->getStoreLabel($product->getStoreId()),
'options' => $attributeOptionsData,
'position' => $attribute->getPosition(),
];
$defaultValues[$attributeId] = $this->getAttributeConfigValue($attributeId, $product);
}
}
return [
'attributes' => $attributes,
'defaultValues' => $defaultValues,
];
}
public function getAttributeOptionsData($attribute, $config)
{
$attributeOptionsData = ;
$attributeId = $attribute->getAttributeId();
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$eavModel = $objectManager->create('MagentoCatalogModelResourceModelEavAttribute');
$attr = $eavModel->load($attributeId);
$attributeCode=$eavModel->getAttributeCode();
$attribute = $this->eavConfig->getAttribute('catalog_product', $attributeCode);
$options = $attribute->getSource()->getAllOptions();
foreach ($options as $attributeOption) {
$optionId = $attributeOption['value'];
$attributeOptionsData = [
'id' => $optionId,
'label' => $attributeOption['label'],
'products' => isset($config[$attribute->getAttributeId()][$optionId])
? $config[$attribute->getAttributeId()][$optionId]
: ,
];
}
return $attributeOptionsData;
}
/**
* Retrieve configurable attributes data
*
* @param MagentoCatalogModelProduct $product
* @return MagentoConfigurableProductModelProductTypeConfigurableAttribute
*/
public function getConfigurableAttributes($product)
{
MagentoFrameworkProfiler::start(
'CONFIGURABLE:' . __METHOD__,
['group' => 'CONFIGURABLE', 'method' => __METHOD__]
);
if (!$product->hasData($this->_configurableAttributes)) {
$configurableAttributes = $this->getConfigurableAttributeCollection($product);
$this->extensionAttributesJoinProcessor->process($configurableAttributes);
$configurableAttributes->orderByPosition()->load();
$product->setData($this->_configurableAttributes, $configurableAttributes);
}
MagentoFrameworkProfiler::stop('CONFIGURABLE:' . __METHOD__);
return $product->getData($this->_configurableAttributes);
}
}
Vendor/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options.wrapper">
<action method='setTemplate'>
<argument name="template" xsi:type="string">Vendor_ConfigurableProduct::configurable.phtml</argument>
</action>
<!--<argument name="class" xsi:type="string">VendorConfigurableProductBlockProductViewTypeConfigurable</argument>-->
</referenceBlock>
</body>
</page>
Vendor/ConfigurableProduct/view/frontend/templates/configurable.phtml
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var $block VendorConfigurableProductBlockProductViewTypeConfigurable */
$_product = $block->getProduct();
$_attributes = $block->decorateArray($block->getAllowAttributes());
?>
<!-- TODO: custom layout -->
<?php if ($_product->isSaleable() && count($_attributes)):?>
<?php foreach ($_attributes as $_attribute): ?>
<div class="field configurable required">
<label class="label" for="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>">
<span><?= $block->escapeHtml($_attribute->getProductAttribute()->getStoreLabel()) ?></span>
</label>
<div class="control">
<select name="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-selector="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-validate="{required:true}"
id="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>"
class="super-attribute-select">
<option value=""><?= /* @escapeNotVerified */ __('Choose an Option...') ?></option>
</select>
</div>
</div>
<?php endforeach; ?>
<script type="text/x-magento-init">
{
"#product_addtocart_form": {
"configurable": {
"spConfig": <?= /* @escapeNotVerified */ $block->getJsonConfig() ?>,
"gallerySwitchStrategy": "<?php /* @escapeNotVerified */ echo $block->getVar('gallery_switch_strategy',
'Magento_ConfigurableProduct') ?: 'replace'; ?>"
}
}
}
</script>
<?php endif;?>
And my system log ever shows:
[2019-01-16 13:02:01] main.CRITICAL: Invalid method MagentoCatalogBlockProductViewInterceptor::decorateArray
So, I can't override the configurable.phtml file, because the Magento Interceptors can't load the decorateArray method.
And before, I need get the configurable products out of stock in my select, like this image:
But I don't know where the method to override this and get all product attributes
magento2 module configurable-product overrides
New contributor
I want to show the all attributes from my configurable product on my select. I followed this tutorial: Magento 2.2 How to show out of stock in configurable product, with some changes and fixes.
Well, my module is like this now:
Vendor/ConfigurableProduct/etc/di.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoSwatchesBlockProductRendererConfigurable" type="VendorConfigurableProductBlockProductViewTypeConfigurable" />
<preference for="MagentoConfigurableProductModelConfigurableAttributeData" type="VendorConfigurableProductModelRewriteConfigurableAttributeData" />
<preference for="MagentoConfigurableProductHelperData" type="VendorConfigurableProductHelperData" />
</config>
Vendor/ConfigurableProduct/Block/ConfigurableProduct.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductBlock;
use MagentoFrameworkViewElementTemplate;
class ConfigurableProduct extends Template
{
protected $_storeManager;
public function __construct(
MagentoFrameworkViewElementTemplateContext $context,
array $data =
){
parent::__construct($context, $data);
$this->_storeManager = $context->getStoreManager();
}
}
Vendor/ConfigurableProduct/Block/Product/View/Type/Configurable.php
<?php
namespace VendorConfigurableProductBlockProductViewType;
uses...
class Configurable extends MagentoSwatchesBlockProductRendererConfigurable
{
public function beforeSetTemplate(
MagentoSwatchesBlockProductRendererConfigurable $subject,
$template
) {
return ['Vendor_ConfigurableProduct::configurable.phtml'];
}
public function beforeSetName(MagentoCatalogModelProduct $subject, $name)
{
return ['(' . $name . ')'];
}
public function __construct(
Context $context,
ArrayUtils $arrayUtils,
EncoderInterface $jsonEncoder,
Data $helper,
CatalogProduct $catalogProduct,
CurrentCustomer $currentCustomer,
PriceCurrencyInterface $priceCurrency,
ConfigurableAttributeData $configurableAttributeData,
SwatchData $swatchHelper,
Media $swatchMediaHelper,
array $data =
){
$this->swatchHelper = $swatchHelper;
$this->swatchMediaHelper = $swatchMediaHelper;
parent::__construct(
$context,
$arrayUtils,
$jsonEncoder,
$helper,
$catalogProduct,
$currentCustomer,
$priceCurrency,
$configurableAttributeData,
$swatchHelper,
$swatchMediaHelper,
$data
);
}
public function getJsonConfig()
{
$store = $this->getCurrentStore();
$currentProduct = $this->getProduct();
$regularPrice = $currentProduct->getPriceInfo()->getPrice('regular_price');
$finalPrice = $currentProduct->getPriceInfo()->getPrice('final_price');
$options = $this->helper->getOptions($currentProduct, $this->getAllowProducts());
$attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options);
$config = [
'attributes' => $attributesData['attributes'],
'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()),
'optionPrices' => $this->getOptionPrices(),
'optionStock' => $this->getOptionStocks(),
'prices' => [
'oldPrice' => [
'amount' => $this->_registerJsPrice($regularPrice->getAmount()->getValue()),
],
'basePrice' => [
'amount' => $this->_registerJsPrice(
$finalPrice->getAmount()->getBaseAmount()
),
],
'finalPrice' => [
'amount' => $this->_registerJsPrice($finalPrice->getAmount()->getValue()),
],
],
'productId' => $currentProduct->getId(),
'chooseText' => __('Choose an Option...'),
'images' => isset($options['images']) ? $options['images'] : ,
'index' => isset($options['index']) ? $options['index'] : ,
];
if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) {
$config['defaultValues'] = $attributesData['defaultValues'];
}
$config = array_merge($config, $this->_getAdditionalConfig());
return $this->jsonEncoder->encode($config);
}
/*-----------------------custom code----------------------*/
protected function getOptionStocks()
{
$stocks = ;
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$stockObject=$objectManager->get('MagentoCatalogInventoryApiStockRegistryInterface');
foreach ($this->getAllowProducts() as $product) {
$productStockObj = $stockObject->getStockItem($product->getId());
$isInStock = $productStockObj['is_in_stock'];
$stocks[$product->getId()] = ['stockStatus' => $isInStock];
}
return $stocks;
}
public function getAllowProducts()
{
if (!$this->hasAllowProducts()){
$skipSaleableCheck = 1;
$products = $skipSaleableCheck ?
$this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct(), null) :
$this->getProduct()->getTypeInstance()->getSalableUsedProducts($this->getProduct(), null);
$this->setAllowProducts($products);
}
return $this->getData('allow_products');
}
public function getAllowAttributes()
{
return $this->getProduct()->getTypeInstance()->getConfigurableAttributes($this->getProduct());
}
}
> Vendor/ConfigurableProduct/Helper/Data.php
<?php
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductHelper;
use MagentoCatalogModelProduct;
/**
* Class Data
* Helper class for getting options
*
*/
class Data extends MagentoConfigurableProductHelperData
{
/**
* Get Options for Configurable Product Options
*
* @param MagentoCatalogModelProduct $currentProduct
* @param array $allowedProducts
* @return array
*/
public function getOptions($currentProduct, $allowedProducts)
{
$options = ;
foreach ($allowedProducts as $product) {
$productId = $product->getId();
$images = $this->getGalleryImages($product);
if ($images) {
foreach ($images as $image) {
$options['images'][$productId] =
[
'thumb' => $image->getData('small_image_url'),
'img' => $image->getData('medium_image_url'),
'full' => $image->getData('large_image_url'),
'caption' => $image->getLabel(),
'position' => $image->getPosition(),
'isMain' => $image->getFile() == $product->getImage(),
];
}
}
foreach ($this->getAllowAttributes($currentProduct) as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$productAttributeId = $productAttribute->getId();
$attributeValue = $product->getData($productAttribute->getAttributeCode());
$options[$productAttributeId][$attributeValue] = $productId;
$options['index'][$productId][$productAttributeId] = $attributeValue;
}
}
return $options;
}
/**
* Get allowed attributes
*
* @param MagentoCatalogModelProduct $product
* @return array
*/
public function getAllowAttributes($product)
{
return $product->getTypeInstance()->getConfigurableAttributes($product);
}
}
Vendor/ConfigurableProduct/Model/Rewrite/ConfigurableAttributeData.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace VendorConfigurableProductModelRewrite;
use MagentoCatalogModelProduct;
use MagentoConfigurableProductModelProductTypeConfigurableAttribute;
class ConfigurableAttributeData extends MagentoConfigurableProductModelConfigurableAttributeData
{
protected $eavConfig;
public function __construct(MagentoEavModelConfig $eavConfig)
{
$this->eavConfig = $eavConfig;
}
/**
* Get product attributes
*
* @param Product $product
* @param array $options
* @return array
*/
public function getAttributesData(Product $product, array $options = )
{
$defaultValues = ;
$attributes = ;
$attrs = $product->getTypeInstance()->getConfigurableAttributes($product);
foreach ($attrs as $attribute) {
$attributeOptionsData = $this->getAttributeOptionsData($attribute, $options);
if ($attributeOptionsData) {
$productAttribute = $attribute->getProductAttribute();
$attributeId = $productAttribute->getId();
$attributes[$attributeId] = [
'id' => $attributeId,
'code' => $productAttribute->getAttributeCode(),
'label' => $productAttribute->getStoreLabel($product->getStoreId()),
'options' => $attributeOptionsData,
'position' => $attribute->getPosition(),
];
$defaultValues[$attributeId] = $this->getAttributeConfigValue($attributeId, $product);
}
}
return [
'attributes' => $attributes,
'defaultValues' => $defaultValues,
];
}
public function getAttributeOptionsData($attribute, $config)
{
$attributeOptionsData = ;
$attributeId = $attribute->getAttributeId();
$objectManager = MagentoFrameworkAppObjectManager::getInstance();
$eavModel = $objectManager->create('MagentoCatalogModelResourceModelEavAttribute');
$attr = $eavModel->load($attributeId);
$attributeCode=$eavModel->getAttributeCode();
$attribute = $this->eavConfig->getAttribute('catalog_product', $attributeCode);
$options = $attribute->getSource()->getAllOptions();
foreach ($options as $attributeOption) {
$optionId = $attributeOption['value'];
$attributeOptionsData = [
'id' => $optionId,
'label' => $attributeOption['label'],
'products' => isset($config[$attribute->getAttributeId()][$optionId])
? $config[$attribute->getAttributeId()][$optionId]
: ,
];
}
return $attributeOptionsData;
}
/**
* Retrieve configurable attributes data
*
* @param MagentoCatalogModelProduct $product
* @return MagentoConfigurableProductModelProductTypeConfigurableAttribute
*/
public function getConfigurableAttributes($product)
{
MagentoFrameworkProfiler::start(
'CONFIGURABLE:' . __METHOD__,
['group' => 'CONFIGURABLE', 'method' => __METHOD__]
);
if (!$product->hasData($this->_configurableAttributes)) {
$configurableAttributes = $this->getConfigurableAttributeCollection($product);
$this->extensionAttributesJoinProcessor->process($configurableAttributes);
$configurableAttributes->orderByPosition()->load();
$product->setData($this->_configurableAttributes, $configurableAttributes);
}
MagentoFrameworkProfiler::stop('CONFIGURABLE:' . __METHOD__);
return $product->getData($this->_configurableAttributes);
}
}
Vendor/ConfigurableProduct/view/frontend/layout/catalog_product_view_type_configurable.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options.wrapper">
<action method='setTemplate'>
<argument name="template" xsi:type="string">Vendor_ConfigurableProduct::configurable.phtml</argument>
</action>
<!--<argument name="class" xsi:type="string">VendorConfigurableProductBlockProductViewTypeConfigurable</argument>-->
</referenceBlock>
</body>
</page>
Vendor/ConfigurableProduct/view/frontend/templates/configurable.phtml
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<?php
/** @var $block VendorConfigurableProductBlockProductViewTypeConfigurable */
$_product = $block->getProduct();
$_attributes = $block->decorateArray($block->getAllowAttributes());
?>
<!-- TODO: custom layout -->
<?php if ($_product->isSaleable() && count($_attributes)):?>
<?php foreach ($_attributes as $_attribute): ?>
<div class="field configurable required">
<label class="label" for="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>">
<span><?= $block->escapeHtml($_attribute->getProductAttribute()->getStoreLabel()) ?></span>
</label>
<div class="control">
<select name="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-selector="super_attribute[<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>]"
data-validate="{required:true}"
id="attribute<?= /* @escapeNotVerified */ $_attribute->getAttributeId() ?>"
class="super-attribute-select">
<option value=""><?= /* @escapeNotVerified */ __('Choose an Option...') ?></option>
</select>
</div>
</div>
<?php endforeach; ?>
<script type="text/x-magento-init">
{
"#product_addtocart_form": {
"configurable": {
"spConfig": <?= /* @escapeNotVerified */ $block->getJsonConfig() ?>,
"gallerySwitchStrategy": "<?php /* @escapeNotVerified */ echo $block->getVar('gallery_switch_strategy',
'Magento_ConfigurableProduct') ?: 'replace'; ?>"
}
}
}
</script>
<?php endif;?>
And my system log ever shows:
[2019-01-16 13:02:01] main.CRITICAL: Invalid method MagentoCatalogBlockProductViewInterceptor::decorateArray
So, I can't override the configurable.phtml file, because the Magento Interceptors can't load the decorateArray method.
And before, I need get the configurable products out of stock in my select, like this image:
But I don't know where the method to override this and get all product attributes
magento2 module configurable-product overrides
magento2 module configurable-product overrides
New contributor
New contributor
New contributor
asked 19 mins ago
Bruno RoboredoBruno Roboredo
1
1
New contributor
New contributor
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "479"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Bruno Roboredo is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmagento.stackexchange.com%2fquestions%2f258032%2fconfigurableproduct-how-to-get-the-configurable-products-out-of-stock%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Bruno Roboredo is a new contributor. Be nice, and check out our Code of Conduct.
Bruno Roboredo is a new contributor. Be nice, and check out our Code of Conduct.
Bruno Roboredo is a new contributor. Be nice, and check out our Code of Conduct.
Bruno Roboredo is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Magento Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmagento.stackexchange.com%2fquestions%2f258032%2fconfigurableproduct-how-to-get-the-configurable-products-out-of-stock%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown