Jump to content

[MODIFICATION] Select multiple values for one feature


Recommended Posts

Même sujet en Français

 

Well, I know that the forum doesn't encourage modifying PrestaShop's core files but I think this feature really misses to many people.

So here are the changes I made on PS 1.4.8.2 to use features with multiple values:

 

For PS v1.5.x see this post : http://www.prestasho...post__p__967294

 

First you have to modify table ps_feature_product to allow inserting multiple lines with same id_feature and id_product. (I assume your table's prefix is "ps", otherwise just replace ps by your prefix)

 

- Access your database via phpmyadmin, and display the structure of table ps_feature_product

- In index area, delete the PRIMERY characteristic of fields id_feature and id_product.

post-344943-0-05893200-1340994439_thumb.png

- If index area doesn't appear, click the SQL tab and run this command:

ALTER TABLE ps_feature_product DROP PRIMARY KEY

 

Now your database is ready to receive multiple values for a given feature.

 

 

Then you have to modify the file AdminProducts.php located in /admin/tabs/

Edit AdminProducts.php to make the following changes:

 

In postProcess function, line 668 (PS 1.4.8.2, maybe another line for another version ...)

Replace:

   if ($val)
	   $product->addFeaturesToDB($match[1], $val);

With:

   if ($val && $val[0] != 0)
	   foreach ($val AS $feature_val) $product->addFeaturesToDB($match[1], $feature_val);

$val variable will become an array containing different values of the feature. So we will add a line for each value in ps_feature_product table.

 

 

In displayFormFeatures function (lines 3578 - PS 1.4.8.2)

Replace:

	   	 foreach ($feature AS $tab_features)
			{
				$current_item = false;
				$custom = true;
				foreach ($obj->getFeatures() as $tab_products)
					if ($tab_products['id_feature'] == $tab_features['id_feature'])
						$current_item = $tab_products['id_feature_value'];

				$featureValues = FeatureValue::getFeatureValuesWithLang((int)$cookie->id_lang, (int)$tab_features['id_feature']);

				echo '
				<tr>
					<td>'.$tab_features['name'].'</td>
					<td style="width: 30%">';

				if (sizeof($featureValues))
				{
					echo '
						<select id="feature_'.$tab_features['id_feature'].'_value" name="feature_'.$tab_features['id_feature'].'_value"
							onchange="$(\'.custom_'.$tab_features['id_feature'].'_\').val(\'\');">
							<option value="0">--- </option>';

					foreach ($featureValues AS $value)
					{
						if ($current_item == $value['id_feature_value'])
							$custom = false;
						echo '<option value="'.$value['id_feature_value'].'"'.(($current_item == $value['id_feature_value']) ? ' selected="selected"' : '').'>'.substr($value['value'], 0, 40).(Tools::strlen($value['value']) > 40 ? '...' : '').' </option>';
					}

					echo '</select>';
				}
				else
					echo '<input type="hidden" name="feature_'.$tab_features['id_feature'].'_value" value="0" /><span style="font-size: 10px; color: #666;">'.$this->l('N/A').' - <a href="index.php?tab=AdminFeatures&addfeature_value&id_feature='.(int)$tab_features['id_feature'].'&token='.Tools::getAdminToken('AdminFeatures'.(int)(Tab::getIdFromClassName('AdminFeatures')).(int)($cookie->id_employee)).'" style="color: #666; text-decoration: underline;">'.$this->l('Add pre-defined values first').'</a></span>';

				echo '
					</td>
					<td style="width:40%" class="translatable">';
				$tab_customs = ($custom ? FeatureValue::getFeatureValueLang($current_item) : array());
				foreach ($this->_languages as $language)
					echo '
						<div class="lang_'.$language['id_lang'].'" style="display: '.($language['id_lang'] == $this->_defaultFormLanguage ? 'block' : 'none').'; float: left;">
							<textarea class="custom_'.$tab_features['id_feature'].'_" name="custom_'.$tab_features['id_feature'].'_'.$language['id_lang'].'" cols="40" rows="1"
								onkeyup="if (isArrowKey(event)) return ;$(\'#feature_'.$tab_features['id_feature'].'_value\').val(0);" >'.htmlentities(Tools::getValue('custom_'.$tab_features['id_feature'].'_'.$language['id_lang'], FeatureValue::selectLang($tab_customs, $language['id_lang'])), ENT_COMPAT, 'UTF-8').'</textarea>
						</div>';
				echo '
					</td>
				</tr>';
			}

With :

	   	 foreach ($feature AS $tab_features)
			{
				$current_item = false;
				$custom = true;
				foreach ($obj->getFeatures() as $tab_products)
					if ($tab_products['id_feature'] == $tab_features['id_feature'])
						$current_item[] = $tab_products['id_feature_value'];

				$featureValues = FeatureValue::getFeatureValuesWithLang((int)$cookie->id_lang, (int)$tab_features['id_feature']);

				echo '
				<tr>
					<td>'.$tab_features['name'].'</td>
					<td style="width: 30%">';

				if (sizeof($featureValues))
				{
					echo '<div style="width:200px;max-height:200px;margin:4px 0px;padding:2px;border:1px solid #e0d0b1;overflow: auto;text-align:left;">';
					if (!$current_item) $current_item[0] = null;
					foreach ($featureValues AS $value) if (in_array($value['id_feature_value'], $current_item)) $custom = false;
					echo '<input type="checkbox" style="display:none;" name="feature_'.$tab_features['id_feature'].'_value[]" id="feature_'.$tab_features['id_feature'].'_value" value="" '.($custom ? 'checked="checked"' : '').'/>';
					foreach ($featureValues AS $value) {
						echo '<label style="padding:2px;text-align:left;cursor:pointer;width:98%;'.((in_array($value['id_feature_value'], $current_item)) ? 'background-color:#acd8fe;' : '').'">
						<input type="checkbox" name="feature_'.$tab_features['id_feature'].'_value[]" class="feature_'.$tab_features['id_feature'].'_value" value="'.$value['id_feature_value'].'"'.((in_array($value['id_feature_value'], $current_item)) ? ' checked="checked"' : '')
						.'onchange="$(\'.custom_'.$tab_features['id_feature'].'_\').val(\'\'); $(\'#feature_'.$tab_features['id_feature'].'_value\').attr(\'checked\', false); if ($(this).attr(\'checked\')) $(this).closest(\'label\').css(\'background-color\', \'#acd8fe\'); else $(this).closest(\'label\').css(\'background-color\', \'#ffffff\');"> '
						.substr($value['value'], 0, 40).(Tools::strlen($value['value']) > 40 ? '...' : '').' </label><br />';
					}
					echo '</div>';
				}
				else
					echo '<input type="hidden" name="feature_'.$tab_features['id_feature'].'_value" value="0" /><span style="font-size: 10px; color: #666;">'.$this->l('N/A').' - <a href="index.php?tab=AdminFeatures&addfeature_value&id_feature='.(int)$tab_features['id_feature'].'&token='.Tools::getAdminToken('AdminFeatures'.(int)(Tab::getIdFromClassName('AdminFeatures')).(int)($cookie->id_employee)).'" style="color: #666; text-decoration: underline;">'.$this->l('Add pre-defined values first').'</a></span>';

				echo '
					</td>
					<td style="width:40%" class="translatable">';
				$tab_customs = ($custom ? FeatureValue::getFeatureValueLang($current_item[0]) : array());
				foreach ($this->_languages as $language)
					echo '
						<div class="lang_'.$language['id_lang'].'" style="display: '.($language['id_lang'] == $this->_defaultFormLanguage ? 'block' : 'none').'; float: left;">
							<textarea class="custom_'.$tab_features['id_feature'].'_" name="custom_'.$tab_features['id_feature'].'_'.$language['id_lang'].'" cols="40" rows="1"
							onkeyup="if (isArrowKey(event)) return; $(\'#feature_'.$tab_features['id_feature'].'_value\').attr(\'checked\', true); $(\'.feature_'.$tab_features['id_feature'].'_value\').attr(\'checked\', false); $(\'.feature_'.$tab_features['id_feature'].'_value\').closest(\'label\').css(\'background-color\', \'#ffffff\');" >'
							.htmlentities(Tools::getValue('custom_'.$tab_features['id_feature'].'_'.$language['id_lang'], FeatureValue::selectLang($tab_customs, $language['id_lang'])), ENT_COMPAT, 'UTF-8').'</textarea>
						</div>';
				echo '
					</td>
				</tr>';
			}

 

$current_item variable is converted to array and retrieves the different recorded values of the feature.

The select is converted to a list of checkboxes which values will be retrieved by the postProcess function previously modified.

 

Now you can select multiple values for your features by clicking the desired values.

post-344943-0-58119400-1345163439_thumb.png

 

 

For those under 1.4.8.2 PS, here is my modified AdminProducts.php:

AdminProducts.php

 

 

Again for PS 1.4.8.2, here are the files ProductController.php and CompareController.php, to ADD into /override/controllers/ to correct the display of multiple value features in product data sheet and product comparison page (see screenshots)

ProductController.php

post-344943-0-83427900-1341234522_thumb.png

CompareController.php

post-344943-0-98980200-1341234548_thumb.png

If you use another version of prestashop or if you already have these files in your override folder, open the files and locate the modified code to apply the mods by yourself on your files (the mods are commented)

 

I made many testing on a site I'm developing locally, and everything seems to work fine.

- The layered navigation module handles the multiple values of features, without any aditional mod.

- You can still enter custom values (not handled by layered navigation)

- With the two attached override files, multiple value ​​features are correctly displayed in product data sheet and product comparison page.

 

 

Voila, I think this mod may interest many people...

 

Despite all my tests, it is always possible that this modification interferes with other parts of the code, so if you have problems let us know here.

Edited by Mellow (see edit history)
  • Like 5

Share this post


Link to post
Share on other sites
  • 2 weeks later...
  • Replies 245
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

1.6 version attached. select-multiple-features-values_1.6.zip

Modification for PS 1.5.3.1 and 1.5.4.0   I have resigned from those overrides /override/controllers/front/ProductController.php /override/controllers/front/CompareController.php   and I have ad

OK, for Prestashop v1.5.1 :   In PS 1.5, admin controllers and admin templates are overridable, so we no longer need to modify core files.   There was 4 files to modify : /controllers/admin/Admin

Posted Images

How does this handle feature on a csv import? Can you just seperate the values wth commas in the import or do you have to go into the back end do select them?

  • Like 1

Share this post


Link to post
Share on other sites

Product import hasn't been modified since it depends on the way features are exported.

 

I don't use csv export / import, and Prestashop doesn't handle export natively, so I can't talk about a particular export module, but I think most of them would simply export the first value found in database for each feature.

 

If you can modify your export module (or directly your csv) to get comma separated values like this :

………;………;………;………;Feature:Video output;………;………..

………;………;………;………;DVI, HDMI, VGA;………;………..

 

You could modify your AdminImport.php, to split values ​​when importing and save them separately.

 

AdminImport.php line 863 (for PS 1.4.8.2)

 

Replace:

	   	 foreach ($features AS $feature => $value)
				if (!strncmp($feature, '#F_', 3) AND Tools::strlen($product->{$feature}))
				{
					$feature_name = str_replace('#F_', '', $feature);
					$id_feature = Feature::addFeatureImport($feature_name);
					$id_feature_value = FeatureValue::addFeatureValueImport($id_feature, $product->{$feature});
					Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value);
				}

 

With:

	   	 foreach ($features AS $feature => $value)
				if (!strncmp($feature, '#F_', 3) AND Tools::strlen($product->{$feature}))
				{
					$feature_name = str_replace('#F_', '', $feature);
					$id_feature = Feature::addFeatureImport($feature_name);
					if (preg_match("/,/i", $product->{$feature})) {
						$thevalues = explode(",", $product->{$feature});
						foreach ($thevalues as $thevalue)
							if (sizeof(trim($thevalue))) {
								$id_feature_value = FeatureValue::addFeatureValueImport($id_feature, trim($thevalue));
								Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value);
							}
					} else {
						$id_feature_value = FeatureValue::addFeatureValueImport($id_feature, $product->{$feature});
						Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value);
					}
				}

  • Like 2

Share this post


Link to post
Share on other sites

If I make those modifications then when I import using a csv it will automaticly select those multiple values? or will I still have to go into the back end and multi click each item?

Share this post


Link to post
Share on other sites

It will automatically select the right values for your product feature.

Assuming that these values exists as predefined values for the given feature...

Share this post


Link to post
Share on other sites
  • 2 weeks later...

I have a question... Please help me if you know the correct way to handle this, but i suspect this might be the only way...

 

Say i have a store where I have a product which suits many different brands of vacuum cleaner, but not all vacuum cleaners. I would like to create a filtered navigation system where by visitors can select their vacuum cleaner, type, model, year etc etc and it will return products suitable tor their specific model.... Now back to this product I have that is adequate for many models.. It is possible to apply.. well I guess a feature?? where you can list out the brands it would be adequate for and then upon selection of which ever brand, if the brand is part of that feature, this product it returned?

 

I hope this makes sense.. I'm not sure i'm meant to be looking at features... Can you filter by anything else?

 

Any advice here would be useful to me

 

Thanks

Rob

Share this post


Link to post
Share on other sites

I'm not sure of understanding exactly your wish, but for exemple :

 

- If you create a feature called "Compatible Brands" where you add as values the brands that may be compatible with your products.

- Then you add this feature as a filter for the layered navigation module.

- And, for a given product, you chose let's say brand_a and brand_x as compatible brands

 

Then, selecting one of these brands in the area "Compatible Brands" of layered navigation module, will return the product. (depending, of course, on other selected filters)

 

Is that what you're looking for ?

Share this post


Link to post
Share on other sites

Hi there,

 

Yes, that is correct - Do i need this modification to be able to do this, or is this part of the core? Also, how / where would i create a feature whereby i can create values, just like your example above?

 

Cheers

Rob

Share this post


Link to post
Share on other sites

Natively Prestashop allows you to create features and their predefined values, in back office => Catalog => Features

 

But when you add or edit a product, you can select only one of the predefined values for each feature.

 

So you actually need this modification to be able to select more then one value for a feature.

 

Regards

Share this post


Link to post
Share on other sites
  • 2 weeks later...

I've added several new features, populated with feature values, that appear in the layered navigation block.

 

Problem is that they're not sorted alphabetically - just in the order they were created.

 

I'm sure it must be somewhere in ProductController.php - I just can't pin down where.

 

Any and all help is very much appreciated.

Share this post


Link to post
Share on other sites

Not sure, but I think that you would like to sort the values of your features in layered navigation module.

In this case, you have to modify the module.

 

In blocklayered.php (getFilterBlock function)

 

~ line 2744 replace:

$sql_query['group'] = 'GROUP BY fv.id_feature_value ';

With:

$sql_query['group'] = 'GROUP BY fv.id_feature_value ORDER BY fvl.value ASC ';

 

~ line 2764 replace:

GROUP BY fv.id_feature_value';

With:

GROUP BY fv.id_feature_value ORDER BY fvl.value ASC';

 

Note that in case you disable "Hide filter values with no product matching" in layered navigation configuration, the values with no product matching will always be displayed at the end of the list...

  • Like 2

Share this post


Link to post
Share on other sites

Thanks Mellow - Looks like a great module :-)

 

I have a couple of quick questions:

 

How are the features selected in the admin, with check boxes I presume? (select all, select none?)

Does duplicating a product carry across this information?

Can you have multiple product features of this type for 1 product i.e compatible brands, compatible years?

Are these features displayed on the product page? Or is this purely for filtering purposes?

 

Thanks in advance.

 

Robert

Share this post


Link to post
Share on other sites

How are the features selected in the admin, with check boxes I presume? (select all, select none?)

Does duplicating a product carry across this information?

Can you have multiple product features of this type for 1 product i.e compatible brands, compatible years?

Are these features displayed on the product page? Or is this purely for filtering purposes?

 

Features are selected in product edition page in back office, with a multiselect box (see screenshot)

Features are common to all products, and values selected are kept when duplicating a product

Yes, you can have as many features as you want, with as many values as you want

Yes, features are displayed on product page and also on product comparison page

 

Regards

Share this post


Link to post
Share on other sites
  • 2 weeks later...

Hello mellow;

I have changed the database and necessary codings, and now could enter multiple features for one product, but the problem is that in the features it looks like the link here, here is the problem that i need feature name one time, and need multiple values in front of this, so how could i do this??

screen shot is attached here, i don't want to repeat functions or any feature name, but want to repeat its value,

post-388951-0-20269600-1344629835_thumb.jpg

Share this post


Link to post
Share on other sites

Hi sabexel2,

 

Please re check the first post, I have also attached two files (ProductController.php and CompareController.php) to ADD into /override/controllers/ to correct the display of multiple value features in data sheet and product comparison page.

 

If you use a version of prestashop older than 1.4.7.x or if you already have these files in your override folder (and if you understand french...) you can watch this post to make the mod manualy : http://www.prestasho...post__p__875553

 

Regards

Share this post


Link to post
Share on other sites

Oups !!!

 

if you use 1.3.7 you don't have override fonctionality

You will have to modify the core controllers (or their equivalents)

 

Unfortunately I don't know the structure of prestashop under 1.4.x

It seems that the equivalents of the controllers are in the root folder...

Share this post


Link to post
Share on other sites

Ok, for presta 1.3.7.0 you can try this :

 

In product.php (root folder) just after :

  	 $features = $product->getFrontFeatures(intval($cookie->id_lang));

insert :

  	 $done = null;
       foreach ($features as $key => $feature) {
           $caract = $features[$key]['name'];
           if (!isset($done[$caract][0])) {
               $features[$key]['name'] .= ' :' ;
               $done[$caract][0] = true;
               $done[$caract][1] = $key;
           } else {
               $features[(int)$done[$caract][1]]['value'] .= ', ' . $features[$key]['value'] ;
               unset($features[$key]);
           }
       }

 

I think it should correct the data sheet display, but note that I did not test this, I just adapted the code...

 

Let me know if it works

Share this post


Link to post
Share on other sites

Here is a small improvement:

 

The use of multiselect is not always convenient (nor aesthetic) and causes a different behavior in different browsers. So I replaced it with checkboxes in a div whose size adapts to the number of values of the feature.

And so the little javascript is no longer necessary either.

 

It looks like this on product sheet in BO:

post-344943-0-58119400-1345163439_thumb.png

 

I've updated the original post with the new code and a new file AdminProducts.php for PS 1.4.8.2

  • Like 2

Share this post


Link to post
Share on other sites

Thank you Mellow!!! Amazing modification. Also maybe you can help to create product feature groups? It would be amazing to group features. Example:

 

Screen:

  • 15,6
  • 1920x1080
  • LED

Memory:

  • 4GB DDR3
  • 2TB HDD

 

 

It would be amazing to have this feature integrated without modules and controlable from admin features tab.

Edited by sakrafanas (see edit history)

Share this post


Link to post
Share on other sites

Sure that being able to group (and sort) features as we want would be nice.

But it would be a more deep modification, probably including other core files and database alteration.

Not in my plans for now, sorry.

Share this post


Link to post
Share on other sites

I have Presta version 1.4.4.1 and i substituted my original Adminproducts.php as well as the Comparecntroller.php and Productcontroller.php with your files offered for download. The features now allow for multiple selection of defined values and they can now be seen in the front products listing tab labled as Data Sheets. Thank you very much for this easy fix.

Share this post


Link to post
Share on other sites

Thank you for your best modification.

I test in prestashop1.4.8.2 it is work fine!

 

Thank you!

 

 

I was wondering if you can do the following filter:

I have a front fender for a Honda 125 from 1981 to 1983

Same fender and for KTM 85 from 1991 to 1992

How can you make such a filter?

 

Something like:

Honda 125 1981

Honda 125 1982

Honda 125 1983

Ktm 85 1991

Ktm 85 1992

 

Thanks in advance!

Share this post


Link to post
Share on other sites

@ Ra Ra

 

Are you talking about the layered navigation filters ?

 

If so you can make a feature named "Fits for" and then add each "model + year" as a value

 

But I feel that what you really need is the same as sakrafanas asked in a post above. That's to say grouping features by theme, like this :

 

Fits for :

Honda 125 : 1981, 1982, 1983

KTM 85 : 1991, 1992

 

Unfortunately there is no way to do that !

Share this post


Link to post
Share on other sites

Why instead of deleting the primary key [ALTER TABLE DROP PRIMARY KEY ps_feature_product], not used as primary key id_featured, id_product and id_featured_value?

Would the search faster?

Congratulations!!!

Share this post


Link to post
Share on other sites
  • 3 weeks later...
  • 2 weeks later...

Any luck with 1.5?

 

I've found the function is located in AdminProductsController

and the html part is in features.tpl but i can not modify it properly...

 

if sizeof($available_feature.featureValues)}  <select id="feature_{$available_feature.id_feature}_value" name="feature_{$available_feature.id_feature}_value"   onchange="$('.custom_{$available_feature.id_feature}_').val('');">   <option value="0">--- </option> {foreach from=$available_feature.featureValues item=value}  <option value="{$value.id_feature_value}"{if $available_feature.current_item == $value.id_feature_value}selected="selected"{/if} >   {$value.value|truncate:40}   </option> {/foreach}  </select> {else}  <input type="hidden" name="feature_{$available_feature.id_feature}_value" value="0" />   <span>{l s='N/A'} -   <a href="{$link->getAdminLink('AdminFeatures')|escape:'htmlall':'UTF-8'}&addfeature_value&id_feature={$available_feature.id_feature}" class="confirm_leave button"><img src="../img/admin/add.gif" alt="values_first" title="{l s='Add pre-defined values first'}" /> {l s='Add pre-defined values first'}</a>  </span> {/if}

 

Share this post


Link to post
Share on other sites

OK, for Prestashop v1.5.1 :

 

In PS 1.5, admin controllers and admin templates are overridable, so we no longer need to modify core files.

 

There was 4 files to modify :

/controllers/admin/AdminProductsController.php (that's where features are treated/saved)

/admin/themes/default/template/controllers/products/features.tpl (template which displays features in product page in back office)

/controllers/front/ProductController.php (controller which loads features for product page in front office)

/controllers/front/CompareController.php (controller which loads features for comparison page)

 

These files can be overridden like this :

/override/controllers/admin/AdminProductsController.php

/override/controllers/admin/templates/products/features.tpl

/override/controllers/front/ProductController.php

/override/controllers/front/CompareController.php

 

[Edit] See this post http://www.prestasho...ost__p__1085967 for PS1.5.3 and above

 

So, here are the override files for PS 1.5.1

select-multiple-feature-values_override-files_PSv1.5.1.zip

Just copy the content of this archive over your PS 1.5.1 override folder, and you're done.

 

Don't forget to modify the structure of table ps_feature_product

ALTER TABLE ps_feature_product DROP PRIMARY KEY

OR :

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

As suggested by petete2008

 

As usual, you should test localy before applying to an online store...

Edited by Mellow (see edit history)
  • Like 6

Share this post


Link to post
Share on other sites

OK, for Prestashop v1.5.1 :

 

In PS 1.5, admin controllers and admin templates are overridable, so we no longer need to modify core files.

 

As usual, you should test localy before applying to an online store...

 

Thank you so much Mellow!

Will try it now.

 

 

It works!

Thank you a lot again... this is the must be feature

Tried with ALTER TABLE ps_feature_product DROP PRIMARY KEY

 

Tested with

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

 

It works too... which one is better? )

Edited by doubleD (see edit history)

Share this post


Link to post
Share on other sites

Tested with

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

It works too... which one is better? )

 

This second option should, in theory, speed up a bit the requests on table ps_feature_product

If you realy have lots of products with lots of features that can have multiple values, maybe you can notice a difference...

Share this post


Link to post
Share on other sites
  • 4 weeks later...

OK, for Prestashop v1.5.1 :

...

 

(updated)

 

For v1.5.2, just copying the files does not do the trick. If you want to apply this (great) change, you should compare the files and apply the changes...

 

Also, the features.tpl file is now in admin/themes/default/template/controllers/products

Edited by Fortega (see edit history)

Share this post


Link to post
Share on other sites

An other remark: if the order of feature values in you product page is important, you should modify two queries in classes/Product.php:

 

replace all occurences of ORDER BY f.position ASC with ORDER BY f.position ASC, pf.id_feature_value ASC'

 

This way, the feature values have the same order as in your admin-section (the order you entered the values)

(this works on 1.5.2, not tested on other versions)

 

I had feature values '1', '2', '3' and '4' for feature 'myFeature'. For a specific product, '1', '3' and '4' were selected. On my product page it was shown as:

 

myFeature : '3', '1', '4'

 

 

Another minor tweak: if you don't like a space before the :, you should edit ProductController.php and replace

$features[$key]['name'] .= ' :' ;

with

$features[$key]['name'] .= ':' ;

Edited by Fortega (see edit history)
  • Like 1

Share this post


Link to post
Share on other sites

For v1.5.2, just copying the files does not do the trick. If you want to apply this (great) change, you should compare the files and apply the changes...

Sorry but I just tested on a fresh install of PS 1.5.2 and it works just fine...

I don't know what is exactly the problem, but maybe you didn't install the files the right way.

Anyway, if you don't care modifying your core files it's up to you, but It's just a pity because overriding helps keeping compatibility after upgrades.

 

Also, the features.tpl file is now in admin/themes/default/template/controllers/products

Exactly the same as version 1.5.1 !

And the override file has to be in override/controllers/admin/templates/products/ (also same as v1.5.1)

 

Regards

Share this post


Link to post
Share on other sites
  • 4 weeks later...

@mellow

 

Not sure if I did something wrong, but I installed your 1.5.1 version on 1.5.2.

 

The bug i seem to be having is in the BO. I can see the multiple selection of features, but after i select the features and click save, the features do not save.

 

In the FO, all my features have the same value as the first feature.

 

(Not sure if this makes a difference, but my table prefix are different from the default.)

Edited by mikecheung (see edit history)

Share this post


Link to post
Share on other sites

Table prefix shouldn't make any difference, but did you alter table feature_product using the proper prefix ?

ALTER TABLE {your-prefix}_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

Share this post


Link to post
Share on other sites

Table prefix shouldn't make any difference, but did you alter table feature_product using the proper prefix ?

ALTER TABLE {your-prefix}_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

 

yes i did

 

UPDATE: Figured out what happened. In the BO, the files I copied over did not transfer properly and in the FO I am using a module for my spec, just had to edit that a little. Thanks Mellow!

Edited by mikecheung (see edit history)

Share this post


Link to post
Share on other sites

OK, for Prestashop v1.5.1 :

 

In PS 1.5, admin controllers and admin templates are overridable, so we no longer need to modify core files.

 

There was 4 files to modify :

/controllers/admin/AdminProductsController.php (that's where features are treated/saved)

/admin/themes/default/template/controllers/products/features.tpl (template which displays features in product page in back office)

/controllers/front/ProductController.php (controller which loads features for product page in front office)

/controllers/front/CompareController.php (controller which loads features for comparison page)

 

These files can be overridden like this :

/override/controllers/admin/AdminProductsController.php

/override/controllers/admin/templates/products/features.tpl

/override/controllers/front/ProductController.php

/override/controllers/front/CompareController.php

 

So, here are the override files for PS 1.5.1

select-multiple-feature-values_override-files_PSv1.5.1.zip

Just copy the content of this archive over your PS 1.5.1 override folder, and you're done.

 

Don't forget to modify the structure of table ps_feature_product

ALTER TABLE ps_feature_product DROP PRIMARY KEY

OR :

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

As suggested by petete2008

 

As usual, you should test localy before applying to an online store...

Although I'm sure this is useful, I don't know what this does! A more in depth explanation is greatly appreciated

Share this post


Link to post
Share on other sites

Although I'm sure this is useful, I don't know what this does! A more in depth explanation is greatly appreciated

 

With these modifications, it is possible to select multiple feature values for one specific product feature. I implemented this on my webshop, and it works great. In the admin-section, you will get a list with checkboxes instead of a dropdown to link a feature to a product. On the front side, it looks like this: http://www.ikwileenspel.be/20-de-kolonisten-van-catan-het-kaartspel.html (see 'mechanisme': there are several feature values selected for feature 'mechanisme'.)

Share this post


Link to post
Share on other sites

For Group Product Features, there is a script here, but not updated for PS 1.5.2.

 

http://code.google.c...ouped-features/

 

Anybody knows to integrate this ?

 

Again thanks to Mellow for the work and Fortega for the tweaks

 

" modify two queries in Product.php:

 

replace all occurences of ORDER BY f.position ASC with ORDER BY f.position ASC, pf.id_feature_value ASC'

 

This way, the feature values have the same order as in your admin-section (the order you entered the values) "

 

" if you don't like a space before the :, you should edit ProductController.php and replace

$features[$key]['name'] .= ' :' ;

with

$features[$key]['name'] .= ':' ; "

Share this post


Link to post
Share on other sites
  • 5 weeks later...

My God!!!

 

I'm a complete newb when it comes to Prestashop. I've only been using it for about 2 - 3 months but this just seems a ridiculous way of doing things. Why isn't this a core feature?

 

I carry products (As do most people) that require 2 or 3 predefined values in the same feature.

I use the template in Layered Navigation to create a filter list for people to search under but as it stands I currently have to choose 1 value for that filter! Even if my clients want to filter for products that carry all 3 values, I cant help them! It's a really stupid way of handling it.

 

Were do I suggest to Prestashop that they should rectify this in the next update?

 

Thanks.

 

Karl

Share this post


Link to post
Share on other sites
  • 2 weeks later...

Modification for PS 1.5.3.1 and 1.5.4.0

 

I have resigned from those overrides

/override/controllers/front/ProductController.php

/override/controllers/front/CompareController.php

 

and I have added one override

/override/classes/Product.php

which works for pages: product details, compare products , RandomSpecial, BestSales, product Packs.

 

In PS 1.5.4, you have to also delete file: /cache/class_index.php after copying new files to your override folder.

 

<?php
class Product extends ProductCore
{
public static function getFrontFeaturesStatic($id_lang, $id_product)
{
 $process = (!array_key_exists($id_product.'-'.$id_lang, parent::$_frontFeaturesCache));
 $features = parent::getFrontFeaturesStatic($id_lang, $id_product);

 //PWeb: join multiple values of one feature into one value
 if ($process AND count($features)) {
  $features_key = array();
  foreach ($features as $key => $feature) {
if (!array_key_exists($feature['name'], $features_key)) {
 $features_key[$feature['name']] = $key;
} else {
 $features[ (int)$features_key[$feature['name']] ]['value'] .= ', ' . $feature['value'] ;
 unset($features[$key]);
}
  }
  parent::$_frontFeaturesCache[$id_product.'-'.$id_lang] = $features;
 }

 return $features;
}
}

Attachment has been updated and mistake in code has been corrected.

select-multiple-feature-values_override-files_PSv1.5.3.1.zip

Edited by pweb (see edit history)
  • Like 7

Share this post


Link to post
Share on other sites
  • 2 weeks later...

Just a little thing : in the zip achive, Product.php file, you have to replace :

 

if (!array_key_exists($feature['name'], $done)) {

 

by :

 

if (!array_key_exists($feature['name'], $features_key)) {

 

Manu

 

UPDATE : pweb's attachment has been corrected, thanks to him !

Edited by Edel (see edit history)
  • Like 1

Share this post


Link to post
Share on other sites

you guys are too helpful!!! :D

 

saved me hours of time and I cannot thank you enough.

 

I must agree with:

 

...this just seems a ridiculous way of doing things. Why isn't this a core feature?

 

..but all is now well :rolleyes:

 

 

 

[EDIT]

 

After doing this my category pages now throw a 500 server error.

 

But only the category pages do this?

 

Any suggestions?

 

 

[EDIT2]

 

I put debug mode on and got this:

 

Fatal error: Call to undefined method Product::getProductsImgs() in /home/public_html/override/controllers/front/CategoryController.php on line 18

Edited by stebee (see edit history)

Share this post


Link to post
Share on other sites

Just a little thing : in the zip achive, Product.php file, you have to replace :

if (!array_key_exists($feature['name'], $done)) {

by :

if (!array_key_exists($feature['name'], $features_key)) {

Manu

 

pweb's attachment has been updated and mistake in code has been corrected.

Edited by Mellow (see edit history)

Share this post


Link to post
Share on other sites

After doing this my category pages now throw a 500 server error.

But only the category pages do this?

Any suggestions?

 

I put debug mode on and got this:

Fatal error: Call to undefined method Product::getProductsImgs() in /home/public_html/override/controllers/front/CategoryController.php on line 18

 

Hi stebee,

 

It seems that you already had an override of the class Product.php that you overwrote with the new file.

 

You should restore your previous file, and instead of replacing it, add the modified function getFrontFeaturesStatic() inside it.

Share this post


Link to post
Share on other sites

Hello guys, i did all you say, first on my localhost and it worked, but when i changed to my online version its not working, i think there is something with the default language. On my local host was English but when i change it to Bulgarian it stop work too, In admin section the options are saved, but in product features in front site they are not. How to make this work in Bulgarian default language? Please excuse my bad English...

 

Edit: ye, now i am sure, its something abouth the language, the product that worked, i duplicated it, and the copy didnt work, only this first product created when default language was English. Pls help! i rly need this to work, its so perfect and usefull :/

 

Edit 2: Now even making all in English, default and interface language and disabling all other languages, its not working... Only this first product that i made with multiple features, before to change the language, work :/

 

I forgot to tell that only first feature value is taken to show, not second

Edited by e_anastassov (see edit history)

Share this post


Link to post
Share on other sites

Good day,

 

Many thanks Mellow and pweb,

I've made some changes to yours scripts:

- add the possibility to change the position of feature value (also with ajax drag and drop).

- the separator(between feature values) is space(by default), but it can be anythings typed at the end of each feature'value(,;- newline...).

- change presentation of product datasheet to be in a table with alternating row colors, not a list.

 

 

Regards

 

Edit:

i forgot something important, please add this line to "install.sql"

ALTER TABLE  `ps_feature_value` ADD  `position` INT( 10 ) UNSIGNED NOT NULL;

 

Separator replaced by prefix selectable among seven predefined prefixes.

 

Here are the override files for PS 1.5.3.1

multiple-feature-values_override-files_PSv1.5.3.1.zip

 

Here same screenshot:

post-358754-0-48550100-1367719483_thumb.jpg post-358754-0-48734100-1367719638_thumb.jpg

post-358754-0-41401800-1367719657_thumb.jpg post-358754-0-23790900-1367719668_thumb.jpg

Edited by Kadeh (see edit history)
  • Like 1

Share this post


Link to post
Share on other sites

This is great! Can some one tell me how to display the multiple features good in de product.tpl template.

I have now the old foreach loop, but this one not working for sure!

 

Thanks!

Share this post


Link to post
Share on other sites

Good work guys, thank you !

 

Can you help me to modify the blocklayered module ?

When I select 2 values in the same feature, I want a "AND" result, not a "OR"

 

Thank you for your help.

Share this post


Link to post
Share on other sites

I was looking for something like this.

 

Only one small problem.

After the change i get something like

Actor: [name of the actor]

Actor: [name of another actor]

 

Can someone pls help me only show the labe once?

Thanks

Share this post


Link to post
Share on other sites

@sadlyblue, I found the solution. You have to edit the product controller. I'll let you soon know what I modified!

 

@Modock, I'm looking for the same. If there is anyone who can help us out, please let uw know!

Share this post


Link to post
Share on other sites

@sadlyblue:

 

Open your productcontroller.php file. Check if you are using the override file. If so, open override/controllers/front/ProductController.php.

 

- Look for the array called: $this->context->smarty->assign(array(. (probably somewhere around line #252)

 

- change 'features' into: 'features' => $features, (now you just set features to a variable string. Next step is to give this string his content)

 

- Before the array in step 1 you add the following code:

$features = $this->product->getFrontFeatures($this->context->language->id);

$done = null;

foreach ($features as $key => $feature) {

$caract = $features[$key]['name'];

if (!isset($done[$caract][0])) {

$features[$key]['name'] .= '' ;

$done[$caract][0] = true;

$done[$caract][1] = $key;

} else {

$features[(int)$done[$caract][1]]['value'] .= ', ' . $features[$key]['value'] ;

unset($features[$key]);

}

}

 

 

Good luck!

  • Like 1

Share this post


Link to post
Share on other sites

yes i did

 

UPDATE: Figured out what happened. In the BO, the files I copied over did not transfer properly and in the FO I am using a module for my spec, just had to edit that a little. Thanks Mellow!

 

Hi mikecheung

 

I am having the same problem. I can select multiple values in the BO but they are not saved. Can you please explain in detail what you did to solve this?

 

Thanks.

Edited by jtrlho (see edit history)

Share this post


Link to post
Share on other sites

Hi mikecheung

 

I am having the same problem. I can select multiple values in the BO but they are not saved. Can you please explain in detail what you did to solve this?

 

Thanks.

 

Same problem for me. (1.5.3.1)

Share this post


Link to post
Share on other sites

Have you tested in PS v.1.4.9

In my case, it does not work.

 

Hi,

I use PS1.4.9 and everything works fine.

What exactly is not working ?

Did you follow the process on the 1st post of this topic ?

The files provided are for v1.4.8.2 so you have to modify your own files...

 

-------------------------------------------------------

 

For PS1.5.x users, sorry but it seems that PS1.5 has strange behaviours (for some it works fine, and for others not...)

As I haven't been testing for a long time on 1.5 versions, I really can't help.

Share this post


Link to post
Share on other sites
  • 3 weeks later...

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Black

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Cyan

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Magenta

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Yellow

Edited by bogdan2707 (see edit history)

Share this post


Link to post
Share on other sites

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Black

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Cyan

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Magenta

Warning: in_array() [function.in-array]: Wrong datatype for second argument in/home/tonere/public_html/cache/smarty/compile/5b4a70142d0b2211a00d70c54828797a667d5930.file.features.tpl.phpon line 97

onchange="$('.custom_8_').val(''); $('#feature_8_value').attr('checked', false); if ($(this).attr('checked')) $(this).closest('label').css('background-color', '#acd8fe'); else $(this).closest('label').css('background-color', '#ffffff');"> Yellow

 

After disabling Smarty Cache everything is ok !

Share this post


Link to post
Share on other sites

Hi mikecheung

 

I am having the same problem. I can select multiple values in the BO but they are not saved. Can you please explain in detail what you did to solve this?

 

Thanks.

 

The problem is that in one of the tables in your database, there is a attribute that is set to Unique by default by Prestashop. In order to select multiple features, you will need to make sure it is NOT unique. Give that a try and let me know how it goes. Sorry I forgot which table it was since this was done quite a while ago.

Share this post


Link to post
Share on other sites

Hi

I hope someone replies! :unsure:

Basically, i uploaded the files to a test site, it worked. I uploaded it to my real site, it didn't! So basically, i found another way (online) to do this (but not fully).

It involves editing blocklayered.php. You delete all occurrences of *AND (fv.custom IS NULL OR fv.custom = 0)*. What this does is allow one to enter values in the 'customised value' section. It's great because these values will now appear in layered navigation and for me (using store manager for Prestashop, importing the 'customised value' is a breeze!). The problem is the values aren't separated.

For example, i am categorising my clothes by many things including body shape. Some clothes suit many body shapes so i may write "Apple, Hour Glass" in the customised value section. In layered navigation (after the code removal), rather than appearing twice, so either one can be selected i.e.

  • Apple
  • Hour Glass

it appears as one selection:

  • Apple, hour glass

There must be a way to edit the blocklayered.php so that text in 'customised value' can be separated. For example, if there is a comma (,) between values, they can be treated as separate values. Or even a pipe (|), i don't know code so who knows!

 

Does anyone have any idea? I'll continue my search in thew mean time, but please help if you can... :D

Thanks so much!

Edited by Cari (see edit history)

Share this post


Link to post
Share on other sites

The problem is that in one of the tables in your database, there is a attribute that is set to Unique by default by Prestashop. In order to select multiple features, you will need to make sure it is NOT unique. Give that a try and let me know how it goes. Sorry I forgot which table it was since this was done quite a while ago.

 

Do you know which table is it? Can not find this.

Share this post


Link to post
Share on other sites

Hi guys

 

I finally managed to get the override to work but i do not know how to import the product.php (i cannot simply add it as the current file has data within it). I imported everything else and while the checkboxes are there, i'm unable to save more than one feature for products so i assume product.php (when i add it) will fix this.

Here is what i have in my product.php (already present in the override folder):

 

<?php
class Product extends ProductCore
{
public static function getProductsImgs($product_id)
{
$sql = '
 (SELECT * from `'._DB_PREFIX_.'image`
 WHERE id_product="'.$product_id.'" and cover=1)
  union
 (SELECT * from `'._DB_PREFIX_.'image`
 WHERE id_product="'.$product_id.'" and cover=0  ORDER BY `position` LIMIT 0,1 )

 LIMIT 0,2
 ';
	$result = Db::getInstance()->ExecuteS($sql);
return $result;
}
}

 

How do i incorporate the new product.php into this one? I'm not good with code and whenever i try to add it it breaks my website (server error). Is it because of the double "<?php class Product extends ProductCore {" in the beginning? I tried removing one, no luck, i tried several things, no luck...

 

Please, please help ")

x

Edited by Cari (see edit history)

Share this post


Link to post
Share on other sites

Hi Cari,

 

If you cannot save more than one feature value, this is not due to product.php.

Most probably you did not modify the database table to allow multiple value

 

You have to run this command on your database using phpmyadmin :

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

(assuming "ps" is your table prefix, otherwise replace ps_ with your prefix)

 

To incorporate the new code in your existing override of product.php, just copy the getFrontFeaturesStatic() function after the existing getPoductsImgs() function.

The new file should be :


<?php
class Product extends ProductCore
{

public static function getProductsImgs($product_id)
	{
$sql = '
 (SELECT * from `'._DB_PREFIX_.'image`
 WHERE id_product="'.$product_id.'" and cover=1)
  union
	 (SELECT * from `'._DB_PREFIX_.'image`
 WHERE id_product="'.$product_id.'" and cover=0  ORDER BY `position` LIMIT 0,1 )

 LIMIT 0,2
 ';
			$result = Db::getInstance()->ExecuteS($sql);
return $result;
	}

public static function getFrontFeaturesStatic($id_lang, $id_product)
{
 $process = (!array_key_exists($id_product.'-'.$id_lang, parent::$_frontFeaturesCache));
 $features = parent::getFrontFeaturesStatic($id_lang, $id_product);

 //PWeb: join multiple values of one feature into one value
 if ($process AND count($features)) {
  $features_key = array();
  foreach ($features as $key => $feature) {
if (!array_key_exists($feature['name'], $features_key)) {
	 $features_key[$feature['name']] = $key;
} else {
	 $features[ (int)$features_key[$feature['name']] ]['value'] .= ', ' . $feature['value'] ;
	 unset($features[$key]);
}
  }
  parent::$_frontFeaturesCache[$id_product.'-'.$id_lang] = $features;
 }

 return $features;
}

}

  • Like 1

Share this post


Link to post
Share on other sites

Hi Cari,

 

If you cannot save more than one feature value, this is not due to product.php.

Most probably you did not modify the database table to allow multiple value

 

You have to run this command on your database using phpmyadmin :

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

(assuming "ps" is your table prefix, otherwise replace ps_ with your prefix)

 

I see... i assumed that i didn't need to alter the database as i'm using the 1.53 modification by pweb, i know the first modification post said to change the database but i assumed you didn't need to do it with the 1.53 version as there was no mention of it...

 

I really appreciate your response, you're an angel! :rolleyes: Thank you for the code also, it didn't cause any errors :)

 

NB. What delimiter should i use when running the command? The default is semicolon, is this correct? Also it says "

Show this query here again"

with a check-mark next to it. I'm not sure what this means, should i leave it checked/ticked?

Thanks!

Edited by Cari (see edit history)

Share this post


Link to post
Share on other sites

Don't worry about delimiter, you can keep semicolon and run the command as is, it should do the trick

you can also keep the "Show this query here again" checked, no matter.

 

Depending on your phpmyadmin version, you could have no response displayed after running the command.

so after, just try to save multiple values for a product to see if it worked

  • Like 1

Share this post


Link to post
Share on other sites

My features didn't save for product... :(

I'm check feures, but after i click 'Save' it is not saving changes....

I have run coomand in phphMyadmin:

 

ALTER TABLE ps_feature_product DROP PRIMARY KEY, ADD PRIMARY KEY (id_feature, id_product, id_feature_value)

but nothing change....

Share this post


Link to post
Share on other sites

Hi Kotkotan

I'm not an expert but are you do you only have one prestashop installation in your backend? I ask this because i have multiple domains in my hosting account and have more than one shop. Also, with my account, if you install then uninstall prestashop, the database remains and you have to manually delete it. Maybe you are using the wrong database?

 

If not that then have you made sure your prestashop database "ps_feature_product" begins with 'ps'? My old one from last year begins with 'ps', more recent ones say 'evw' and 'fmz' e.g. fmz_feature_product. Make sure you change the 'ps' if you haven't. If it's not these things, then i have no idea and perhaps Mellow will reply...

Good luck!

Edited by Cari (see edit history)

Share this post


Link to post
Share on other sites