I'm trying to override the module-catalog/Block/Product/View/Options/Type/Select.php
class with a new version which includes a few other bits of custom php (adding HTML classes and IDs to the containing DIVs). I am trying to achieve this by creating anew module. Unfortunately, when this new module is enabled, the select options aren't rendered to the product page. The rest of the page is fine, just without the select (checkboxes and radio buttons) options. I think everything looks fine and should work, so I can't understand why the Select.php
isn't returning the select options.
Directory structure:
app/
├── Mike/
│ ├── Newselect/
│ │ ├── Block/
│ │ │ ├── Product/
│ │ │ │ ├── View/
│ │ │ │ │ ├── Options/
│ │ │ │ │ │ ├── Type/
│ │ │ │ │ │ │ ├── Select.php
│ │ ├── etc/
│ │ │ ├── di.xml
│ │ │ ├── module.xml
│ │ ├── registration.php
│ │ ├── composer.json
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">
<preference for="Magento\Catalog\Block\Product\View\Options\Type\Select" type="Mike\Newselect\Block\Product\View\Options\Type\Select" />
</config>
module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Mike_Newselect" setup_version="1.0.0"/>
</config>
registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Mike_Newselect',
__DIR__
);
composer.json
{
"name": "Mike/Newselect",
"description": "Update the Select module to add HTML classes and IDs",
"require": {
"php": "~5.5.0|~5.6.0|~7.0.0",
"magento/module-store": "100.0.*",
"magento/module-eav": "100.0.*",
"magento/module-cms": "100.0.*",
"magento/module-indexer": "100.0.*",
"magento/module-customer": "100.0.*",
"magento/module-theme": "100.0.*",
"magento/module-checkout": "100.0.*",
"magento/module-backend": "100.0.*",
"magento/module-widget": "100.0.*",
"magento/module-wishlist": "100.0.*",
"magento/module-tax": "100.0.*",
"magento/module-msrp": "100.0.*",
"magento/module-catalog-inventory": "100.0.*",
"magento/module-directory": "100.0.*",
"magento/module-catalog-rule": "100.0.*",
"magento/module-product-alert": "100.0.*",
"magento/module-url-rewrite": "100.0.*",
"magento/module-catalog-url-rewrite": "100.0.*",
"magento/module-page-cache": "100.0.*",
"magento/module-quote": "100.0.*",
"magento/module-config": "100.0.*",
"magento/module-media-storage": "100.0.*",
"magento/framework": "100.0.*",
"magento/module-configurable-product": "100.0.*",
"magento/module-ui": "100.0.*"
},
"suggest": {
"magento/module-cookie": "100.0.*",
"magento/module-catalog-sample-data": "Sample Data version:100.0.*"
},
"type": "magento2-module",
"version": "100.0.5",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Magento\\Catalog\\": ""
}
}
}
Select.php
(this just a copy of the core Select.php file – not updated yet – apart from the Namespace and extending the core class)
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/**
* Product options text type block
*
* @author Magento Core Team <core@magentocommerce.com>
*/
namespace Mike\Newselect\Block\Product\View\Options\Type;
class Select extends \Magento\Catalog\Block\Product\View\Options\Type\Select
{
/**
* Return html for control element
*
* @return string
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function getValuesHtml()
{
$_option = $this->getOption();
$configValue = $this->getProduct()->getPreconfiguredValues()->getData('options/' . $_option->getId());
$store = $this->getProduct()->getStore();
$this->setSkipJsReloadPrice(1);
// Remove inline prototype onclick and onchange events
if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_DROP_DOWN ||
$_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_MULTIPLE
) {
$require = $_option->getIsRequire() ? ' required' : '';
$extraParams = '';
$select = $this->getLayout()->createBlock(
'Magento\Framework\View\Element\Html\Select'
)->setData(
[
'id' => 'select_' . $_option->getId(),
'class' => $require . ' product-custom-option admin__control-select'
]
);
if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_DROP_DOWN) {
$select->setName('options[' . $_option->getid() . ']')->addOption('', __('-- Please Select --'));
} else {
$select->setName('options[' . $_option->getid() . '][]');
$select->setClass('multiselect admin__control-multiselect' . $require . ' product-custom-option');
}
foreach ($_option->getValues() as $_value) {
$priceStr = $this->_formatPrice(
[
'is_percent' => $_value->getPriceType() == 'percent',
'pricing_value' => $_value->getPrice($_value->getPriceType() == 'percent'),
],
false
);
$select->addOption(
$_value->getOptionTypeId(),
$_value->getTitle() . ' ' . strip_tags($priceStr) . '',
['price' => $this->pricingHelper->currencyByStore($_value->getPrice(true), $store, false)]
);
}
if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_MULTIPLE) {
$extraParams = ' multiple="multiple"';
}
if (!$this->getSkipJsReloadPrice()) {
$extraParams .= ' onchange="opConfig.reloadPrice()"';
}
$select->setExtraParams($extraParams);
if ($configValue) {
$select->setValue($configValue);
}
return $select->getHtml();
}
if ($_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_RADIO ||
$_option->getType() == \Magento\Catalog\Model\Product\Option::OPTION_TYPE_CHECKBOX
) {
$selectHtml = '<div class="options-list nested" id="options-' . $_option->getId() . '-list">';
$require = $_option->getIsRequire() ? ' required' : '';
$arraySign = '';
switch ($_option->getType()) {
case \Magento\Catalog\Model\Product\Option::OPTION_TYPE_RADIO:
$type = 'radio';
$class = 'radio admin__control-radio';
if (!$_option->getIsRequire()) {
$selectHtml .= '<div class="field choice admin__field admin__field-option">' .
'<input type="radio" id="options_' .
$_option->getId() .
'" class="' .
$class .
' product-custom-option" name="options[' .
$_option->getId() .
']"' .
($this->getSkipJsReloadPrice() ? '' : ' onclick="opConfig.reloadPrice()"') .
' value="" checked="checked" /><label class="label admin__field-label" for="options_' .
$_option->getId() .
'"><span>' .
__('None') . '</span></label></div>';
}
break;
case \Magento\Catalog\Model\Product\Option::OPTION_TYPE_CHECKBOX:
$type = 'checkbox';
$class = 'checkbox admin__control-checkbox';
$arraySign = '[]';
break;
}
$count = 1;
foreach ($_option->getValues() as $_value) {
$count++;
$priceStr = $this->_formatPrice(
[
'is_percent' => $_value->getPriceType() == 'percent',
'pricing_value' => $_value->getPrice($_value->getPriceType() == 'percent'),
]
);
$htmlValue = $_value->getOptionTypeId();
if ($arraySign) {
$checked = is_array($configValue) && in_array($htmlValue, $configValue) ? 'checked' : '';
} else {
$checked = $configValue == $htmlValue ? 'checked' : '';
}
$selectHtml .= '<div class="field choice admin__field admin__field-option' .
$require .
'">' .
'<input type="' .
$type .
'" class="' .
$class .
' ' .
$require .
' product-custom-option"' .
($this->getSkipJsReloadPrice() ? '' : ' onclick="opConfig.reloadPrice()"') .
' name="options[' .
$_option->getId() .
']' .
$arraySign .
'" id="options_' .
$_option->getId() .
'_' .
$count .
'" value="' .
$htmlValue .
'" ' .
$checked .
' price="' .
$this->pricingHelper->currencyByStore($_value->getPrice(true), $store, false) .
'" />' .
'<label class="label admin__field-label" for="options_' .
$_option->getId() .
'_' .
$count .
'"><span>' .
$_value->getTitle() .
'</span> ' .
$priceStr .
'</label>';
$selectHtml .= '</div>';
}
$selectHtml .= '</div>';
return $selectHtml;
}
}
}
catalog_product_view.xml
<block class="Magento\Catalog\Block\Product\View\Options\Type\Select" as="select" template="product/view/options/type/select.phtml"/>
Best Answer
First of all,
we need to add Constructor injection method to our custom select class:(Edit: we don't need to add Constructor Injection, we need to add the sequence module)We need to add the :
http://devdocs.magento.com/guides/v2.1/extension-dev-guide/build/module-load-order.html
Second, copy
vendor/magento/module-catalog/view/frontend/templates/product/view/options/type/select.phtml
to our custom moduleapp/code/Mike/Newselect/view/frontend/templates/product/view/options/type/select.phtml