Search code examples
prestashopprestashop-1.7

Create product combinations in prestashop 1.7 programmatically duplicate id issue


I am trying to add products with combinations with php code. What when running the script duplicate primary ID error occured in ps_product_attribute_combination table. I am using multiple attributes from the color and size group. This code is placed after $product->save() call.

        $combinationAttributes[] = array(1,2);
        $combinationAttributes[] = array(5,6,7);
        

        if(!$product->productAttributeExists($combinationAttributes,false, null, true, true)){
            $price = $price;
            $weight = '';
            $ecotax = '';
            $unit_price_impact="";
            $quantity = 100;
            $reference = $reference;
            $supplier_reference = "";
            $ean13 = "";

            
            $default = '0';


            $idProductAttribute = $product->addProductAttribute((float)$price, (float)$weight, $unit_price_impact, (float)$ecotax, (int)$quantity, "", strval($reference), strval($supplier_reference), strval($ean13), $default, NULL, NULL,'','','','');
    
            
            $product->addAttributeCombinaison($idProductAttribute, $combinationAttributes);

Solution

  • Inserting product programmatically can be a pain. I have written my own code using a part of Prestashop default values and a part inserting values using sql.

    Hope this code helps you in your progress. You can add this file to your adminfolder and run it.

    Standalone PHP file

    <?php
    if ( !defined( '_PS_ADMIN_DIR_' ) ) {
        define( '_PS_ADMIN_DIR_', getcwd() );
    }
    include( _PS_ADMIN_DIR_ . '/../config/config.inc.php' );
    
    addProduct(
        '1234567891234',                         // Product EAN13
        'Stackoverflow',                         // Product reference
        'Crezzur',                               // Product name
        5,                                       // Product quantity
        'Code by Crezzur (https://crezzur.com)', // Product description
        array(                                   // Product features (array)
            array( "name" => "Color", "value" => "Red" ),
            array( "name" => "Height", "value" => "200cm" ),
        ),
        '999.95',                                // Product price
        'https://i.imgur.com/yOp1xt3.jpg',       // Product image
        1,                                       // Product default category
        array(1, 5)                              // All categorys for product (array)
    );
    
    function addProduct( $ean13, $ref, $name, $qty, $text, $features, $price, $imgUrl, $catDef, $catAll ) {
        $product = new Product();              // Create new product in prestashop
        $product->ean13 = $ean13;
        $product->reference = $ref;
        $product->name = createMultiLangField( $name );
        $product->description = htmlspecialchars($text);
        //$product->link_rewrite = createMultiLangField($linkrewrite);
        $product->id_category_default = $catDef;
        $product->redirect_type = '301';
        $product->price = $price;
        $product->quantity = $qty;
        $product->minimal_quantity = 1;
        $product->show_price = 1;
        $product->on_sale = 0;
        $product->online_only = 0;
        $product->meta_description = '';
        $product->add();
        $product->addToCategories($catAll);
    
        // Insert "feature name" and "feature value"
        if ( is_array( $features ) ) {
            foreach ( $features as $feature ) {
                $attributeName = $feature[ 'name' ];
                $attributeValue = $feature[ 'value' ];
    
                // 1. Check if 'feature name' exist already in database
                $FeatureNameId = Db::getInstance()->getValue( 'SELECT id_feature FROM ' . _DB_PREFIX_ . 'feature_lang WHERE name = "' . pSQL( $attributeName ) . '"' );
                // If 'feature name' does not exist, insert new.
                if ( empty( $getFeatureName ) ) {
                    Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature` (`id_feature`,`position`) VALUES (0, 0)' );
                    $FeatureNameId = Db::getInstance()->Insert_ID(); // Get id of "feature name" for insert in product
                    Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_shop` (`id_feature`,`id_shop`) VALUES (' . $FeatureNameId . ', 1)' );
                    Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_lang` (`id_feature`,`id_lang`, `name`) VALUES (' . $FeatureNameId . ', ' . Context::getContext()->language->id . ', "' . pSQL( $attributeName ) . '")' );
                }
    
                // 1. Check if 'feature value name' exist already in database
                $FeatureValueId = Db::getInstance()->getValue( 'SELECT id_feature_value FROM webshop_feature_value WHERE id_feature_value IN (SELECT id_feature_value FROM webshop_feature_value_lang WHERE value = "' . pSQL( $attributeValue ) . '") AND id_feature = ' . $FeatureNameId );
                // If 'feature value name' does not exist, insert new.
                if ( empty( $FeatureValueId ) ) {
                    Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_value` (`id_feature_value`,`id_feature`,`custom`) VALUES (0, ' . $FeatureNameId . ', 0)' );
                    $FeatureValueId = Db::getInstance()->Insert_ID();
                    Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_value_lang` (`id_feature_value`,`id_lang`,`value`) VALUES (' . $FeatureValueId . ', ' . Context::getContext()->language->id . ', "' . pSQL( $attributeValue ) . '")' );
                }
                Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_product` (`id_feature`, `id_product`, `id_feature_value`) VALUES (' . $FeatureNameId . ', ' . $product->id . ', ' . $FeatureValueId . ')' );
            }
        }
    
        $shops = Shop::getShops( true, null, true );
        $image = new Image();
        $image->id_product = $product->id;
        $image->position = Image::getHighestPosition( $product->id ) + 1;
        $image->cover = true;
        if ( ( $image->validateFields( false, true ) ) === true && ( $image->validateFieldsLang( false, true ) ) === true && $image->add() ) {
            $image->associateTo( $shops );
            if ( !uploadImage( $product->id, $image->id, $imgUrl ) ) {
                $image->delete();
            }
        }
        echo 'Product added successfully (ID: ' . $product->id . ')';
    }
    
    function uploadImage( $id_entity, $id_image = null, $imgUrl ) {
        $tmpfile = tempnam( _PS_TMP_IMG_DIR_, 'ps_import' );
        $watermark_types = explode( ',', Configuration::get( 'WATERMARK_TYPES' ) );
        $image_obj = new Image( $id_image );
        $path = $image_obj->getPathForCreation();
        $imgUrl = str_replace( ' ', '%20', trim( $imgUrl ) );
        // Evaluate the memory required to resize the image: if it's too much, you can't resize it.
        if ( !ImageManager::checkImageMemoryLimit( $imgUrl ) )
            return false;
        if ( @copy( $imgUrl, $tmpfile ) ) {
            ImageManager::resize( $tmpfile, $path . '.jpg' );
            $images_types = ImageType::getImagesTypes( 'products' );
            foreach ( $images_types as $image_type ) {
                ImageManager::resize( $tmpfile, $path . '-' . stripslashes( $image_type[ 'name' ] ) . '.jpg', $image_type[ 'width' ], $image_type[ 'height' ] );
                if ( in_array( $image_type[ 'id_image_type' ], $watermark_types ) ) {
                    Hook::exec( 'actionWatermark', array( 'id_image' => $id_image, 'id_product' => $id_entity ) );
                }
            }
        } else {
            unlink( $tmpfile );
            return false;
        }
        unlink( $tmpfile );
        return true;
    }
    
    function createMultiLangField( $field ) {
        $res = array();
        foreach ( Language::getIDs( false ) as $id_lang ) {
            $res[ $id_lang ] = $field;
        }
        return $res;
    }