Jump to content

[PS 8.2] - Unique Reference and Ean13


Simao Henriques

Recommended Posts

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

  • 4 weeks later...

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

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);
    }

}

 

  • Thanks 1
Link to comment
Share on other sites

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

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...