Jump to content

Créer Champ Produit Presta 1.5 - Override Classe Product.php et AdminProducts.php


Recommended Posts

Bonjour à tous et merci pour l'aide que vous pourrez m'apporter,

 

Mon problème est le suivant : j'ai besoin pour le développement de ma boutique d'être capable d'ajouter de nouveaux champs sur les fiches produits. Ces champs doivent être éditables dans l'admin sur les fiches produits. La structure de la version 1.5 étant différente de la 1.4 il faut tout réapprendre...

 

J'aimerais notamment créer une variable booléenne "devis". Lorsque cette variable sera à 1 au lieu d'afficher "Ajouter au panier" sur la fiche Produit en Front-Office il sera affiché "Demander un devis". Les débouchés de la méthode sont grands et un tutoriel serait utile pour tous.

 

Ajout du champ à la table ps_product

 

Dans un premier temps j'ajoute à la fin de la table ps_product de la BDD Prestashop un champ "devis".

 

Override de la classe "Product.php"

 

J'ouvre "override/classes/Product.php" et je déclare la nouvelle variable et modifie la définition en fonction.

 

class Product extends ProductCore
{
public $devis = false;
public static $definition = array(
 'table' => 'product',
 'primary' => 'id_product',
 'multilang' => true,
 'multilang_shop' => true,
 'multishop' => true,
 'fields' => array(
  // Classic fields
  [...]
  /*Custom Fields */
  'devis' =>	   array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
);
}

 

Override du controller "AdminProducts.php"

 

Devant la longueur du fichier je ne parviens pas du tout à voir quoi modifier, même en essayant de prendre exemple sur des champs existant... J'espère que quelqu'un peut vraiment m'expliquer comment procéder.

 

 

Un grand merci à ceux qui pourront m'aider à débloquer la situation et ainsi permettre à tous les utilisateurs de la version 1.5 d'avancer dans le développement de leur site :)

 

Bonne journée à tous !

Link to comment
Share on other sites

  • 2 weeks later...

Encore un up...

C'est quand même basique, alors si personne ne sait faire, et vu qu'il n'y a pas de doc digne de ce nom, c'est pas gagné ^^

Je donne quand même mon avancé, mais il y a une erreur au moment d'enregistrer : "Une erreur s'est produite pendant la mise à jour de l'objet. product ()"

 

alors : override\classes\Product.php :

 

<?php
class Product extends ProductCore
{
/** @var boolean enable_cross_categories */
public $enable_cross_categories = false;

public static $definition = array(
 'table' => 'product',
 'primary' => 'id_product',
 'multilang' => true,
 'multilang_shop' => true,
 'fields' => array(
  // Classic fields
  'id_shop_default' =>    array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
  'id_manufacturer' =>    array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
  'id_supplier' =>	 array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
  'reference' =>	  array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32),
  'supplier_reference' =>   array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 32),
  'location' =>	  array('type' => self::TYPE_STRING, 'validate' => 'isReference', 'size' => 64),
  'width' =>	   array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'),
  'height' =>	  array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'),
  'depth' =>	   array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'),
  'weight' =>	  array('type' => self::TYPE_FLOAT, 'validate' => 'isUnsignedFloat'),
  'quantity_discount' =>    array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
  'ean13' =>	   array('type' => self::TYPE_STRING, 'validate' => 'isEan13', 'size' => 13),
  'upc' =>	   array('type' => self::TYPE_STRING, 'validate' => 'isUpc', 'size' => 12),
  'cache_is_pack' =>	 array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
  'cache_has_attachments' =>   array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
  'is_virtual' =>	 array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
  /* Shop fields */
  'id_category_default' =>   array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'),
  'id_tax_rules_group' =>   array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedId'),
  'on_sale' =>	  array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'online_only' =>	 array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'ecotax' =>	  array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'),
  'minimal_quantity' =>    array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
  'price' =>	   array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice', 'required' => true),
  'wholesale_price' =>    array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'),
  'unity' =>	   array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isString'),
  'unit_price_ratio' =>    array('type' => self::TYPE_FLOAT, 'shop' => true),
  'additional_shipping_cost' =>  array('type' => self::TYPE_FLOAT, 'shop' => true, 'validate' => 'isPrice'),
  'customizable' =>	 array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
  'text_fields' =>	 array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
  'uploadable_files' =>    array('type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'),
  'active' =>	  array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'available_for_order' =>   array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'available_date' =>    array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'),
  'condition' =>	  array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isGenericName', 'values' => array('new', 'used', 'refurbished'), 'default' => 'new'),
  'show_price' =>	 array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'indexed' =>	  array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'visibility' =>	 array('type' => self::TYPE_STRING, 'shop' => true, 'validate' => 'isProductVisibility', 'values' => array('both', 'catalog', 'search', 'none'), 'default' => 'both'),
  'cache_default_attribute' =>  array('type' => self::TYPE_INT, 'shop' => true),
  'advanced_stock_management' =>  array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  'date_add' =>	  array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'),
  'date_upd' =>	  array('type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDateFormat'),

  /* custom fields */
  'enable_cross_categories' =>  array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
  /* Lang fields */
  'meta_description' =>    array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
  'meta_keywords' =>	 array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
  'meta_title' =>	 array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128),
  'link_rewrite' =>	 array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128),
  'name' =>	   array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isCatalogName', 'required' => true, 'size' => 128),
  'description' =>	 array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString'),
  'description_short' =>    array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString'),
  'available_now' =>	 array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
  'available_later' =>    array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'IsGenericName', 'size' => 255),

 ),
 'associations' => array(
  'manufacturer' =>	 array('type' => self::HAS_ONE),
  'supplier' =>	  array('type' => self::HAS_ONE),
  'default_category' =>    array('type' => self::HAS_ONE, 'field' => 'id_category_default', 'object' => 'Category'),
  'tax_rules_group' =>    array('type' => self::HAS_ONE),
  'categories' =>	 array('type' => self::HAS_MANY, 'field' => 'id_category', 'object' => 'Category', 'association' => 'category_product'),
 ),
);

}

 

override/controllers/admin/AdminProductsController.php :

 

<?php
class AdminProductsController extends AdminProductsControllerCore
{
/**
 * renderForm contains all necessary initialization needed for all tabs
 *
 * @return void
 */
public function renderForm()
{
 // This nice code (irony) is here to store the product name, because the row after will erase product name in multishop context
 $this->product_name = $this->object->name[$this->context->language->id];
 if (!method_exists($this, 'initForm'.$this->tab_display))
  return;
 $product = $this->object;
 $this->product_exists_in_shop = true;
 if ($this->display == 'edit' && Validate::isLoadedObject($product) && Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP && !$product->isAssociatedToShop($this->context->shop->id))
 {
  $this->product_exists_in_shop = false;
  if ($this->tab_display == 'Informations')
   $this->displayWarning($this->l('Warning: this product does not exist in this shop.'));

  $default_product = new Product();
  $fields_to_copy = array('minimal_quantity',
	   'price',
	   'additional_shipping_cost',
	   'wholesale_price',
	   'on_sale',
	   'online_only',
	   'unity',
	   'unit_price_ratio',
	   'ecotax',
	   'active',
	   'available_for_order',
	   'available_date',
	   'show_price',
	   'indexed',
	   'id_tax_rules_group',
	   'advanced_stock_management',
	   'enable_cross_categories');
  foreach ($fields_to_copy as $field)
   $product->$field = $default_product->$field;
 }
 // Product for multishop
 $this->context->smarty->assign('bullet_common_field', '');
 if (Shop::isFeatureActive() && $this->display == 'edit')
 {
  if (Shop::getContext() != Shop::CONTEXT_SHOP)
  {
   $this->context->smarty->assign(array(
 'display_multishop_checkboxes' => true,
 'multishop_check' => Tools::getValue('multishop_check'),
   ));
  }
  if (Shop::getContext() != Shop::CONTEXT_ALL)
  {
   $this->context->smarty->assign('bullet_common_field', '<img src="themes/'.$this->context->employee->bo_theme.'/img/bullet_orange.png" style="vertical-align: bottom" />');
   $this->context->smarty->assign('display_common_field', true);
  }
 }
 $this->tpl_form_vars['tabs_preloaded'] = $this->available_tabs;
 $this->tpl_form_vars['product_type'] = (int)Tools::getValue('type_product', $product->getType());
 $this->getLanguages();
 $this->tpl_form_vars['id_lang_default'] = Configuration::get('PS_LANG_DEFAULT');
 $this->tpl_form_vars['currentIndex'] = self::$currentIndex;
 $this->tpl_form_vars['display_multishop_checkboxes'] = (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP && $this->display == 'edit');
 $this->fields_form = array('');
 $this->display = 'edit';
 $this->tpl_form_vars['token'] = $this->token;
 $this->tpl_form_vars['combinationImagesJs'] = $this->getCombinationImagesJs();
 $this->tpl_form_vars['post_data'] = Tools::jsonEncode($_POST);
 $this->tpl_form_vars['save_error'] = !empty($this->errors);
 // autoload rich text editor (tiny mce)
 $this->tpl_form_vars['tinymce'] = true;
 $iso = $this->context->language->iso_code;
 $this->tpl_form_vars['iso'] = file_exists(_PS_ROOT_DIR_.'/js/tiny_mce/langs/'.$iso.'.js') ? $iso : 'en';
 $this->tpl_form_vars['ad'] = dirname($_SERVER['PHP_SELF']);
 if (Validate::isLoadedObject(($this->object)))
  $id_product = (int)$this->object->id;
 else
  $id_product = (int)Tools::getvalue('id_product');
 $this->tpl_form_vars['form_action'] = $this->context->link->getAdminLink('AdminProducts').'&'.($id_product ? 'id_product='.(int)$id_product : 'addproduct');
 $this->tpl_form_vars['id_product'] = $id_product;
 // Transform configuration option 'upload_max_filesize' in octets
 $upload_max_filesize = Tools::getOctets(ini_get('upload_max_filesize'));
 // Transform configuration option 'upload_max_filesize' in MegaOctets
 $upload_max_filesize = ($upload_max_filesize / 1024) / 1024;
 $this->tpl_form_vars['upload_max_filesize'] = $upload_max_filesize;
 $this->tpl_form_vars['country_display_tax_label'] = $this->context->country->display_tax_label;
 $this->tpl_form_vars['has_combinations'] = $this->object->hasAttributes();
 // let's calculate this once for all
 if (!Validate::isLoadedObject($this->object) && Tools::getValue('id_product'))
  $this->errors[] = 'Unable to load object';
 else
 {
  $this->_displayDraftWarning($this->object->active);
  // if there was an error while saving, we don't want to lose posted data
  if (!empty($this->errors))
   $this->copyFromPost($this->object, $this->table);
  $this->initPack($this->object);
  $this->{'initForm'.$this->tab_display}($this->object);
  $this->tpl_form_vars['product'] = $this->object;
  if ($this->ajax)
   if (!isset($this->tpl_form_vars['custom_form']))
 throw new PrestaShopException('custom_form empty for action '.$this->tab_display);
   else
 return $this->tpl_form_vars['custom_form'];
 }
 $parent = parent::renderForm();
 $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch'));
 return $parent;
}

public function initFormInformations($product)
{
 $data = $this->createTemplate($this->tpl_form);
 $currency = $this->context->currency;
 $data->assign('languages', $this->_languages);
 $data->assign('currency', $currency);
 $this->object = $product;
 $this->display = 'edit';
 $this->_applyTaxToEcotax($product);
 /*
 * Form for adding a virtual product like software, mp3, etc...
 */
 $product_download = new ProductDownload();
 if ($id_product_download = $product_download->getIdFromIdProduct($this->getFieldValue($product, 'id')))
  $product_download = new ProductDownload($id_product_download);
 $product->{'productDownload'} = $product_download;
 $cache_default_attribute = (int)$this->getFieldValue($product, 'cache_default_attribute');
 $product_props = array();
 // global informations
 array_push($product_props, 'reference', 'ean13', 'upc',
 'available_for_order', 'show_price', 'online_only',
 'id_manufacturer', 'enable_cross_categories'
 );
 // specific / detailled information
 array_push($product_props,
 // physical product
 'width', 'height', 'weight', 'active',
 // virtual product
 'is_virtual', 'cache_default_attribute',
 // customization
 'uploadable_files', 'text_fields'
 );
 // prices
 array_push($product_props,
  'price', 'wholesale_price', 'id_tax_rules_group', 'unit_price_ratio', 'on_sale',
  'unity', 'minimum_quantity', 'additional_shipping_cost',
  'available_now', 'available_later', 'available_date'
 );
 if (Configuration::get('PS_USE_ECOTAX'))
  array_push($product_props, 'ecotax');
 foreach ($product_props as $prop)
  $product->$prop = $this->getFieldValue($product, $prop);
 $product->name['class'] = 'updateCurrentText';
 if (!$product->id)
  $product->name['class'] .= ' copy2friendlyUrl';
 $images = Image::getImages($this->context->language->id, $product->id);
 foreach ($images as $k => $image)
  $images[$k]['src'] = $this->context->link->getImageLink($product->link_rewrite[$this->context->language->id], $product->id.'-'.$image['id_image'], 'small_default');
 $data->assign('images', $images);
 $data->assign('imagesTypes', ImageType::getImagesTypes('products'));
 $product->tags = Tag::getProductTags($product->id);
 $data->assign('product_type', (int)Tools::getValue('type_product', $product->getType()));
 $check_product_association_ajax = false;
 if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL)
  $check_product_association_ajax = true;
 // TinyMCE
 $iso_tiny_mce = $this->context->language->iso_code;
 $iso_tiny_mce = (file_exists(_PS_JS_DIR_.'tiny_mce/langs/'.$iso_tiny_mce.'.js') ? $iso_tiny_mce : 'en');
 $data->assign('ad', dirname($_SERVER['PHP_SELF']));
 $data->assign('iso_tiny_mce', $iso_tiny_mce);
 $data->assign('check_product_association_ajax', $check_product_association_ajax);
 $data->assign('id_lang', $this->context->language->id);
 $data->assign('product', $product);
 $data->assign('token', $this->token);
 $data->assign('currency', $currency);
 $data->assign($this->tpl_form_vars);
 $data->assign('link', $this->context->link);
 $data->assign('PS_PRODUCT_SHORT_DESC_LIMIT', Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT') ? Configuration::get('PS_PRODUCT_SHORT_DESC_LIMIT') : 400);
 $this->tpl_form_vars['product'] = $product;
 $this->tpl_form_vars['custom_form'] = $data->fetch();
}
}

 

et override/controllers/admin/templates/products/informations.tpl (aller là je ne met pas tout ^^) :

<td class="col-left"><label>{$bullet_common_field} {l s='Enable cross categories:'}</label></td>
  <td style="padding-bottom:5px;">
   <input type="checkbox" name="enable_cross_categories" id="enable_cross_categories" value="1" {if $product->enable_cross_categories}checked="checked"{/if} />
  </td>

 

Bref, je cherche à rajouter une case à cocher dans l'onglet informations. Met ça bug quand il s'agit d'enregistrer...

Alors, des idées ? :)

Link to comment
Share on other sites

J'ai réussi à résoudre le problème concernant le message : "Une erreur s'est produite pendant la mise à jour de l'objet. product ()"

 

Il s'agit d'ajouter le champ personnalisé à la toute fin de la définition de l'objet "Produit", et d'ajouter aussi le champ à la toute fin de la table "ps_product".

 

public static $definition = array(
 'table' => 'product',
 'primary' => 'id_product',
 'multilang' => true,
 'multilang_shop' => true,
 'fields' => array(
  // Classic fields
  'id_shop_default' =>	array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
  [...]
 'associations' => array(
  'manufacturer' =>	 array('type' => self::HAS_ONE),
 [...]
  'stock_availables' =>   array('type' => self::HAS_MANY, 'field' => 'id_stock_available', 'object' => 'StockAvailable', 'association' => 'stock_availables'),
 ),
 /* Custom fields */
  'devis_only' =>	 array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'),
);

 

Cela dit j'ai toujours une erreur. Le champ s'affiche bien dans la fiche produit, est bien ajouté à la définition d'un produit (test d'affichage dans un template en front office OK), mais la sauvegarde de celui-ci ne s'opère pas du tout lorsque je sauvegarde un produit...

 

Par exemple pour une checkbox si je la check et sauvegarde le produit, lorsque je retourne sur la fiche produit la checkbox est désactivée. Cela doit provenir d'un problème au niveau d'AdminProductsController.php Pourtant j'ai suivi exactement le modèle de champs existants. Je vais essayer avec des champs de plusieurs types voir si ça ne vient que des booléens et je vous tiens au courant.

 

Merci, s'il y en a qui y sont parvenus, d'apporter leur aide :)

  • Like 1
Link to comment
Share on other sites

Merci Splash_info pour la suppression de l'erreur !

Je ne trouve pas pour ce qui est du problème d'enregistrement. J'ai contacté Prestashop mais ils ne répondent pas..

Je continue de chercher. D'autres personnes sont les bienvenues :D

Link to comment
Share on other sites

Petite avancée :

J'ai réussi à enregistrer l'état d'une checkbox.

 

pour Product.php, le champ doit être mit dans Fields :

 

 

class Product extends ProductCore{public $enable_cross_categories = false;public static $definition = array( 'table' => 'product', 'primary' => 'id_product', 'multilang' => true, 'multilang_shop' => true, 'fields' => array(  // Classic fields  'available_later' =>	array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'IsGenericName', 'size' => 255),//custom field  'enable_cross_categories' =>  array('type' => self::TYPE_BOOL, 'shop' => true, 'validate' => 'isBool'), ),);}

 

 

pour AdminProductsController.php : (j'ai remplacé les "parent :: " par "AdminControllerCore::")

Ajouter pour chaque fonction le code pour votre variable en copiant la logique de "available_for_order"

 

- protected function copyFromPost(&$object, $table)

- public function renderForm()

- public function initFormInformations($product)

 

Et la case à cocher sera bien enregistrée...mais avec le message d'erreur "Une erreur s'est produite pendant la mise à jour de l'objet. product ()"

 

Voilà...J'attends vos réactions ;)

 

EDIT : en fait du coup les autres champs (genre available_for_order ne s'enregistrent plus. Je vais me pendre et je reviens.)

Edited by Zulian (see edit history)
Link to comment
Share on other sites

Bon, j'ai trouvé ! Je met donc un petit tuto ici, les admins me diront si il y a un meilleur endroit pour ça...

 

TUTO : Ajout d'une checkbox dans l'onglet 'Information' de Product

 

1. Dans "\override\classes\Product.php" :

 

class Product extends ProductCore
{
public $my_checkbox = false;
public static $definition = array(
 'table' => 'product',
 'primary' => 'id_product',
 'multilang' => true,
 'multilang_shop' => true,
 'fields' => array(
  // Classic fields
  'id_shop_default' =>	array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
  // ...
  'is_virtual' =>	 array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),

/* My custom field */
  'my_checkbox' =>  array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),

/* Shop fields */
 // ...

);

}

 

2. Dans "\override\controllers\admin\AdminProductsController.php" :

Copier les fonctions :

- protected function copyFromPost(&$object, $table)

- public function renderForm()

- public function initFormInformations($product)

 

En y ajoutant le code pour "my_checkbox" sur le modèle de "available_for_order".

 

3. Dans "\override\controllers\admin\templates\products\informations.tpl"

 

Incorporer ligne 142 :

<tr>
  <td class="col-left"><label>{$bullet_common_field} {l s='My checkbox :'}</label></td>
  <td style="padding-bottom:5px;">
<input type="checkbox" name="my_checkbox" id="my_checkbox" value="1" {if $product->my_checkbox}checked="checked"{/if} />
  </td>
 </tr>

 

4. Ajouter dans la table `ps_product`,

my_checkbox type : tinyint(1), null : non, défaut : 0

 

Et voilà, votre checkbox apparait bien, et l'enregistrement se passe sans problème :)

Edited by Zulian (see edit history)
  • Like 4
Link to comment
Share on other sites

Excellent tuto, merci ; des heures de gagnées.

 

J'ai juste un léger souci, sur prestashop 1.5.2, si j'override le tpl prices.tpl (j'ai besoin d'un champ prix supplémentaire sur la fiche produit), la traduction "saute" ; tout l'onglet Prix passe en Anglais :-(

 

Si je place l'information dans le fichier prices.tpl d'origine, aucun souci (juste la traduction des 2 nouveaux champs à mettre en oeuvre, mais ça c'est normal).

 

Si quelqu'un a une idée, je suis preneur (en attendant, je laisse l'écriture dans le fichier d'origine, mais ce n'est pas conventionnel...

Link to comment
Share on other sites

Je vous propose une solution plus pérenne, car si la variable $definition est modifiée au cours des mises à jour de prestashop vous devrez mettre à jour votre override. Avec la solution suivante pas besoin de modifier votre override meme si la variable $definition est modifiée :

 

override/classes/Product.php :

class Product extends ProductCore
{
public $new_variable;

public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
 Product::$definition['fields']['new_variable'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');
 parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
}

Edited by Paco112 (see edit history)
  • Like 1
Link to comment
Share on other sites

Bonjour, j'ai le même problème que Thierry Point2vente :

j'ai créé plusieurs champs et j'ai donc overridé le tpl shipping.tpl et informations.tpl.

L'enregistrement se passe nickel mais à l'affichage sur les 2 onglets informations et transport, tous les textes sont en anglais (champs natifs et nouveaux champs).

Thierry Point2Vente, as tu résolu le problème ?

 

PS : Pour déclarer le type de les champs, j'ai utilisé la solution Paco112 au lieu de modifier directement la variable $definition

 

Merci de votre aide...

Link to comment
Share on other sites

Sorry but I write in english because of my poor french...

 

I have solved the problem of writing the database. I have removed from Paco112 soution the word "Context" into the __construct function (see code below) and everything worked as expected.

 

 

class Product extends ProductCore

{

public $new_variable;

 

public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)

{

Product::$definition['fields']['new_variable'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');

parent::__construct($id_product, $full, $id_lang, $id_shop, $context);

}

}

 

 

Thank you again for your invaluable help.

 

Andrea

Edited by marioscrafts (see edit history)
Link to comment
Share on other sites

Bonjour à tous,

 

En partant de la solution du Zulian modifié par Paco112, tout fonctionne normalement pour moi.

 

En revanche, quelqu'un a-t-il essayé de remplir ce nouveau lors d'un import csv?

 

De mon coté j'ai fait plusieurs tentatives en overridant le fichier AdminImportController.php mais sans succès...

Le topic de Weetabix http://www.prestashop.com/forums/topic/182079-resolu-ajout-de-champs-import-produits/ donne la solution mais sur la 1.4, pas sur la 1.5.

 

Si quelqu'un a des pistes je suis preneur!

Merci d'avance pour votre aide,

 

Fred.

Marchand sur la 1.5

Link to comment
Share on other sites

Salut, pouvez-vous m'aidez s'il vous plaît ?

 

J'ai suivi votre tuto, et l'enregistrement lors d'un nouvel ajout de produit fonctionne bien;

mais lorsque je veux modifier la checkbox, la désactiver, la modification dans la base de donnée ne se fait pas !

 

Merci d'avance et merci pr tout

 

___________________________________________

 

 

c bon j'ai résolu le problème en ajoutant dans copyfrompost la récupération de la valeur :

 

$object->type_produits= (int)Tools::getValue('type_produits');

 

bon courage à tous

 

 

www.creation-com.fr

Edited by mbouajaj (see edit history)
Link to comment
Share on other sites

Très bon tuto Zulian,

 

Ca fonctionne nickel sur mon PS 1.5.2.

Je l'ai utilisé pour ajouter un champ "N° de page" qui mentionne sur quelle page apparaît le produit dans le catalogue "papier" de mon entreprise.

Excellente initiative, qui prouve qu'il y a quand même quelques membres actifs et altruistes dans la communauté Prestashop.

Link to comment
Share on other sites

Bon histoire de pousser le vice, je cherche à créer trois nouveaux champs texte.

L'un serait invisible et les deux autres visibles lorsque l'utilisateur est loggué. Et l'inverse, quand l'utilisateur n'est pas loggué, l'un visible et deux invisibles.

...Quelqu'un a une idée ?

Link to comment
Share on other sites

La solution suivante est possible mais pourquoi ne pas rendre visible ou non vos champs dans le controlleur ou meme le template ?

 

<?php
class Product extends ProductCore
{
public $var_nologin1;
public $var_login1;
public $var_login2;
public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
 if(!$context) $context = Context::getContext();

 if(!$context->customer->isLogged())
 {
  Product::$definition['fields']['var_nologin1'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');
 }
 else
 {
  Product::$definition['fields']['var_login1'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');
  Product::$definition['fields']['var_login2'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');
 }

 parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
}

Link to comment
Share on other sites

Bonjour,

 

Prestashop prévoit l'override de ces fichiers, mais comment anticiper une mise à jour BDD ?

 

Paco112 propose une solution pérenne des futurs fichiers quite à une mise à jour, mais qu'en est-il de la base de données?

Est-ce que la déclaration d'une nouvelle variable déclenche un champ dans la base de données? ou sommes nous obligé de modifier à la base de données à chaque mise à jour :/ ?

 

Quelqu'un à des éléments de réponse ? :)

Link to comment
Share on other sites

Bon histoire de pousser le vice, je cherche à créer trois nouveaux champs texte.

L'un serait invisible et les deux autres visibles lorsque l'utilisateur est loggué. Et l'inverse, quand l'utilisateur n'est pas loggué, l'un visible et deux invisibles.

...Quelqu'un a une idée ?

 

 

Je suis l'avis de Paco112, j'interviendrais directement sur le .tpl avec la conditions is_loggued()

Link to comment
Share on other sites

Bonjour à tous,

 

Tout d'abord merci à Zulian et Paco 112 pour leurs solutions.

J'ai cependant un petit soucis.

 

J'ai fait la mise à jour de mon Prestashop 1.4.8.2 vers la 1.5.2. J'avais rajouté un champ, j'ai donc naturellement voulu le recréer dans cette nouvelle version.

 

J'ai donc essayé de rajouter un textarea "points forts" mais la sauvegarde ne s'effectue pas.

Voici mon code :

 

Informations.tpl


<tr>
<td class="col-left">
{include file="controllers/products/multishop/checkbox.tpl" field="pointsforts" type="tinymce" multilang="true"}
<label>{l s='Points forts :'}<br /></label>
<p class="product_description">({l s='Points forts du produit'})</p>
</td>
<td style="padding-bottom:5px;">
{include file="controllers/products/textarea_lang.tpl"
languages=$languages
input_name='pointsforts'
input_value=$product->pointsforts}
<p class="clear"></p>
</td>
</tr>

 

 

Classe Product.php

class Product extends ProductCore
{
public $pointsforts;

public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
  Product::$definition['fields']['pointsforts'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');
  parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
}

 

 

AdminProductsController.php

Fonction copyFromPost :

$object->available_for_order = (int)Tools::getValue('available_for_order');
$object->pointsforts = Tools::getValue('pointsforts');
$object->show_price = $object->available_for_order ? 1 : (int)Tools::getValue('show_price');

 

Fonction renderForm :

$default_product = new Product();
  $fields_to_copy = array('minimal_quantity',
	   'price',
	   'additional_shipping_cost',
	   'wholesale_price',
	   'on_sale',
	   'online_only',
	   'unity',
	   'unit_price_ratio',
	   'ecotax',
	   'active',
	   'available_for_order',
	   'pointsforts',
	   'available_date',
	   'show_price',
	   'indexed',
	   'id_tax_rules_group',
	   'advanced_stock_management');
  foreach ($fields_to_copy as $field)
$product->$field = $default_product->$field;

 

Fonction initFormInformations :

$product_props = array();
 // global informations
 array_push($product_props, 'reference', 'ean13', 'upc',
 'available_for_order', 'pointsforts', 'show_price', 'online_only',
 'id_manufacturer'
 );

 

La valeur de mon champ est bien récupérée, mais lorsque je sauvegarde, elle est écrasée et devient vide.

J'ai l'impression que le champ est interprété comme un int au lieu d'un char.

Je précise enfin que mon champ 'pointsforts' est à la fin de la table product_lang et non product.

 

Quelqu'un saurait-il m'éclairer ?

Merci par avance,

Pauline.

Edited by Pauloscorps (see edit history)
Link to comment
Share on other sites

Bonjour à tous,

 

J'ai placé mon nouveau template admin dans le dossier overide bien comme il faut.

Seulement jai le meme probleme que certain avec la traduction.

Impossible de trouver pourquoi le texte apparait en anglais.

 

Quelqu'un à t-il une solution ?

 

pwb

++

Link to comment
Share on other sites

  • 3 weeks later...

Bonjour a tous,

 

J'ai aussi le problème de traduction de l'admin sur les overrides et j'ai contourné le problème, voici les explications.

 

Lorsque je créé mon dossier je créé mon fichier information.tpl dans override/controllers/admin/templates/products/

 

Celui ci est bien pris en compte dans la Localisation/Traductions dans un nouveau bloc en fin de pages appelé AdminAdmin sur mon site en production et AdminProgramme files en local ??

 

Hors je n'ai pas réussi à localisé ces informations ??? et j'en déduis que lors de la traduction ces informations ne sont pas récupérées pour remplacer les traductions par défaut.

 

Donc si la team pouvait au moins nous orienté sur le sujet on pourrait peut être trouvé le bug et le corrigé

 

J'ai donc fait mes modifs tout simplement au niveau du thème par défaut pour les essais et là la traduction marche très bien. Je vais à présent voir s'il on peut créer un autre thème afin de conserver les fichiers originaux en attendant d'avoir une solution plus propre avec les overrides de l'admin.

 

La question que je me pose à présent : Pourquoi utiliser l'override pour les fichiers template du back office puisqu'ils sont gérés sous la forme de thème comme le front ?

 

Je vais creuser de ce côté et mettrai mes conclusions en ligne.

 

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

 

Conclusion :

 

J'ai créé un nouveau thème Admin, j'ai modifié mes templates.

J'ai affecté le thème à tous les employés administrateur du site et rajouté les traductions.

Tout est ok et je pourrais donc récupérer mon thème pour la prochaine mise à jour (enfin ça c'est une autre histoire...)

Edited by latelier-sl (see edit history)
Link to comment
Share on other sites

Bonjour a tous, je vous remercie pour ce beau tuto !

j'ai essayé de l'appliquer en ajoutant quelques input ( int ) a la page information, j'ai suivie tte les etapes cité en haut mais j'ai la fameuse phrase : Une erreur s'est produite pendant la mise à jour de l'objet. product ()

 

Les nouveaux champs prennent bien la valeur 0 mais je n'arrive pas a faire enregistrer une nouvelle valeur, et pourtant j'ai bien modifier les deux fichiers ( product.php et AdminProductsController.php et ajouter les champs dans la table :s)

 

Si quelqu'un peut m'aider ou bien me guider sur ou peut etre l'erreur ca serai magnifique !

Merci a vous

Edited by ddlink (see edit history)
Link to comment
Share on other sites

Bonjour,

 

Merci pour cette avancée.

 

Dans mon cas, j'ai ajouté une checkbox "store_only" comme il existe "online_only".

 

J'ai suivi exactement les étapes de Zulian. Par contre, j'ai toujours le message d'erreur suivant : "Une erreur s'est produite pendant la mise à jour de l'objet. product ()".

- j'ai une version toute fraîche 1.5.2

- toutes mes données s'enregistrent correctement (vous allez me dire, bah c'est bon alors :) .... bah non, avec le message d'erreur ça ne le fait pas ! ).

- et toutes mes traductions sautent et j'ai du UK (donc je n'override pas le tpl pour le moment...)

 

Une idée, une piste, une suggestion pour comprendre d'où vient ce message et le supprimer ?

 

J'ai déjà essayé :

- avec la solutoin "public static $definition" et "public function __construct" dans override/classes/Products

- de mettre le champ "store_only" en début, en fin, au mileu de la table et aussi dans l'ordre de déclaration du array.

 

Mais rien n'y fait :(

 

Merci d'avance pour vos lumières :)

 

SOLUTION :

 

bon, j'ai passé une bonne heure à var_dumper dans tous les sens jusque dans DbCore pour comprendre le souci :

 

Dans le tuto de Zulian, au niveau du point 4 ajoutez ceci :

 

4. Ajouter dans la table `ps_product`,

my_checkbox type : tinyint(1), null : non, défaut : 0

ET FAITES DE MEME DANS `ps_product_shop`

 

 

Voili, j'espère que ça en aidera certains et certaines :)

Edited by webdigit (see edit history)
  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

Bonjour et merci pour ce précieux tuto!

 

J'ai voulu ajouter un champ de texte supplémentaire dans la fiche produit de l'admin, ce que j'ai réussi à faire.

J'ai aussi créé la table correspondant à ce champ dans ma base de données. Mais quand je remplis le champ via l'admin, la base de données n'enregistre pas.

Par contre, si je saisis directement dans ma base de données, les infos sont visibles dans le formulaire de l'admin et la fiche produit..

 

Je suis sure que ça doit être quelque chose de tout bête, mais je n'arrive pas à mettre la main dessus... quelqu'un aurait une idée?

Merci d'avance

Link to comment
Share on other sites

Bonjour et merci pour ce précieux tuto!

 

J'ai voulu ajouter un champ de texte supplémentaire dans la fiche produit de l'admin, ce que j'ai réussi à faire.

J'ai aussi créé la table correspondant à ce champ dans ma base de données. Mais quand je remplis le champ via l'admin, la base de données n'enregistre pas.

Par contre, si je saisis directement dans ma base de données, les infos sont visibles dans le formulaire de l'admin et la fiche produit..

 

Je suis sure que ça doit être quelque chose de tout bête, mais je n'arrive pas à mettre la main dessus... quelqu'un aurait une idée?

Merci d'avance

 

Hello,

Pourquoi avoir créé un table correspondante ? Il faut créer un champ dans ps_product et dans ps_product_shop avec le nom donné à votre input. Si vous souhaitez enregistrer les données dans une nouvelle table, la technique est différente et plus complexe, car il faut déclarer cette table à Prestashop dans son modèle (puisque MVC)...

 

A mon sens le souci est là.

 

Bonne nuit !

Link to comment
Share on other sites

Webdigit, merci pour ta réponse.

J'ai donc ajouté les bons champs, et tout recommencé en suivant le tuto de la page précédente.

Maintenant, c'est super, lorsque je saisis dans le champ de mon formulaire, c'est enregistré dans la base de données.

Mais le problème, est que la case du formulaire se vide à nouveau (même si l'écriture dans la base de données a été effective). je ne peux pas non plus récupérer l'info entrée dans le front de mon site.

 

Dans mon fichier product.php (classes/product.php), j'ai inséré la ligne suivante:

 

'url' =>	   array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 32),

 

Est-ce que c'est ça qui pose problème?

Edited by creations (see edit history)
Link to comment
Share on other sites

Webdigit, merci pour ta réponse.

J'ai donc ajouté les bons champs, et tout recommencé en suivant le tuto de la page précédente.

Maintenant, c'est super, lorsque je saisis dans le champ de mon formulaire, c'est enregistré dans la base de données.

Mais le problème, est que la case du formulaire se vide à nouveau (même si l'écriture dans la base de données a été effective). je ne peux pas non plus récupérer l'info entrée dans le front de mon site.

 

Dans mon fichier product.php (classes/product.php), j'ai inséré la ligne suivante:

 

'url' =>	   array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 32),

 

Est-ce que c'est ça qui pose problème?

 

Heylo,

 

difficile de dire ce qui ne va pas sans avoir le code source.

Possibilité : ta checkbox ou ton champ n'affiche pas la donnée en BO => vérifier le nom du input (name et id au cas où), vérifier que a nouvelle variable est bien créée

Affichage en front => utiliser les syntaxes smarty et faire commre pour les autres variables ex : {if $product.mavariable}mon code{/if}

Si cela ne va toujours pas, fait nous part de ton code source :)

Voici une autre source si besoin :

http://www.webdigit....tashop-1-5.html

Edited by webdigit (see edit history)
Link to comment
Share on other sites

Bonjour,

votre tuto m'intéresse grandement puisque je cherche à ajouter un champ perso à mes fiches produits, par contre je rencontre des difficultés .... :unsure:

(je précise que je ne suis pas un as de la programation, mais que je fais preuve de bonne volonté ..... :P )

 

Après modif, je n'arrive plus a entrer sur les fiches produits dans l'admin, je pense que je merdois sur l'étape 2 du tuto

 

...

 

2. Dans "\override\controllers\admin\AdminProductsController.php" :

Copier les fonctions :

- protected function copyFromPost(&$object, $table)

- public function renderForm()

- public function initFormInformations($product)

 

En y ajoutant le code pour "my_checkbox" sur le modèle de "available_for_order".

...

 

je ne comprend pas trop le

En y ajoutant le code pour "my_checkbox" sur le modèle de "available_for_order".

pouvez vous me donner votre fichier AdminProductsController.php afin de m'aiguiller un peu!!

 

Merci

Link to comment
Share on other sites

Bonjour,

 

Afin de compléter ce qui est relaté précédemment, Je vais vous montré un exemple pour un champ type description avec éditeur de contenu.

 

Avant toute chose allez dans votre jolie base de donnée et créer le champ "new_variable" dans la table "prefix_product_lang".

 

Ensuite, tel que l'à énoncé Paco112, modifier le fichier suivant.

override/classes/Products.php :

class Product extends ProductCore
{
public $new_variable;
public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
 Product::$definition['fields']['new_variable'] = array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString');
 parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
}

 

Ensuite dans le fichier ci-dessous (s'il n'existe pas, le créer à partir du fichier override/admin/template/products/informations.tpl) ajouté les ligne suivante où bon vous semble (si jamais vous pouvez à toujours le mettre après le description, près de la ligne 290) :

 

override/controllers/admin/templates/products/informations.tpl :

<tr>
<td class="col-left">
 {include file="controllers/products/multishop/checkbox.tpl" field="new_variable" type="tinymce" multilang="true"}
 <label>{$bullet_common_field} {l s='test :'}<br /></label>
 <p class="product_description">({l s='test'})</p>
</td>
<td style="padding-bottom:5px;">
  {include file="controllers/products/textarea_lang.tpl" languages=$languages
  input_name='new_variable'
  input_value=$product->new_variable
  }
 <p class="clear"></p>
</td>
  </tr>

 

Et dès lors que tout ceci est mis en place, vous avez un joli custom-textfield associer a votre produit.

 

La partie AdminProductsController n'est pas nécessaire s'il ne s'agit que d'un texte tout simplement. par contre si vous souhaité le limité en caractères, je vous conseille de voir se que est fait vis à vis du champ "description_short".

 

Voili voilou. merci au personne qui m'on aidé dans mon raisonnement et qui m’ont certainement fait gagné un temps monstre :)

Edited by hiroshi (see edit history)
Link to comment
Share on other sites

Nickel merci hiroshi !

 

Je suis moi aussi exactement en ce moment sur ce champ d'édition texte. Je ferai un retour sur le sujet ce soir encore.

 

Merci !

 

P.S : tu n'as pas de souci de traduction ? Car en faisant un override du tpl il y a en général toutes les traduction qui sautent :)

 

Pour ceux qui n'utilisent pas la version de Paco112 (mais je conseille la version de Paco qui sera plus perenne), voici le code :

 

class Product extends ProductCore
{

(...)
public $new_variable;


public static $definition = array(
 'table' => 'product',
 'primary' => 'id_product',
 'multilang' => true,
 'multilang_shop' => true,
 'fields' => array(
  // Classic fields
  (...)
  /* Shop fields */
  (...)

  /* Lang fields */
  'new_variable' =>   array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString'),
  (...)

 ),
 'associations' => array(
(...)
 )
);
}

 

Pour ceux qui souhaitent un textarea sans le rte (rich text editor qui prend quand même vachement de place... surtout quand on en a pas :D), il vous suffit de créer un fichier "textarea_lang_notiny.tpl" que vous placez au même endroit que textarea_lang.tpl (ou alors vous procédez à un override) avec le code suivant (qui est en fait le même que textarea_lang.tpl sans la classe "autoload_rte". Ainsi vous aurez la main dessus pour le mettre aux dimensions voulues si comme moi vous placez ce textarea sous les options du produit)

 

<div class="translatable">
  {foreach from=$languages item=language}
  <div class="lang_{$language.id_lang}" style="{if !$language.is_default}display:none;{/if}float: left;">
  <textarea cols="40" rows="4" type="text" id="{$input_name}_{$language.id_lang}" name="{$input_name}_{$language.id_lang}" >{if isset($input_value[$language.id_lang])} {$input_value[$language.id_lang]|htmlentitiesUTF8}{/if}</textarea>
  <span class="counter" max="{if isset($max)}{$max}{else}none{/if}"></span>
  <span class="hint" name="help_box">{$hint|default:''}
	 <span class="hint-pointer"> </span>
  </span>
  </div>
  {/foreach}
</div>

 

et ensuite dans votre information.tpl vous faites appel comme ceci :

 

{include file="controllers/products/textarea_lang_notiny.tpl" languages=$languages input_name='new_variable' input_value=$product->new_variable}

 

Et hop, le tour est joué. Vous avez un petit textarea à placer où vous voulez...

 

P.S : pour modifier les dimensions, pour ceux qui ne sauraient pas :rolleyes: , faites varier cols (hauteur) et rows (largeur)

Edited by webdigit (see edit history)
Link to comment
Share on other sites

Pour le coté traduction a vrai dire, je ne m'y suis pas trop penché car tout le coté admin est destiné à des utilisateurs Français pour le moment.

 

Mais c'est une bonne question à soulever en effet.

 

Sinon pour la partie front du produit, juste pour indication, l'appel du contenu se fait comme ça :

themes/mon_theme/product.tpl :

{if isset($product) && $product->new_variable}
 <!-- full new_variable -->
 <div id="idTabx2" class="rte">{$product->new_variable}</div>
{/if}

 

Et pas la peine de me remercier, il faut surtout remercier Paco112 et Zulian qui m'ont permis d'écrire ce bout de code.

 

@ +

Edited by hiroshi (see edit history)
Link to comment
Share on other sites

Pour les traductions, je m'y met prochainement. La solution vient du fait que (je pense) les liens vers les fichiers de traductions ne sont plus corrects lorsque l'on fait l'override. Il faut donc vérifier si les fichiers qui sont en override accèdent correctement aux traductions. Et si mes souvenir sont bon, quand on fait un override de certaines méthode, on bypass le setting des traductions... sans doute ajouter ce chemin dans le construct ? (c'est une idée que je testerai :rolleyes: )

Link to comment
Share on other sites

Je viens de trifouiller un peu dans la traduction.

 

Donc pour tester j'ai modifier le fichier /classes/Translate vers la ligne 70 :

$key = md5(str_replace('\'', '\\\'', $string));
 if (isset($_LANGADM[$class.$key]))
  $str = $_LANGADM[$class.$key];
 else
  $str = $class.$key;
  //$str = Translate::getGenericAdminTranslation($string, $key, $_LANGADM);

 

Et là je remarque que tout les traduction non exécuter n'ont qu'un $key et pas de $classe.

 

Donc peut-être en rajoutant dans le fichier de traduction les key sans les classe, ça peu fonctionner...

c'est une solution alternative à tester en attendant d'avoir mieux.

 

Pour faire une traduction à la volé :

imaginons que ma variable est {l s='appears in the body of the product page'} il faut faire en php du md5('appears in the body of the product page') pour récupérer la key.

 

cordialement,

Link to comment
Share on other sites

Je confirme se que j'avançai, Dans le fichier "translations/fr/admin.php" afin de remettre les traductions de la class surclasser avec uniquement les key.

 

Exemple :

$_LANGADM['AdminProducts38d301f7ef549a79620e99fd8b51fa34'] = 'apparaît dans les listes de produits et sur le haut de la page du produit';

Il faut ajouter (préférence après une petite ligne de commentaire explicative à la fin du fichier) :

/* Traduction de la class Produits Overider pour le site mon_site */
$_LANGADM['38d301f7ef549a79620e99fd8b51fa34'] = 'apparaît dans les listes de produits et sur le haut de la page du produit';

 

Comme dit précédemment, il s'agit que d'une solution de substitution en attendant d'en trouvé une meilleur.

 

Cordialement,

Link to comment
Share on other sites

Webdigit, merci pour ta réponse. J'ai donc ajouté les bons champs, et tout recommencé en suivant le tuto de la page précédente. Maintenant, c'est super, lorsque je saisis dans le champ de mon formulaire, c'est enregistré dans la base de données. Mais le problème, est que la case du formulaire se vide à nouveau (même si l'écriture dans la base de données a été effective). je ne peux pas non plus récupérer l'info entrée dans le front de mon site. Dans mon fichier product.php (classes/product.php), j'ai inséré la ligne suivante:
'url' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 32),

Est-ce que c'est ça qui pose problème?

 

Hello,

 

tu parles d'un champ et d'une checkbox. Il faut que tu crées les variables pour chacune des entrées. Une variable pour la checkbox et une variable pour le champ + les décli dans les 3 fichiers du tuto.

Le fait que ta checkbox n'a pas le comportement attendu, c'est, me semble t il, parce que ta checkbox n'est tout simplement pas enregistrée, il n'y a que ton champ url.

 

A dispo si besoin...

Link to comment
Share on other sites

  • 2 weeks later...

Bonjour,

J'aurai une nouvelle problématique.

Je m'explique.

 

J'ai des produits qui se compose d'autre produit (comme des packages de produits). Il me faudrai un super custom field avec la liste des produit existant attaché a une catégorie avec la possibilité de les ajouté ou retiré de la liste de mes choix retenu (un peu a la minière de la configuration du module "menu horizontal" natif à presta 1.5).

 

Mais pour l'heure, je décompose mon problème et je ne vois pas comment passer à mon objet product une nouvelle variable (même textuel).

 

Si vous avez des pistes, je suis preneur.

Link to comment
Share on other sites

En effet, je découvre encore...

Merci pour l'info et pour le coup, je passe pour un vrai noob :P

 

A trop vouloir faire de code on oublie les fonction de base :P

 

Mais je serait quand même intéresser de savoir si il es possible d'&ajouté une variable à un object.

 

Merci beaucoup :P

Link to comment
Share on other sites

En effet, je découvre encore...

Merci pour l'info et pour le coup, je passe pour un vrai noob :P

 

A trop vouloir faire de code on oublie les fonction de base :P

 

Mais je serait quand même intéresser de savoir si il es possible d'&ajouté une variable à un object.

 

Merci beaucoup :P

 

Bah, je pense que le forum est là pour cela :) Moi ça m'a déjà aussi aidé ;)

A charge de revanche :) :)

Link to comment
Share on other sites

A la lecture de ce que tu demandes, c'est ce que cette fonctionnalité fait, non ?

 

Juste pour savoir, y'a t'il possibilité de généré un select a la place de l'input en auto-complession ?

du style :

<select>
<optgroup label="Cat1">
 <option value="id1">Produit1</option>
 <option value="id2">Produit2</option>
 <option value="id3">Produit3</option>
</optgroup>
<optgroup label="Cat2">
 <option value="id4">Produit4</option>
 <option value="id5">Produit5</option>
 <option value="id6">Produit6</option>
</optgroup>
</select>

  • Like 1
Link to comment
Share on other sites

Juste pour savoir, y'a t'il possibilité de généré un select a la place de l'input en auto-complession ?

du style :

<select>
<optgroup label="Cat1">
 <option value="id1">Produit1</option>
 <option value="id2">Produit2</option>
 <option value="id3">Produit3</option>
</optgroup>
<optgroup label="Cat2">
 <option value="id4">Produit4</option>
 <option value="id5">Produit5</option>
 <option value="id6">Produit6</option>
</optgroup>
</select>

Oui, mais tu vas perdre l'aspect dynamique AJAX de la chose... Là tu va devoir créer une méthode dans la class correspondante. Tu va chercher les info avec une jointure dans les tables categorie_product (de mémoire) et product_lang et category_lang. Ensuite te crée ton select (inspire toi de ce qui existe déjà pour les select autoformés.) Là pas trop le temps de décortiquer, mais c'est l'esprit...

Link to comment
Share on other sites

  • 2 weeks later...

Bonsoir,

 

Je préviens d'entrer je débute sur Prestashop mais il faut bien commencer :D

Tout d'abord, merci à ceux qui ont fait les tutos.

 

Mon problème :

dans override/classes/product.php, j'ai mis :

 


public static $definition = array(
....
'leadtime' =>  array('type' => self::TYPE_STRING, 'validate' => 'isLeadtime'),
....
);

 

Quand je cherche à mettre la déclinaison à jours, j'ai me message suivant

 

 


[color=#000000][font=Verdana]
[b]Validation function not found. isLeadtime[/b]
[i]at line [/i][b]928[/b][i] in file [/i][b]classes/ObjectModel.php[/b][/font][/color][color=#000000][font=Verdana]

922. 
923. 		// Check field validator
924. 		if (!empty($data['validate']))
925. 		{
926. 			if (!method_exists('Validate', $data['validate']))
[color=#F20000][b]927. 				throw new PrestaShopException('Validation function not found. '.$data['validate']);
[/b][/color]928. 
929. 			if (!empty($value) && !call_user_func(array('Validate', $data['validate']), $value))
930. 				return 'Property '.get_class($this).'->'.$field.' is not valid';
931. 		}
932. [/font][/color]

 

Avez-vous une idée du problème ?

Eh oui je débute !!!

 

Merci d'avance pour votre aide

Link to comment
Share on other sites

Hello stef71,

 

Ton souci est que tu demandes une validation "isLeadTime" sur une chaîne de caractère (TYPE_STRING).

Prestashop ne reconnait pas cette méthode de validation ("Validation function not found. isLeadtime").

 

Si c'est bien une chaîne de caractères que tu as, utilise plutôt la validation "isString".

Edited by webdigit (see edit history)
Link to comment
Share on other sites

Salut,

 

Bon j'ai résolu mon problème ci-dessus

 

Mon nouveau champs se met à jour dans la base et je vois les données dans les déclinaisons.

 

Par contre quand je clique sur "modifier", je ne vois que l'intitulé du champs mais la valeur n’apparaît pas.

Si j'entre une valeur dans ce champ, la table se met bien à jour.

 

A ce stade, je n'arrive pas a savoir ou se trouve la fonction qui récupère les données pour les afficher à l'écran. :unsure:

 

si quelqu’un pourrait m'aiguiller ça serait sympas.

 

Merci d'avance

Link to comment
Share on other sites

Bon mes problèmes de BO sont résolus mais je sèche sur le front depuis hier soir

 

J'ai fait les modif dans product.tpl puis dans product.js mais que nenni :wacko:

J'ai bien l'étiquette qui s'affiche mais pas la valeur.

En regardant le code source généré, je constate que addCombination ne trouve pas de valeur pour mon nouveau champ.

 

 

fonction addCombination de product.js

function addCombination(idCombination, arrayOfIdAttributes, quantity, price, ecotax, id_image, reference, leadtime, unit_price, minimal_quantity, available_date, combination_specific_price)
{
globalQuantity += quantity;
var combination = [];
combination['idCombination'] = idCombination;
combination['quantity'] = quantity;
combination['idsAttributes'] = arrayOfIdAttributes;
combination['price'] = price;
combination['ecotax'] = ecotax;
combination['image'] = id_image;
combination['reference'] = reference;
combination['leadtime'] = leadtime; // mon nouveau champ
combination['unit_price'] = unit_price;
combination['minimal_quantity'] = minimal_quantity;
combination['available_date'] = available_date;
combination['specific_price'] = [];
combination['specific_price'] = combination_specific_price;
combinations.push(combination);

}

 

Merci d'avance

 

PS Leadtime vient de la table ps_attribut_product

Link to comment
Share on other sites

 

PS Leadtime vient de la table ps_attribut_product

 

Les méthode de validation sont définies dans le Core et ne sont pas liées au nom de ta variable. Ex : isString signifie "vérifie que ce que je reçois est bien une chaîne de caractère". Si tu souhaites utiliser isLeadtime, tu dois créer la méthode isLeadTime avec tes propres retours sur validation.

Link to comment
Share on other sites

@stef71 : tu as fait un alert dans ta fonction js pour voir si tu reçois leadtime ? Si tu ne reçois rien à ce niveau, il faut que tu remontes dans ton algo petit à petit pour voir où tu perds ta variable.

Je n'ai pas de visibilité sur ton code, mais si c'est pour un réaffichage, as tu vérifié que cette variable est dispo dans ton objet product ?

Edited by webdigit (see edit history)
Link to comment
Share on other sites

@stef71 : fait un

 

print_r($product);

 

ou

 

var_dump($product);

 

dans tes algo PHP où tu as l'object product qui est généré ou utilisé. Lors de l'affichage de la page, il t'affichera avec print_r le contenu complet de ton object. Va tout en bas et tu verras les valeurs des variables. Tu verras déjà si la tienne y est :)

 

Prestashop est orienté object... c'est le moment de s'y mettre :);)

Edited by webdigit (see edit history)
Link to comment
Share on other sites

Eh, eh, ca y est avec un peu de patience on y arrive.

 

Pour ceux qui voudront agir sur les attributs et notamment la table ps_product_attribut, il faut penser à modifier le select en incluant le nouveau champ dans la requête sql dans classes/products.php

 

@weddigit : merci pour ton aide et ta patience

Link to comment
Share on other sites

  • 2 weeks later...
  • 1 month later...

Bonjour,

 

Tout fonctionnait chez moi avant la maj vers la 1.5.4.

 

Depuis seul le premier champ ajouté dans le fichier override/classes/product.php s'enregistre par le BO.

 

Voilà comment j'ai écrit mon code:

 

<?php
class Product extends ProductCore
{
public $livre_avec;
public $points_forts;

public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
 Product::$definition['fields']['livre_avec'] = array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString');
 parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
 Product::$definition['fields']['points_forts'] = array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString');
 parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}
}
?>

 

Quelqu'un aurait-il une piste pour m'aiguiller?

Merci d'avance!

 

Fred

 

 

EDIT: Problème résolu: il faut écrire une seule ligne "parent::_construct" à la fin, et pas entre chaque définition. Cela fonctionnait auparavant mais c'était plutôt anormal... Si cela peut servir à quelqu'un!

Edited by Frédéric D. (see edit history)
Link to comment
Share on other sites

  • 3 months later...

Bonjour,
 
Je suis de retour  :D
 
J'essaie de faire marche le tuto sur une version 1.5.5 mais sans succès
Je bloque au niveau de override/classe/product.php.
 
1°: j'ai ce message qui s'affiche

 
 Strict Standards: Declaration of Product::addProductAttribute() should be compatible with that of ProductCore::addProductAttribute() in .../override/classes/Product.php on line 164

Strict Standards: Declaration of Product::addCombinationEntity() should be compatible with that of ProductCore::addCombinationEntity() in .../override/classes/Product.php on line 164

Strict Standards: Declaration of Product::updateProductAttribute() should be compatible with that of ProductCore::updateProductAttribute() in .../override/classes/Product.php on line 164

Strict Standards: Declaration of Product::updateAttribute() should be compatible with that of ProductCore::updateAttribute() in .../override/classes/Product.php on line 164

Strict Standards: Declaration of Product::addAttribute() should be compatible with that of ProductCore::addAttribute() in ..../override/classes/Product.php on line 164

 
 
Je vois bien mon champ dans le FO mais impossible de le mettre a jour ou de faire une création .
 
product.php :

<?php

class Product extends ProductCore
{
public $leadtime;

public function __construct($id_product = null, $full = false, $id_lang = null, $id_shop = null, Context $context = null)
{
Product::$definition['fields']['leadtime'] = array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isString');
parent::__construct($id_product, $full, $id_lang, $id_shop, $context);
}

public function addProductAttribute($price, $weight, $unit_impact, $ecotax, $quantity, $id_images, $reference,
$id_supplier = null, $ean13, $default, $location = null, $upc = null, $leadtime, $minimal_quantity = 1)
{
Tools::displayAsDeprecated();

$id_product_attribute = $this->addAttribute(
$price, $weight, $unit_impact, $ecotax, $id_images,
$reference, $ean13, $default, $location, $upc, $leadtime, $minimal_quantity
);

if (!$id_product_attribute)
return false;

StockAvailable::setQuantity($this->id, $id_product_attribute, $quantity);
//Try to set the default supplier reference
$this->addSupplierReference($id_supplier, $id_product_attribute);
return $id_product_attribute;
}

public function addCombinationEntity($wholesale_price, $price, $weight, $unit_impact, $ecotax, $quantity,
$id_images, $reference, $id_supplier, $ean13, $default, $location = null, $upc = null, $leadtime, $minimal_quantity = 1, array $id_shop_list = array())
{
$id_product_attribute = $this->addAttribute(
$price, $weight, $unit_impact, $ecotax, $id_images,
$reference, $ean13, $default, $location, $upc, $leadtime, $minimal_quantity, $id_shop_list);

$this->addSupplierReference($id_supplier, $id_product_attribute);
$result = ObjectModel::updateMultishopTable('Combination', array(
'wholesale_price' => (float)$wholesale_price,
), 'a.id_product_attribute = '.(int)$id_product_attribute);

if (!$id_product_attribute || !$result)
return false;

return $id_product_attribute;
}

public function updateProductAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax,
$id_images, $reference, $id_supplier = null, $ean13, $default, $location = null, $upc = null, $leadtime, $minimal_quantity, $available_date)
{
Tools::displayAsDeprecated();

$return = $this->updateAttribute(
$id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax,
$id_images, $reference, $ean13, $default, $location = null, $upc = null, $leadtime, $minimal_quantity, $available_date
);
$this->addSupplierReference($id_supplier, $id_product_attribute);

return $return;
}

public function updateAttribute($id_product_attribute, $wholesale_price, $price, $weight, $unit, $ecotax,
$id_images, $reference, $ean13, $default, $location = null, $upc = null, $leadtime, $minimal_quantity = null, $available_date = null, $update_all_fields = true, array $id_shop_list = array())
{
$combination = new Combination($id_product_attribute);

if (!$update_all_fields)
$combination->setFieldsToUpdate(array(
'price' => !is_null($price),
'wholesale_price' => !is_null($wholesale_price),
'ecotax' => !is_null($ecotax),
'weight' => !is_null($weight),
'unit_price_impact' => !is_null($unit),
'default_on' => !is_null($default),
'minimal_quantity' => !is_null($minimal_quantity),
'available_date' => !is_null($available_date),
));

$price = str_replace(',', '.', $price);
$weight = str_replace(',', '.', $weight);

$combination->price = (float)$price;
$combination->wholesale_price = (float)$wholesale_price;
$combination->ecotax = (float)$ecotax;
$combination->weight = (float)$weight;
$combination->unit_price_impact = (float)$unit;
$combination->reference = pSQL($reference);
$combination->location = pSQL($location);
$combination->ean13 = pSQL($ean13);
$combination->upc = pSQL($upc);
$combination->upc = pSQL($upc);
$combination->default_on = (int)$default;
$combination->minimal_quantity = (int)$minimal_quantity;
$combination->available_date = $available_date ? pSQL($available_date) : '0000-00-00';

if (count($id_shop_list))
$combination->id_shop_list = $id_shop_list;

$combination->save();

if (!empty($id_images))
$combination->setImages($id_images);

Product::updateDefaultAttribute($this->id);

Hook::exec('actionProductAttributeUpdate', array('id_product_attribute' => $id_product_attribute));

return true;
}

public function addAttribute($price, $weight, $unit_impact, $ecotax, $id_images, $reference, $ean13,
$default, $location = null, $upc = null, $leadtime, $minimal_quantity = 1, array $id_shop_list = array())
{
if (!$this->id)
return;

$price = str_replace(',', '.', $price);
$weight = str_replace(',', '.', $weight);

$combination = new Combination();
$combination->id_product = (int)$this->id;
$combination->price = (float)$price;
$combination->ecotax = (float)$ecotax;
$combination->quantity = 0;
$combination->weight = (float)$weight;
$combination->unit_price_impact = (float)$unit_impact;
$combination->reference = pSQL($reference);
$combination->location = pSQL($location);
$combination->ean13 = pSQL($ean13);
$combination->upc = pSQL($upc);
$combination->leadtime = pSQL($leadtime);
$combination->default_on = (int)$default;
$combination->minimal_quantity = (int)$minimal_quantity;

// if we add a combination for this shop and this product does not use the combination feature in other shop,
// we clone the default combination in every shop linked to this product
if ($default && !$this->hasAttributesInOtherShops())
{
$id_shop_list_array = Product::getShopsByProduct($this->id);
foreach ($id_shop_list_array as $array_shop)
$id_shop_list[] = $array_shop['id_shop'];
$id_shop_list = array_unique($id_shop_list);
}

if (count($id_shop_list))
$combination->id_shop_list = array_unique($id_shop_list);

$combination->add();

if (!$combination->id)
return false;

Product::updateDefaultAttribute($this->id);

if (!empty($id_images))
$combination->setImages($id_images);

return (int)$combination->id;
}


}

Une petite idée du problème ?

 

 

Link to comment
Share on other sites

Pour ceux que ça intéresse vous pouvez vous inspirer de ça

 

http://nemops.com/extending-prestashop-objects/

 

ça marche avec une 1.5.5 pour un ajout de champs sur la fiche produit

 

Par contre si vous êtes comme moi et que vous souhaitez avoir un champ au niveau des combinaisons, c'est pas la joie car toujours ce problème avec l'override AdminProductsController et ce foutu message :

 Strict Standards: Declaration of Product::addProductAttribute() should be compatible with that of ProductCore::addProductAttribute() in .../override/classes/Product.php on line 164

Edited by stef71 (see edit history)
Link to comment
Share on other sites

  • 1 year later...

HeY

oui sans souci. Il suffit de suivre les exemples de ce topic. Ensuite utiliser les données du nouveau champ dans ton category.tpl en allant chercher la variable que tu aura passé dans ton objet products.

donc 1 créer ton champ et voir qu'il s'enregistre bien en bd. 2 regarder comme les données sont rapatriées dans ton tpl et faire de même pour ton nouveau champ en ça se passe dans ton cas dans category.tpl

Link to comment
Share on other sites

@webdigit Merci pour ta réponse . J'ai suivi le tuto en essayant de l'adapter comme je  voulais une description des produits affichés sur les pages catégories. J'ai bien mon champ qui apparait en BO mais dès que je veux enregistrer une description  j'ai un message d'erreur   "Une erreur s'est produite pendant la mise à jour de l'objet. category ()". J'ai vidé le cache après mes modifications pourtant. Je me demandais si l'appel du nouveau champ ne devrait pas se faire dans product-list.tpl , mais pareil ça marche pas.

Edited by Fulanyboy (see edit history)
Link to comment
Share on other sites

Ok. D'abord step 1. Ton nouveau champ est bien dans l'onglet information de la création/édition produit ? Si oui, tu devrait plutôt être dans l'object Product plutôt que l'object Category, non ? Tu souhaites ajouter une descr produit qui ne serait affichée que dans la page catégorie c'est bien cela ? Si oui, c'est le même principe que ce qu'il y a dans les autres tuto, hormis le fait que ta variable tu dois aller la chercher et l'afficher dans category.tpl. Si j'ai bien compris ta demande... ;)

Link to comment
Share on other sites

Heu je comprend nin là ;)

Ta demandes : 

 

"Bonjour à tous est-il possible d'avoir un champ de description pour les produits mais quand ils sont affichés sur les pages de catégories et pas sur la page produit individuelle ?"

 

Pourquoi es tu dans la description de la catégorie alors que tu souhaites une description pour les produits ? La description concerne quoi ? La catégorie en elle même ou les produits ? C'est très différent. Autrement dit, est ce que cette nouvelle description est identique pour tous les produits d'une même catégorie ou alors cette description doit pouvoir être différente en fonction des produits ?

 

Si la descr doit être différente en fonction des produits => il faut que tu reste dans catalogue > produit et pas catalogue > catégories

Link to comment
Share on other sites

Je ne suis pas clair dans la formulation effectivement , j'aimerai avoir une description différente pour les produits en fonction des catégories. J'ai suivi le tuto mais comme j'avais pas de résultat pour une description du produit affiché dans les pages catégories , j'ai pensé à faire la modif pour un champ dans catalogue>catégories.

Edited by Fulanyboy (see edit history)
Link to comment
Share on other sites

  • 2 months later...

Bonjour,

Je suis en train de développer un module de devis personnalisée, j'ai suivit ce blog pour  ajouter un bouton devis pour chaque produit, le code il marche bien en back-office par contre en front-office quand je clic sur un produit j'ai l'erreur suivant " there is 1 error product not found ".

 

Je travail avec la version 1.6.0.13 de prestashop, un grand merci à ceux qui pourront m'aider à débloquer la situation. 

 

 

post-923382-0-50663000-1430812642_thumb.jpg
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...