Multi select filter in layered navigation - php

I have a custom multi select attribute which I'd like to take part in filtering of products. The attribute is set as used in Layered Navigation however doesn't appear in the list of available filters. Could be due to custom model implementation?
Anyone have some tips where to check why it doesn't appear? Attribute is set for several products
Magento version used is EE 1.11
Thanks

For those who will struggle with this in the future: the problem is in Mage_Catalog_Model_Resource_Product_Indexer_Eav_Source file on line 191. By default multi select attribute values are being pulled from eav_attribute_option and if your custom attribute uses custom source model the attribute will not be indexed.
I don't know as of yet if it's intended but I couldn't find a better solution than overriding that model in local pull and adding required values in $options array.
Hope this helps someone, someday

What is the backend_type. i.e. are the values stored in the catalog_product_entity_varchar or catalog_product_entity_text table?
The backend_type has to match the checks in Mage_Catalog_Model_Resource_Eav_Attribute::isIndexable(), so text wouldn't work without rewriting the attribute model.
Is the is_filterable and/or is_filterable_in_search attribute property set?
The Mage_Catalog_Model_Product_Indexer_Eav::_registerCatalogAttributeSaveEvent() checks for those when updating the index for the layered navigation.
Are the methods getFlatColums(), getFlatIndexes() and getFlatUpdateSelect() implemented in the custom source model?
This actually is only required for building and updating the flat catalog product tables (so the used_in_product_listing or is_filterable property needs to be set in order for Magento to pick up the attribute).
Check the class Mage_Eav_Model_Entity_Attribute_Source_Table as a reference on what these there methods are supposed to return.

NOTE: I'm adding this in a new answer to use the code format.
How it was said, the problem is with multiselect attributes using a custom source model.
Solution:
Rewrite the class
Mage_Catalog_Model_Resource_Product_Indexer_Eav_Source
Override the method:
_prepareMultiselectIndex
add this code after the $options array is filled with the default code (check line 200 in original file)
foreach($attrIds as $attId){
if( ! isset($options[$attId])){
$options[$attId] = $this->_getOptionsFromSourceModel($attId);
}
}
add this method too:
protected function _getOptionsFromSourceModel($attId)
{
$options = array();
/** #var Mage_Eav_Model_Entity_Attribute_Abstract $attribute */
$attribute = Mage::getResourceSingleton('catalog/product')->getAttribute($attId);
/** #var Mage_Eav_Model_Entity_Attribute_Source_Abstract $source */
$source = $attribute->getSource();
$sourceOptions = $source->getAllOptions();
if($sourceOptions){
foreach($sourceOptions as $sourceOption){
if(isset($sourceOption['value'])){
$options[$sourceOption['value']] = true;
}
}
}
return $options;
}
I couldn't find a less intrusive way to fix this.

Related

Is there a way to change the format on how Yii2 creates ID's for fields within ActiveForm?

I'm using ActiveForm with Yii2 and by default it seems to generate default id's for fields if you don't set one, in the format of:
{action-name}-{field-name}
So for example if I had a field with the name of foo_bar used in an action of actionSettings then the id of this field would be generated as:
settings-foo_bar
I would prefer this to just be foo_bar.
Is this possible to change on a form by form basis?
Based on the answer provided by #Bizley I was investigating how the method calculated the name and found out there is another way to achieve this as well.
You can simply override the formName method of your respective model to return a blank value, such as:
public function formName() {
return '';
}
Whilst this has less overheads as you don't need to create a new class, it will also affect other things within your form such as the field names and also should not be used for forms which contain multiple different models as explained here.
Lastly, because this question was about changing how Yii formats the id, #Bizleys answer is the correct one; my solution is just another option of possibly achieving it another way.
ActiveField id is by default created based on the form's model name and field's name.
If you want to change it for the whole form override the method that does it:
protected function getInputId()
{
return $this->_inputId ?: Html::getInputId($this->model, $this->attribute);
}
and use this modified class in your form.

Magento Get Different options to select from Options.php

I have a admin back-end options section/module to control few things like upload slider images, site background, banners etc.
That is simple cause it just requires xml code in system.xml.
I want to add different drop-downs, radio buttons, multiple select.
I have the following code in Options.php
Its giving me options to select one, two or three for every drop-down, radio or multi select.
What I have to define here to get different options? not just one, two and Three.
<?php
class Options_CustomConfig_Model_Options
{
/**
* Provide available options as a value/label array
*
* #return array
*/
public function toOptionArray()
{
return array(
array('value'=>1, 'label'=>'One'),
array('value'=>2, 'label'=>'Two'),
array('value'=>3, 'label'=>'Three')
);
}
}
You can create individual models for individual drop down and specify relevant model in the system.xml while creating field.
Hope this will help you.
You need to create Different Source model if options are different in configuration field.
here is the some useful links for creating source model:
http://magento.ikantam.com/qa/source-model
http://www.atwix.com/magento/frontend-backend-source/
Ok so this is what needs to be done to get more options: I created another folder in Model called Optiontwo and inside Option.php. Class for options.php have to have folded in it like this: class CustomConfig_Model_Optiontwo_Options. And then in system.xml for source_model have to be declared like this: customconfig/Optiontwo_options
Thanks to Adrsh Khatri for pointing in the right direction.

Magento: Limit text field size in product custom attribute to 80 characters

I have a problem by using the following tip from the magento forum:
Quote:
One option you could do is to add a backend model for this attribute.
In this model you could write your own beforeSave function that will
process the length of given value and trim it to be the desired
length. The class should extend Mage_Eav_Model_Entity_Attribute_Backend_Abstract
Code:
public function beforeSave($object) {
$attrCode = $this->getAttribute()->getAttributeCode();
if ($object->hasData($attrCode)) {
$object->setData($attrCode, substr($object->getData($attrCode),0,50));
}
return $this; }
My question now is: how and where do I implement this snippet?
I recently put it in /app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Default.php but it had no effect.
first at all, you'll never should place custom code into core files. This destroys your upgradabillity. Create your own custom modules under app/code/local. There you can create your model which extends from Mage_Eav_Model_Entity_Attribute_Backend_Abstract.
May this link helps you to create your module:
http://www.smashingmagazine.com/2012/03/01/basics-creating-magento-module/
Also you can use magerun (an cli tool for magento) to create a module: http://magerun.net/

How to set quicksearch initial value?

where I want tu put an initial value.
I have seen that quicksearch has 'q' element but I can't access it, for example this does not find the q element:
$quickSearch->getElement('q');
How can I access the quicksearch in order to set an initial value?
Looking at the source of it can help you find things out. Agile Toolkit is designed in a way where developer should take advantage of the knowledge of the source code.
QuickSearch is derived from Filter which is derived from Form, so there should be addField somewhere. Looking at the QuickSearch, you'll find it inside recallAll() function. There are no calls to this functions so we should look into the parent class - Filter.
Filter sets up a hook in api to call recallAll after initialization have been finished. That means to be able to access the field you can either redefine a method or add a hook yourself.
Hook:
$this->api->addHook('post-init',function() use($quickSearch){
$quickSearch->getElement('q')->set('hello');
});
Extending
class MyQuicksearch extends QuickSearch {
function recallAll(){
parent::recallAll();
$this->getElement('q')->set('hello');
}
}
Finally you can take advantage of knowing where recallAll is loading their default values from and simply do this:
$quicksearch->memorize('q','hello');
to address this, we must first understand how the Search Field of the QuickSearch Class is added to the Grid Basic Class. so upon investigation of the source code, we can see that:
QuickSearch Class does not track (or save a PUBLIC reference of) the Form_Field q
Form_Field q is ONLY added DURING the Rendering phase of the grid
knowing these, we can now proceed adding the modifications to address item #1.
first, we need to add a variable to track the Form_Field q in the QuickSearch Class:
var $search_field=null; // add this line (1)
function recallAll(){
$ff=$this->addField('line','q','');
$this->search_field=$ff; // and this line (2)
parent::recallAll();
:
:
}
second, to address item #2, on our page where the grid is defined, we need add a follow-up hook, example:
class page_gridsearchtest extends Page {
var $search=null;
function init() {
parent::init();
$g = $this->add('MVCGrid');
$g->setModel('Employees');
if($g){
$this->search=$g->addQuickSearch(array('fullname'));
if($this->search)
$this->api->addHook('post-init',array($this,'MyHook')); // add hook
}
}
function MyHook(){ // hooked method
if($this->search->search_field) {
if($this->search->search_field->get()=='')
$this->search->search_field->set('Juan'); // set initial search if blank
$this->search->search_field->setCaption('Employee Name Search');
}
}
}
this will set a CAPTION beside the QuickSearch field and add a DEFAULT search text if the search field is empty.
if this is just a one-time thing, then this may be useful as a quick fix because directly making changes to the library source is very unorthodoxed and does not follow the OOP concept of extending and sub-classing as promoted by ATK.

How to get data from Magento System Configuration

I just wandering on how I can get the configuration data for my custom module. The configuration can be set from the admin system->configuration and how to pull it in frontend?
$configValue = Mage::getStoreConfig('sectionName/groupName/fieldName');
sectionName, groupName and fieldName are present in etc/system.xml file of your module.
The above code will automatically fetch config value of currently viewed store.
If you want to fetch config value of any other store than the currently viewed store then you can specify store ID as the second parameter to the getStoreConfig function as below:
$store = Mage::app()->getStore(); // store info
$configValue = Mage::getStoreConfig('sectionName/groupName/fieldName', $store);
you should you use following code
$configValue = Mage::getStoreConfig(
'sectionName/groupName/fieldName',
Mage::app()->getStore()
);
Mage::app()->getStore() this will add store code in fetch values so that you can get correct configuration values for current store this will avoid incorrect store's values because magento is also use for multiple store/views so must add store code to fetch anything in magento.
if we have more then one store or multiple views configured then this will insure that we are getting values for current store
Magento 1.x
(magento 2 example provided below)
sectionName, groupName and fieldName are present in etc/system.xml file of the module.
PHP Syntax:
Mage::getStoreConfig('sectionName/groupName/fieldName');
From within an editor in the admin, such as the content of a CMS Page or Static Block; the description/short description of a Catalog Category, Catalog Product, etc.
{{config path="sectionName/groupName/fieldName"}}
For the "Within an editor" approach to work, the field value must be passed through a filter for the {{ ... }} contents to be parsed out. Out of the box, Magento will do this for Category and Product descriptions, as well as CMS Pages and Static Blocks. However, if you are outputting the content within your own custom view script and want these variables to be parsed out, you can do so like this:
<?php
$example = Mage::getModel('identifier/name')->load(1);
$filter = Mage::getModel('cms/template_filter');
echo $filter->filter($example->getData('field'));
?>
Replacing identifier/name with the a appropriate values for the model you are loading, and field with the name of the attribute you want to output, which may contain {{ ... }} occurrences that need to be parsed out.
Magento 2.x
From any Block class that extends \Magento\Framework\View\Element\AbstractBlock
$this->_scopeConfig->getValue('sectionName/groupName/fieldName');
Any other PHP class:
If the class (and none of it's parent's) does not inject \Magento\Framework\App\Config\ScopeConfigInterface via the constructor, you'll have to add it to your class.
// ... Remaining class definition above...
/**
* #var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $_scopeConfig;
/**
* Constructor
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
// ...any other injected classes the class depends on...
) {
$this->_scopeConfig = $scopeConfig;
// Remaining constructor logic...
}
// ...remaining class definition below...
Once you have injected it into your class, you can now fetch store configuration values with the same syntax example given above for block classes.
Note that after modifying any class's __construct() parameter list, you may have to clear your generated classes as well as dependency injection directory: var/generation & var/di
for example if you want to get EMAIL ADDRESS from config->store email addresses.
You can specify from wich store you will want the address:
$store=Mage::app()->getStore()->getStoreId();
/* Sender Name */
Mage::getStoreConfig('trans_email/ident_general/name',$store);
/* Sender Email */
Mage::getStoreConfig('trans_email/ident_general/email',$store);

Categories