Jump to content
thirty bees forum

products with multiple features


zimmer-media

Recommended Posts

There is still uncertain, if this function will eventually be installed in the core, here's the guide from the PS forum, for those who can not wait or do not know yet.

Step 1 go to your database in prefixfeatureproduct all 3 entrys with primary key

from this 0_1514327207678_586559fc-475a-4dd3-be40-02e80355a783-grafik.png


to this 0_1514327227032_19e20564-00cb-48ea-a683-2231d53e5712-grafik.png

step 2

create "Product.php" at folder /override/classes/ ``` <?php /** * Modification Name: Multiple features for Prestashop * Description: Allows the user to select multiple features for a product * Version: 1.6 * Author: Mellow http://www.prestashop.com/forums/user/344943-mellow * Adaptation to Prestashop 1.5.6: David Bucur http://www.tricksfordevelopers.com * Prestashop 1.6 version: Josef Gullstr�m http://www.prestashop.com/forums/user/597992-jgullstr * License: GPL2 */ class Product extends ProductCore { public static function getFrontFeaturesStatic($id_lang, $id_product) { if (!Feature::isFeatureActive()) return array(); if (!array_key_exists($id_product.'-'.$id_lang, self::$_frontFeaturesCache)) { // Display multi-valued features as comma-separated values in product // data sheet. self::$_frontFeaturesCache[$id_product.'-'.$id_lang] = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT name, GROUP_CONCAT(value SEPARATOR \', \') AS value, pf.id_feature FROM '._DB_PREFIX_.'feature_product pf LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.id_feature_value = pf.id_feature_value AND fvl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature f ON (f.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') '.Shop::addSqlAssociation('feature', 'f').' WHERE pf.id_product = '.(int)$id_product.' GROUP BY pf.id_feature ORDER BY f.position ASC' ); } return self::$_frontFeaturesCache[$id_product.'-'.$id_lang]; }

public function addFeaturesToDB($idfeature, $idvalue, $cust = 0) { // Default behavior. if ($cust || !isarray($idvalue)) { return parent::addFeaturesToDB($idfeature, $idvalue, $cust); }

// For multi-value features, build array of rows and insert into db.
$base =  array(
  'id_feature' => (int)$id_feature,
  'id_product' => (int)$this->id,
);
$rows = array();
foreach ($id_value as $value) {
  if(!empty($value)) {
    $rows[] = $base + array('id_feature_value' => $value);
  }
}
if(!empty($rows)) {
  Db::getInstance()->insert('feature_product', $rows);
}

// From parent.
SpecificPriceRule::applyAllRules(array((int)$this->id));
    if ($id_value) {
        return ($id_value);
}
}

} ```

Step 3 create "AdminProductsController.php" at folder /override/controllers/admin/

``` <?php /** * Modification Name: Multiple features for Prestashop * Description: Allows the user to select multiple features for a product * Version: 1.6 * Author: Mellow http://www.prestashop.com/forums/user/344943-mellow * Adaptation to Prestashop 1.5.6: David Bucur http://www.tricksfordevelopers.com * Prestashop 1.6 version: Josef Gullstr�m http://www.prestashop.com/forums/user/597992-jgullstr * License: GPL2 */ class AdminProductsController extends AdminProductsControllerCore { public function initFormFeatures($obj) {

if (!$this->default_form_language)
  $this->getLanguages();

$data = $this->createTemplate($this->tpl_form);
    $data->assign('default_form_language', $this->default_form_language);

if (!Feature::isFeatureActive())
  $this->displayWarning($this->l('This feature has been disabled. ').' <a href="index.php?tab=AdminPerformance&token='.Tools::getAdminTokenLite('AdminPerformance').'#featuresDetachables">'.$this->l('Performances').'</a>');
else
{
  if ($obj->id)
  {
    if ($this->product_exists_in_shop)
    {
      $features = Feature::getFeatures($this->context->language->id, (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP));

      // Mellow modification.
      foreach ($features as $k => $tab_features)
      {
        $features[$k]['current_item'] = false;
        $features[$k]['val'] = array();

        $features[$k]['custom'] = true;
        foreach ($obj->getFeatures() as $tab_products) {
          if ($tab_products['id_feature'] == $tab_features['id_feature'])
            $features[$k]['current_item'][] = $tab_products['id_feature_value'];
        }

        if (!$features[$k]['current_item']) {
          $features[$k]['current_item'][0] = null;
        }

        $features[$k]['featureValues'] = FeatureValue::getFeatureValuesWithLang($this->context->language->id, (int)$tab_features['id_feature']);
        if (count($features[$k]['featureValues'])) {
          foreach ($features[$k]['featureValues'] as $value) {
            if (in_array($value['id_feature_value'], $features[$k]['current_item'])) {
              $features[$k]['custom'] = false;
            }
          }
        }
        if ($features[$k]['custom']) {
          $features[$k]['val'] = FeatureValue::getFeatureValueLang($features[$k]['current_item'][0]);
        }
      }
      // EOF Mellow modification.
      $data->assign('available_features', $features);

      $data->assign('product', $obj);
      $data->assign('link', $this->context->link);
      $data->assign('languages', $this->_languages);
      $data->assign('default_form_language', $this->default_form_language);
    }
    else
      $this->displayWarning($this->l('You must save the product in this shop before adding features.'));
  }
  else
    $this->displayWarning($this->l('You must save this product before adding features.'));
}
$this->tpl_form_vars['custom_form'] = $data->fetch();

}

public function processFeatures() { if (!Feature::isFeatureActive()) return;

if (Validate::isLoadedObject($product = new Product((int)Tools::getValue('id_product'))))
{
  // delete all objects
  $product->deleteFeatures();

  // add new objects
  $languages = Language::getLanguages(false);
  foreach ($_POST as $key => $val)
  {
    if (preg_match('/^feature_([0-9]+)_value/i', $key, $match))
    {
      //  "&& $val[0] != 0" added by override.
      if ($val && $val[0] != 0) {
        $product->addFeaturesToDB($match[1], $val);
      }
      else {
        if ($default_value = $this->checkFeatures($languages, $match[1]))
        {
          $id_value = $product->addFeaturesToDB($match[1], 0, 1);
          foreach ($languages as $language)
          {
            if ($cust = Tools::getValue('custom_'.$match[1].'_'.(int)$language['id_lang']))
              $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $cust);
            else
              $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $default_value);
          }
        }
      }
    }
  }
}
else
  $this->errors[] = Tools::displayError('A product must be created before adding features.');

} }

**Step 4** create "features.tpl" at folder /override/controllers/admin/templates/products/ {* * 2007-2014 PrestaShop * * NOTICE OF LICENSE * * This source file is subject to the Academic Free License (AFL 3.0) * that is bundled with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://opensource.org/licenses/afl-3.0.php * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@prestashop.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to http://www.prestashop.com for more information. * * @author PrestaShop SA contact@prestashop.com * @author Josef Gullstr�m http://www.prestashop.com/forums/user/597992-jgullstr * @copyright 2007-2014 PrestaShop SA * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * International Registered Trademark & Property of PrestaShop SA *}

{if isset($product->id)}

{l s='Assign features to this product'}

{l s='You can specify a value for each relevant feature regarding this product. Empty fields will not be displayed.'}
{l s='You can either create a specific value, or select among the existing pre-defined values you\'ve previously added.'}
{foreach from=$available_features item=available_feature} {foreachelse} {/foreach}
{l s='Feature'} {l s='Pre-defined value'} {l s='or'} {l s='Customized value'}
{$available_feature.name} {* Changed for multiple-value support *} {if sizeof($available_feature.featureValues)} {else} {* /Changed for multiple-value support *} {l s='N/A'} - {l s='Add pre-defined values first'} {/if} {foreach from=$languages key=k item=language} {if $languages|count > 1}
{/if} {if $languages|count > 1}
{/if} {/foreach}
{l s='No features have been defined'}
{l s='Add a new feature'}

{/if}

{/literal} ```

product backoffice 0_1514328929917_09338a37-a5a6-4716-8f6b-074851d6a4a9-grafik.png

product frontoffice 0_1514328976394_0f4deb5f-db50-4f95-8bc4-cfa8454784d3-grafik.png

if you use blocklayered - your customer have more option when you change the features option in the modul 0_1514329074331_8d813be5-90e3-4d05-b5be-d66a8e983a70-grafik.png

Link to comment
Share on other sites

  • 8 months later...
  • 2 weeks later...

Hello.

I'm new in Prestashop, got my page done few days ago. I'm looking for the option mentioned in this topic. I have electronic equipment and my goal is to be able to assign multiple values of the same feature to one device (e.g. a device can have 24Vdc or 230Vac power supply version) so the customers can filter it correctly. I do not care about printing this features on product front page. All I want to do is

I went through the whole Internet and the only useful information I can see here and here: https://www.prestashop.com/forums/topic/176242-modification-select-multiple-values-for-one-feature/ .

I'm working on Prestashop 1.7.2.1 and I'm too scared to update to newest 1.7.4.2 :) Yes, I've heard that multi features option is available since 1.7.3 but for sure it can be also done by modifying core files in 1.7.2

What I've done so far: 1) Step 1 of this instruction. SQL database accepts multiple idfeaturevalue for the same idfeature. I can manually add suitable records to SQL psfeature_products and it is working properly on the website, filtering etc. . Even when I open product editing page, Prestashop loads all the features from the DB. The problem is that when I want to change something in the product, only the last feature is saved (Prestashop overrides SQL database) - I want to change this.

2) From what I understand the whole thing is about modifying processFeatures() funtion in AdminProductsController.php and maybe addFeaturesToDB() function in Product.php.

The approach is to gather feature values in processFeatures() function and pass it to addFeaturesToDB() function as an array. Then in addFeaturesToDB() function add to the array idfeature, idproduct and write it to DB.

AdminProductsController.php: ``` public function processFeatures($id_product = null) { if (!Feature::isFeatureActive()) { return; }

    $id_product = (int) $id_product ? $id_product : (int)Tools::getValue('id_product');

    if (Validate::isLoadedObject($product = new Product($id_product))) {
        // delete all objects
        $product->deleteFeatures();

        // add new objects
        $languages = Language::getLanguages(false);
        foreach ($_POST as $key => $val) {
            if (preg_match('/^feature_([0-9]+)_value/i', $key, $match)) {
                if ($val && $val[0] != 0){
                    foreach ($val as $feature_val) $product->addFeaturesToDB($match[1], $feature_val);
                } else {
                    if ($default_value = $this->checkFeatures($languages, $match[1])) {
                        $id_value = $product->addFeaturesToDB($match[1], 0, 1);
                        foreach ($languages as $language) {
                            if ($cust = Tools::getValue('custom_'.$match[1].'_'.(int)$language['id_lang'])) {
                                $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $cust);
                            } else {
                                $product->addFeaturesCustomToDB($id_value, (int)$language['id_lang'], $default_value);
                            }
                        }
                    }
                }
            }
        }
    } else {
        $this->errors[] = $this->trans('A product must be created before adding features.', array(), 'Admin.Catalog.Notification');
    }
}

This suppose to get all the features values into array val and pass it to addFeaturesToDB(). I have also tried the way it is shown in this post so without "foreach ($val as $feature_val) $product->addFeaturesToDB($match[1], $feature_val);" but only "$product->addFeaturesToDB($match[1], $val);" in this place. Then we have: addFeaturesToDB(): public function addFeaturesToDB($idfeature, $idvalue, $cust = 0) { // Default behavior. if ($cust) { $row = array('idfeature' => (int)$idfeature, 'custom' => 1); Db::getInstance()->insert('featurevalue', $row); $idvalue = Db::getInstance()->Insert_ID(); }

// For multi-value features, build array of rows and insert into db.
$base =  array(
  'id_feature' => (int)$id_feature,
  'id_product' => (int)$this->id,
);
$rows = array();
foreach ($id_value as $value) {
  if(!empty($value)) {
    $rows[] = $base + array('id_feature_value' => $value);
  }
}
$row = array('id_feature' => (int)$id_feature, 'id_product' => (int)$this->id, 'id_feature_value' => (int)$id_value);
    Db::getInstance()->insert('feature_product', $row);
    SpecificPriceRule::applyAllRules(array((int)$this->id));
    if ($id_value)
        return ($id_value);
}

``` I build an array with idfeature and idproduct and add id_value array which is val from processFeatures() function.

But it does not work.

Can you help me, please? Maybe since Prestashop 1.7.4 is released someone can look up how they are solving this issue?

Best regards, Jacek

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...