Simao Henriques Posted November 28, 2024 Share Posted November 28, 2024 Hey everyone, newbie dev here, I am trying to make it so that when adding a new product in PrestaShop, forbid duplicate references and/or ean13. For that I found this old thread:Product's Reference code field to be required and unique - Core developers - PrestaShop Forums But that solution is for the legacy controller AdminProductsController (as far as I know, not being used anymore). How can I implement something similar but for the new controllers ? Thank you very much in advance, Simão Henriques Link to comment Share on other sites More sharing options...
Simao Henriques Posted December 27, 2024 Author Share Posted December 27, 2024 Anyone with a solution ? Link to comment Share on other sites More sharing options...
ps8modules Posted December 27, 2024 Share Posted December 27, 2024 Hi, You can use a hook in your module hookActionObjectProductUpdateBefore($params) For example, you can get a product ID: $id_product = $params['object']->id; Link to comment Share on other sites More sharing options...
Simao Henriques Posted December 30, 2024 Author Share Posted December 30, 2024 I remember trying something similar (getting the product data and comparing it before saving with an hook) and having the following problem: if any product is left with an empty ean13 (let's say someone forgets to set it after adding a new product, or simply is not set by any reason), when someone then presses "Add new product", prestashop actually creates an empty product (with an empty ean13 too), so it would give an error because all the hooks that trigger when saving/creating a product would also be called, and thus my own code would detect the same ean13 (of empty) in both products. The same would happen when duplicating a product, since prestashop would attempt to create a product with same ean13 before even displaying the edit page to the admin. Is there a way to prevent that ? Also, let me just say thank you for replying, I appreciate any input. And sorry if my english is not great. Link to comment Share on other sites More sharing options...
ps8modules Posted December 30, 2024 Share Posted December 30, 2024 Hi. Everything you write can be treated in the code so that an error is not displayed in the case of an empty ean13 or reference. I'm not at my computer right now, so I'll give you a demo of the function later. Approx. per hour. Link to comment Share on other sites More sharing options...
ps8modules Posted December 30, 2024 Share Posted December 30, 2024 Sample: public function hookActionObjectProductUpdateBefore($params) { /* detect duplicate ean 13 */ $checkEan13 = true; /* detect duplicate reference */ $checkReference = true; /* check if it is a copy */ $checkCopyOfproduct = true; /* id product */ $idProduct = $params['object']->id; /* product reference */ $productReference = $params['object']->reference; /* ean 13 */ $productEan13 = $params['object']->ean13; $db = Db::getInstance(); /* check if copy product */ $yesCopyOfProduct = false; if (str_contains($params['object']->name, 'copy of')) { $yesCopyOfProduct = true; } /* errors */ $errors = []; if ($checkEan13 && !empty($productEan3)) { if ($yesCopyOfProduct) { $params['object']->ean13 = ''; } else { $findDuplicateEan13 = $db->getValue('SELECT COUNT(id_product) as cnt FROM '._DB_PREFIX_.'product WHERE ean13 = \''.$productEan13.'\''); if ($findDuplicateEan13) { $errors[] = $this->l('Found').' '.$findDuplicateEan13.' '.$this->l('products with the same EAN 13'); } } } if ($checkReference && !empty($productReference)) { if ($yesCopyOfProduct) { $params['object']->reference = ''; } else { $findDuplicateReference = $db->getValue('SELECT COUNT(id_product) as cnt FROM '._DB_PREFIX_.'product WHERE reference = \''.$productReference.'\''); if ($findDuplicateReference) { $errors[] = $this->l('Found').' '.$findDuplicateReference.' '.$this->l('products with the same reference'); } } } if ($errors) { $this->errors[] = implode('<br>', $errors); } } 1 Link to comment Share on other sites More sharing options...
Simao Henriques Posted December 31, 2024 Author Share Posted December 31, 2024 Thanks you so much, looking at your solution, it is so simple and clean to the point that I am left feeling dumb on how I didn't think of doing that in the first place. The only error it gave was in the scenario of editing a product: it would detect a ean/ref violation since the product itself already exists in the database, it was easily fixed tough just by adding another check at the end of the querries: $findDuplicateEan13 = $db->getValue('SELECT COUNT(id_product) as cnt FROM '._DB_PREFIX_.'product WHERE ean13 = \''.$productEan13.'\' AND id_product != ' . (int)$idProduct); $findDuplicateReference = $db->getValue('SELECT COUNT(id_product) as cnt FROM '._DB_PREFIX_.'product WHERE reference = \''.$productReference.'\' AND id_product != ' . (int)$idProduct); And a slight tweak on the check if copy line, because name was an array (because of language ids): $defaultLanguageId = (int)Context::getContext()->language->id; if (str_contains($params['object']->name[$defaultLanguageId] ?? '', 'copy of')) { $yesCopyOfProduct = true; } On the other hand, I couldn't make the exception work, $this->errors doesn't seem to work (maybe because I am not in an admin controller ? I don't really know), I tried some other syntaxes but with no sucess. What I ended up doing is addding an error pop-up with the following: $this->get('session')->getFlashBag()->clear(); $this->get('session')->getFlashBag()->add($type, implode(', ', $errors)); But the saving process of the product still goes trough. While not exactly what I had in mind, it works good enough. I will leave the full code in case someone finds this post and wishes to copy your method with the small changes mentioned: public function hookActionObjectProductUpdateBefore($params) { // Get the default language ID for the current shop $defaultLanguageId = (int)Context::getContext()->language->id; /* detect duplicate ean 13 */ $checkEan13 = true; /* detect duplicate reference */ $checkReference = true; /* check if it is a copy */ $checkCopyOfproduct = true; /* id product */ $idProduct = $params['object']->id; /* product reference */ $productReference = $params['object']->reference; /* ean 13 */ $productEan13 = $params['object']->ean13; $db = Db::getInstance(); /* check if copy product */ $yesCopyOfProduct = false; if (str_contains($params['object']->name[$defaultLanguageId] ?? '', 'copy of')) { $yesCopyOfProduct = true; } /* errors */ $errors = []; if ($checkEan13 && !empty($productEan13)) { if ($yesCopyOfProduct) { $params['object']->ean13 = ''; } else { $findDuplicateEan13 = $db->getValue('SELECT COUNT(id_product) as cnt FROM '._DB_PREFIX_.'product WHERE ean13 = \''.$productEan13.'\' AND id_product != ' . (int)$idProduct); if ($findDuplicateEan13) { $errors[] = $this->l('Found').' '.$findDuplicateEan13.' '.$this->l('products with the same EAN 13'); } } } if ($checkReference && !empty($productReference)) { if ($yesCopyOfProduct) { $params['object']->reference = ''; } else { $findDuplicateReference = $db->getValue('SELECT COUNT(id_product) as cnt FROM '._DB_PREFIX_.'product WHERE reference = \''.$productReference.'\' AND id_product != ' . (int)$idProduct); if ($findDuplicateReference) { $errors[] = $this->l('Found').' '.$findDuplicateReference.' '.$this->l('products with the same reference'); } } } $type="error"; $this->get('session')->getFlashBag()->clear(); $this->get('session')->getFlashBag()->add($type, implode(', ', $errors)); } And in case someone knows how to throw an exception (for context, this is in a hook inside a custom module), feel free to let me know. Thank you @ps8modules , once again, for the solution Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now