magento-lts icon indicating copy to clipboard operation
magento-lts copied to clipboard

Add custom source for multiselect product attributes

Open bastienlm opened this issue 9 years ago • 15 comments

When you create your own multiselect product attribute with a custom source model, this attribute is not displayed on the layered navigation.

Thanks to this fix, you can show your attribute on the filter. In first time I browse all attribute_id and if the attribute have a custom source model I set all custom values on options array.

(Inspirated by : http://stackoverflow.com/questions/7597448/multi-select-filter-in-layered-navigation)

bastienlm avatar Oct 14 '16 14:10 bastienlm

@drobinson Can you run this code and check it is working?

@drobinson On a side note, we need to get a working testing framework in place and mandate tests for PRs.

LeeSaferite avatar Oct 16 '16 16:10 LeeSaferite

On hold ... broke indexer (or ive done something wrong)

sreichel avatar Jan 31 '18 15:01 sreichel

@sreichel Strange, I have this fix on a big project since many month and I have no problem. When you say 'broke indexer', you can't reindex or it's broke after reindex ? product attributes indexe ?

bastienlm avatar Feb 01 '18 22:02 bastienlm

With this fix I wasnt able to reindex product attributes. As said ... maybe Ive done something wong (just copy&paste to our dev server where I have some multiselect attributes with custom source model)

Just put on hold to verify :)

sreichel avatar Feb 01 '18 22:02 sreichel

I've update my PR for respect space, thanks @colinmollenhour for the report.

bastienlm avatar Mar 01 '18 12:03 bastienlm

@sreichel Did you ever figure out if there is indeed a bug with this PR or not?

colinmollenhour avatar Oct 04 '18 18:10 colinmollenhour

@colinmollenhour I will check it on sunday.

sreichel avatar Oct 05 '18 16:10 sreichel

With this code i cannot reindex product attribtues.

@bastienlm which magento version do you use for your project? This PR was for 1.9.3.0, (in 2016) maybe something else has changed.

@colinmollenhour @Flyingmana can you please test it, too?

sreichel avatar Oct 07 '18 11:10 sreichel

This code work on Magento ver. 1.9.3.7 (no LTS)

I try to test this on the last LTS version this week.

bastienlm avatar Oct 08 '18 10:10 bastienlm

This PR needs to be rebased to OpenMage:1.9.4.x.

addison74 avatar Jun 02 '22 19:06 addison74

What about @sreichel remarks?

addison74 avatar Jun 15 '22 05:06 addison74

What about @sreichel remarks?

that's precisely what i checked and it seems to work for me

fballiano avatar Jun 15 '22 07:06 fballiano

I've applied this patch on a customer's project (on my local copy) and I can reindex without problems:

fab@MBP-Fab ~/P/x (prod)> php shell/indexer.php reindexall
Category Flat Data index was rebuilt successfully in 00:00:00
Product Flat Data index was rebuilt successfully in 00:00:00
Stock Status index was rebuilt successfully in 00:00:00
Catalog product price index was rebuilt successfully in 00:00:00
Category URL Rewrites index was rebuilt successfully in 00:00:00
Product URL Rewrites index was rebuilt successfully in 00:00:00
URL Redirects index was rebuilt successfully in 00:00:00
Catalog Category/Product Index index was rebuilt successfully in 00:00:00
Search Index index was rebuilt successfully in 00:00:02
Tag Aggregation Data index was rebuilt successfully in 00:00:00
Product Attributes index was rebuilt successfully in 00:00:01
fab@MBP-Fab ~/P/x (prod)> 

so I don't know...

fballiano avatar Aug 23 '22 20:08 fballiano

Has someone example code to test with? (I have just plain OM with sample data)

sreichel avatar Aug 23 '22 20:08 sreichel

I tested on an empty store and one of my customer's data, but only the reindex process.

fballiano avatar Aug 23 '22 21:08 fballiano

I get

There was a problem with reindexing process.

This is caused by

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '14-143-1-0' for key 'PRIMARY', query was: INSERT INTO catalog_product_index_eav_idx (entity_id,attribute_id,store_id,value) VALUES (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?)

To replicate, set source_model to customer/entity_address_attribute_source_country in the table eav_attribute for the multiselect attribute. Then go to backend > System > Index Management > reindex "Product Attributes".

This is because the column value in the table catalog_product_index_eav_idx only accepts int. This means that the source model must not return string value, in the my example, the values are the country codes such as 'US", 'FR', which are all converted to 0 when saving to the table resulting in constraint violations.

kiatng avatar May 23 '23 08:05 kiatng

mmmm but if the "keys" of the custom source were "int" then it would work? because it would probably be better than nothing? maybe documenting the limitation?

fballiano avatar May 23 '23 09:05 fballiano

The core really does not expect custom source_model for attributes that use layered navigation. This PR is half-baked solution for it. Do we really want to cater for these edge cases? In any case, the following code prevents the integrity constraint violation, but it won't help with layered nav:

        $select  = $adapter->select()
            ->from($this->getTable('eav/attribute'), ['attribute_id'])
            ->where('source_model != ?', 'eav/entity_attribute_source_table')
            ->where('attribute_id IN (?)', $attrIds);
        $query = $select->query();
        while ($row = $query->fetch()) {
            $attribute = Mage::getResourceSingleton('catalog/product')->getAttribute($row['attribute_id']);
            if ($source = $attribute->getSource()) {
                if ($sourceOptions = $source->getAllOptions()) {
                    unset($options[$row['attribute_id']]);
                    foreach ($sourceOptions as $sourceOption) {
                        // Values can only be integer
                        if (is_int($sourceOption['value']) || is_string($sourceOption['value']) && ctype_digit($sourceOption['value'])) {
                            $options[$row['attribute_id']][$sourceOption['value']] = true;
                        }
                    }
                }
            }
        }

Because there is no good solution, I think this PR should be closed.

kiatng avatar May 23 '23 15:05 kiatng

agreed, it could anyway be reopened, just in case

fballiano avatar May 23 '23 15:05 fballiano