Popular Post Crezzur.com Posted September 27, 2020 Popular Post Share Posted September 27, 2020 (edited) Compatible with version: Prestashop 1.7+Tutorial last update: 22/07/2021 Special thanks to following contributor(s): @mfdenis, @Inter Svetainė, @seblyon, @Oelita A while ago i received the question on how to add products programmatically using a PHP file. After looking around in the Prestashop files and searching the worldwide-web i have come up with a working script. I decided to share this code with the Prestashop community. If you have any questions our improvements don't hesitate to ask or say them. The file we are creating can be easily run with a cron-job and is able to fetch data from a page using JSON trough an Ajax call. Lets get started! The first step is creating a new PHP file in your admin folder. Create a new PHP file in the folder yourstore/back-office/FILENAME.php. In our small tutorial we use the filename importmyproduct.php Setting up connection with the config file First we start to check if the global variable _PS_ADMIN_DIR_ is defined. After we check that _PS_ADMIN_DIR_ is defined we will make connection with the prestashop config.inc.php file. So on top of our page we will add following code. <?php // Check if _PS_ADMIN_DIR_ is defined if (!defined('_PS_ADMIN_DIR_')) { // if _PS_ADMIN_DIR_ is not defined, define. define('_PS_ADMIN_DIR_', getcwd()); } // Setup connection with config.inc.php (required for database connection, ...) include(_PS_ADMIN_DIR_.'/../config/config.inc.php'); Adding access security and check if page is setup correctly. Since we do not want that our importmyproduct.php can be easily accessed by strangers we will add a security feature. We will also display our first echo to check if everything is working correctly. After we have setup our secure-key we can visit our PHP page by going to yourstore.com/yourbackoffice/importmyproduct.php?secure_key=yoursecuretoken $secure_key = 'ed3fa1ce558e1c2528cfbaa3f99403'; // Check if the client use the correct secure_key, url to use: www.yourstore.com/yourbackoffice/importmyproduct.php?secure_key=ed3fa1ce558e1c2528cfbaa3f99403 if(!Tools::getValue('secure_key') || Tools::getValue('secure_key') != $secure_key) { // If the secure_key is not set our not equal the php page will stop running. die('UNAUTHORIZED: We dont want you on this page!'); } echo 'Welcome, the secure_key you have used is correct. Now we can start adding product programmatically ... <br>'; Our product import function In this next step we will add our product import function which can be called later on to import a new product. 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(utf8_encode($name)); $product->description = htmlspecialchars($text); $product->id_category_default = $catDef; $product->redirect_type = '301'; $product->price = number_format($price, 6, '.', ''); $product->minimal_quantity = 1; $product->show_price = 1; $product->on_sale = 0; $product->online_only = 0; $product->meta_description = ''; $product->link_rewrite = createMultiLangField(Tools::str2url($name)); // Contribution credits: mfdenis $product->add(); // Submit new product StockAvailable::setQuantity($product->id, null, $qty); // id_product, id_product_attribute, quantity $product->addToCategories($catAll); // After product is submitted insert all categories // 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($FeatureNameId)) { 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 ' . _DB_PREFIX_ . 'feature_value WHERE id_feature_value IN (SELECT id_feature_value FROM `' . _DB_PREFIX_ . '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 . ')'); } } // add product image. $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 . ')'; } We also will need a function to handle our image upload, add below following code: This function will insert the image into your store and assign it to your created product. 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((int)$id_image); $path = $image_obj->getPathForCreation(); $imgUrl = str_replace(' ', '%20', trim($imgUrl)); // Evaluate the memory required to resize the image: if it's too big we 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; } Multi language support. As you can see in the above code we call the function createMultiLangField() This function make sure we add our product to all available languages on your store. Add the following function to your script. function createMultiLangField($field) { $res = array(); foreach (Language::getIDs(false) as $id_lang) { $res[$id_lang] = $field; } return $res; } The last step And after this all we come at our last step, adding our first programmatically created product. This can be done by calling our function addProduct and pass the necessary values. addProduct( '1234567891234', // Product EAN13 'Tutorial by Crezzur', // 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://crezzur.com/img/crezzur-logo-1544601440.jpg', // Product image 1, // Product default category array(1, 5) // All categorys for product (array) ); For the people that don't want to copy paste all the code we have created a file which contains all of the above the full code file can be found here : https://crezzur.com/en/modules/10-script-for-adding-prestashop-17-products-programmatically Using the code above will allow you to mass import products using a Ajax call (JSON) our using a CSV file. We do not add this code since the variables for each web service will be different. Generate Products Packs In PHP For those searching to import product packs with my code can find more information about this in the topic of @jmauclair A like and/or a thank you for my work is much appreciated Edited July 22, 2021 by Crezzur (see edit history) 11 6 Link to comment Share on other sites More sharing options...
hrnsykk Posted May 5, 2021 Share Posted May 5, 2021 Crezzur, It was very useful for me but how to add Customization field to this product. Thank you. Link to comment Share on other sites More sharing options...
Crezzur.com Posted May 5, 2021 Author Share Posted May 5, 2021 hello @hrnsykk Can you explain a bit more what you mean with a Customization field? Link to comment Share on other sites More sharing options...
hrnsykk Posted May 6, 2021 Share Posted May 6, 2021 Crezzur, I mean, the area marked in red in the attached photo. Link to comment Share on other sites More sharing options...
mfdenis Posted May 22, 2021 Share Posted May 22, 2021 (edited) if you use multiple languages, you'll encounter problems displaying images unless you add this line to addProduct() function: $product->link_rewrite = createMultiLangField(Tools::str2url($name)); along with all other $product-> lines. without it images are nicely uploaded and even visible from backend product list, but links to them are corrupted on frontend if seo-friendly urls setting is on. Cost me half of day to figure out. result is hiding in table "_product_lang" column "link_rewrite" and used in urls generation (both for product url and images url), so very unobvious problem. Tools::str2url used here is prestashop built-in tool to convert any language texts to urls. (current PS 1.7.7.4, not sure about earlier or later versions) in all other means - perfect tutorial, very helpful, THANK YOU! Edited May 22, 2021 by mfdenis (see edit history) 1 Link to comment Share on other sites More sharing options...
Crezzur.com Posted May 22, 2021 Author Share Posted May 22, 2021 1 hour ago, mfdenis said: if you use multiple languages, you'll encounter problems displaying images unless you add this line to addProduct() function: $product->link_rewrite = createMultiLangField(Tools::str2url($name)); along with all other $product-> lines. without it images are nicely uploaded and even visible from backend product list, but links to them are corrupted on frontend if seo-friendly urls setting is on. Cost me half of day to figure out. result is hiding in table "_product_lang" column "link_rewrite" and used in urls generation (both for product url and images url), so very unobvious problem. Tools::str2url used here is prestashop built-in tool to convert any language texts to urls. (current PS 1.7.7.4, not sure about earlier or later versions) in all other means - perfect tutorial, very helpful, THANK YOU! Hello @mfdenis Thank you for your contribution! I will look into you suggested update and add it to the code if it is working correctly. I was not aware of this issue with SEO. Kind regards, Jaimy Link to comment Share on other sites More sharing options...
mfdenis Posted May 24, 2021 Share Posted May 24, 2021 Another minor change I'd offer is $product->price = round($price, 6); instead of simple $product->price = $price; because this is price tax excluded and most likely it will be float, which doesn't pass prestashop's FieldValue check. (db value expects decimal with 6 figures after coma, while float in php has much longer 'tail') (probably this depends on store's settings - how it calculates final price - if it stores price tax included or tax excluded in DB. In my case it caused script crash on non-integer values, so I've applied this fix.) yet again - current PS 1.7.7.4, not sure about earlier or later versions 1 Link to comment Share on other sites More sharing options...
Crezzur.com Posted May 24, 2021 Author Share Posted May 24, 2021 8 minutes ago, mfdenis said: Another minor change I'd offer is $product->price = round($price, 6); instead of simple $product->price = $price; because this is price tax excluded and most likely it will be float, which doesn't pass prestashop's FieldValue check. (db value expects decimal with 6 figures after coma, while float in php has much longer 'tail') (probably this depends on store's settings - how it calculates final price - if it stores price tax included or tax excluded in DB. In my case it caused script crash on non-integer values, so I've applied this fix.) yet again - current PS 1.7.7.4, not sure about earlier or later versions Hey @mfdenis thank you for your contributions! For the $product-price part i prefer using the following: $product->price = number_format($price_incl, 6, '.', ''); When using my auto-importer i have noticed that some company's uses a comma instead of a point in there prices, this will then result in a import failure. I did not update this code in this tutorial, so i added this today, thank you for pointing this out! Link to comment Share on other sites More sharing options...
mfdenis Posted May 24, 2021 Share Posted May 24, 2021 3 hours ago, Crezzur said: $product->price = number_format($price_incl, 6, '.', ''); yeah! that's even more fool-proof! Thank you! Link to comment Share on other sites More sharing options...
Inter Svetainė Posted June 9, 2021 Share Posted June 9, 2021 Line $product->price = number_format($price_incl, 6, '.', ''); uses $price_incl, but in arguments is $price. 1 Link to comment Share on other sites More sharing options...
Crezzur.com Posted June 9, 2021 Author Share Posted June 9, 2021 3 minutes ago, Inter Svetainė said: Line $product->price = number_format($price_incl, 6, '.', ''); uses $price_incl, but in arguments is $price. You are correct! Its a copy paste mistake from my side. Thank for points this typo out! 1 Link to comment Share on other sites More sharing options...
mfdenis Posted June 10, 2021 Share Posted June 10, 2021 one more copy-paste mistake is in this part: // 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); where all "webshop_" parts should be replaced with ' . _DB_PREFIX_ . ' I suppose. 1 Link to comment Share on other sites More sharing options...
Crezzur.com Posted June 11, 2021 Author Share Posted June 11, 2021 12 hours ago, mfdenis said: one more copy-paste mistake is in this part: // 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); where all "webshop_" parts should be replaced with ' . _DB_PREFIX_ . ' I suppose. You are correct! Thank for points this out 😉 Link to comment Share on other sites More sharing options...
Inter Svetainė Posted June 11, 2021 Share Posted June 11, 2021 There is no limit to upgrade Your already perfect code for example add (int) into this line $image_obj = new Image($id_image); and it will look like $image_obj = new Image((int)$id_image); to be sure that id of image will be for sure an integer 1 Link to comment Share on other sites More sharing options...
Crezzur.com Posted June 11, 2021 Author Share Posted June 11, 2021 4 hours ago, Inter Svetainė said: There is no limit to upgrade Your already perfect code for example add (int) into this line $image_obj = new Image($id_image); and it will look like $image_obj = new Image((int)$id_image); to be sure that id of image will be for sure an integer Thank you for your contribution, i have added it to the code. Have a nice day! 1 Link to comment Share on other sites More sharing options...
mfdenis Posted June 11, 2021 Share Posted June 11, 2021 8 hours ago, Crezzur said: You are correct! Thank for points this out 😉 Hey @Crezzur, there are TWO mentions of db tables in that long SQL query, I noticed you've fixed only one in code, second is still there 😅 (nonetheless one of the most useful tutorials over whole forum, just can't stop praise it!) Link to comment Share on other sites More sharing options...
Crezzur.com Posted June 11, 2021 Author Share Posted June 11, 2021 (edited) 16 minutes ago, mfdenis said: Hey @Crezzur, there are TWO mentions of db tables in that long SQL query, I noticed you've fixed only one in code, second is still there 😅 (nonetheless one of the most useful tutorials over whole forum, just can't stop praise it!) My mistake! changed now. When I started creating a script for programmatically adding products, I quickly found that little has been written on this subject. You'll find little bits of code all over the prestashop forums that often also contained errors. After a month of searching and testing I finally had a working script. It therefore seemed fairest to me to share it with the community where I was able to find parts of the script. Then I wrote a module (https://crezzur.com/en/prestashop-modules/16-crezzur-dst) with this script that works quickly and without errors. The script has already been tested with an import of more than 10,000 products and has more than proven its effectiveness. I am glad to hear that you enjoy it as much as i do 😉 Edited June 11, 2021 by Crezzur (see edit history) Link to comment Share on other sites More sharing options...
Crezzur.com Posted June 14, 2021 Author Share Posted June 14, 2021 Update 14/06/2021: Added utf8_encode() to prevent characters like ö, à, ï to be replaced by question marks. OLD CODE: $product->name = createMultiLangField($name); NEW CODE: $product->name = createMultiLangField(utf8_encode($name)); Link to comment Share on other sites More sharing options...
seblyon Posted June 17, 2021 Share Posted June 17, 2021 Hi guys, First, thank you for your really cool scrypt ! 1 ) here is a solution for a problem , i encounter on stock. (after a lot of research) this line is not working on my prestashop (1.7.7), stock is always 0 : $product->quantity = $qty; you need to set stock like this after adding product StockAvailable::setQuantity($product->id, null, $qty); 2) i have a problem with image : upload works fine, in Admin the image is set cover no problem. But on front , image is not displaying (empty/broken) when i go on my product admin file and validate it .... front product file is working. Have you any idear what is missing ? thank you !! 2 Link to comment Share on other sites More sharing options...
Crezzur.com Posted June 17, 2021 Author Share Posted June 17, 2021 45 minutes ago, seblyon said: Hi guys, i have a problem with image : <upload works fine, in Admin the image is set cover no problem. But on front , image is not displaying (empty/broken) when i go on my product admin file and validate it .... front product file is working. Have you any idear what is missing ? First of all, thank you for your contribution! I have checked and confirmed that this was an issue. We have updated our tutorial with your suggestions which is working fine. For you image problems lets try to trouble shout the issue. Normally there are no issues with the importer (checked and still working) Can you add this code: $img = $product->getCover($product->id); echo 'Product IMAGE: ' . Context::getContext()->link->getImageLink($product->link_rewrite[1], $img['id_image']); under the line: echo 'Product added successfully (ID: ' . $product->id . ')'; Now you will receive the image url, does this url work correctly? Link to comment Share on other sites More sharing options...
Crezzur.com Posted July 8, 2021 Author Share Posted July 8, 2021 For the people who want to add product packages with my script, check this topic: Link to comment Share on other sites More sharing options...
Oelita Posted July 20, 2021 Share Posted July 20, 2021 Hi, I met what I think is an error, in the features code : // 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)) { As it is, it duplicates the existing features. That should be (change on last line) : // 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($FeatureNameId )) { Thanks a lot for your code ! 1 Link to comment Share on other sites More sharing options...
Crezzur.com Posted July 22, 2021 Author Share Posted July 22, 2021 @Oelita You are correct, it needs to be if (empty($FeatureNameId )) {, ill change it now. Thank you for your contribution 😉 Link to comment Share on other sites More sharing options...
Alicebfeskjfghj Posted January 21, 2022 Share Posted January 21, 2022 Hello, Thank you a lot for this ! I would like to add a file in FTP (like the import file for example) so that it could automatically import the products. In the step 7 you add a product manually. Is it possible to make it call a file directly ? Thank you ! :-) Link to comment Share on other sites More sharing options...
orotoi Posted February 11, 2022 Share Posted February 11, 2022 Hi there and thanks for the so usefull script! It's one of the more core features but it was still lacking of info around the forums.. One question in case you have something in mind is how to modify so it can be used for product with combinations.. Does anyone has done something similar? Link to comment Share on other sites More sharing options...
orotoi Posted February 11, 2022 Share Posted February 11, 2022 (edited) On 1/21/2022 at 1:31 PM, Alicebfeskjfghj said: Hello, Thank you a lot for this ! I would like to add a file in FTP (like the import file for example) so that it could automatically import the products. In the step 7 you add a product manually. Is it possible to make it call a file directly ? Thank you ! 🙂 You can read your .csv file and then within a loop use the addProduct function Edited February 11, 2022 by orotoi (see edit history) Link to comment Share on other sites More sharing options...
mfdenis Posted February 11, 2022 Share Posted February 11, 2022 1 hour ago, orotoi said: Hi there and thanks for the so usefull script! It's one of the more core features but it was still lacking of info around the forums.. One question in case you have something in mind is how to modify so it can be used for product with combinations.. Does anyone has done something similar? just a portion of my code to give you some idea where to look for (don't expect this code to work out of the box, it requires you to set up Attributes Group and to know its ID): // look for $id_attribute_group in your Prestashop BO $attributes = AttributeGroup::getAttributes(1, $id_attribute_group); $product = new Product($product_id); foreach ($attributes as $attribute) { if (!$first_run) { $set_as_default = 1; } else { $set_as_default = 0; } // calculate your $calculated_price $idProductAttribute = $product->addCombinationEntity( 0, //$wholesale_price $calculated_price, 0, //$weight 0, //$unit_impact 0, //$ecotax 0, //$quantity '', //$id_images '', //$reference '', //$id_supplier '', //$ean13 $set_as_default //$default ); Db::getInstance()->execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'product_attribute_combination (id_attribute, id_product_attribute) VALUES (' . (int) $attribute["id_attribute"] . ',' . (int) $idProductAttribute . ')', false); $first_run = true; // not the most elegant solution, but just works for me } 1 Link to comment Share on other sites More sharing options...
Alicebfeskjfghj Posted March 2, 2022 Share Posted March 2, 2022 Hello, I didn't understand how to make the ajax call. Is there a tutorial ? Thanks ! Link to comment Share on other sites More sharing options...
FranAyala Posted May 24, 2022 Share Posted May 24, 2022 On 5/6/2021 at 8:39 AM, hrnsykk said: Crezzur, I mean, the area marked in red in the attached photo. Hi all Anyone can add this feature to the script? Insert a new product with customizable fields. Thanks! Link to comment Share on other sites More sharing options...
Inter Svetainė Posted June 17, 2022 Share Posted June 17, 2022 (edited) I also offer to change first step (where config file is included). If "add-product-file.php" will be created not in root/public_html then this will not work. <?php // Check if _PS_ADMIN_DIR_ is defined if (!defined('_PS_ADMIN_DIR_')) { // if _PS_ADMIN_DIR_ is not defined, define. define('_PS_ADMIN_DIR_', getcwd()); } // Setup connection with config.inc.php (required for database connection, ...) include(_PS_ADMIN_DIR_.'/../config/config.inc.php'); cause getcwd(); returns current folder of file, not root. For example if I create "add-product-file.php" in public_html/manual-code/add-item/add-product-file.php. So getcwd() returns public_html/manual-code/add-item. Defined _PS_ADMIN_DIR_ value will be wrong. Later on including _PS_ADMIN_DIR_ .'/../config/config.inc.php' will throw error. Full path to file becomes "public_html/manual-code/config/config.inc.php". Which, of course, is wrong. I suggest to not rely on/don't use getcwd(). Instead use "$_SERVER['DOCUMENT_ROOT']". Full code snippet would be <?php // Check if _PUBLIC_HTML_DIR_ is defined if (!defined('_PUBLIC_HTML_DIR_')) { // if _PUBLIC_HTML_DIR_ is not defined, define. define('_PUBLIC_HTML_DIR_', $_SERVER['DOCUMENT_ROOT']); } // Setup connection with config.inc.php (required for database connection, ...) include(_PUBLIC_HTML_DIR_.'/config/config.inc.php'); So does not matter where custom add item code will be placed it will always will be using root project dir/public_html dir to start looking for core files. Please note I changed const name. Edited June 17, 2022 by Inter Svetainė added not of changed const name (see edit history) Link to comment Share on other sites More sharing options...
mfdenis Posted June 17, 2022 Share Posted June 17, 2022 1 hour ago, Inter Svetainė said: I suggest to not rely on/don't use getcwd(). Instead use "$_SERVER['DOCUMENT_ROOT']". Why not use php built-in __DIR__ magic constant? https://www.php.net/manual/en/language.constants.magic.php Link to comment Share on other sites More sharing options...
Michael Shelest Posted July 3, 2022 Share Posted July 3, 2022 The code is great and does the work but wanted to suggest another usefull tip: Search::indexation(false, $productId); This code will help to do reindex in the end because after programmatical creation the product search was not working for me (even after manual reindex in the admin panel) Thanks, Michael 1 Link to comment Share on other sites More sharing options...
Inter Svetainė Posted July 3, 2022 Share Posted July 3, 2022 On 6/17/2022 at 2:04 PM, mfdenis said: Why not use php built-in __DIR__ magic constant? https://www.php.net/manual/en/language.constants.magic.php Yes, we can 😊 Just because I used $_SERVER data upper in my code I used it in example. Link to comment Share on other sites More sharing options...
Cezar Lacatus Posted July 14, 2022 Share Posted July 14, 2022 How do you add more images using this piece of code? Thank you. Link to comment Share on other sites More sharing options...
Inter Svetainė Posted October 17, 2022 Share Posted October 17, 2022 (edited) On 7/15/2022 at 12:31 AM, Cezar Lacatus said: How do you add more images using this piece of code? Thank you. You can try something like this: function addImageToPresta($idProduct, $urlToImage) { $absoluteUrlToImg = Context::getContext()->shop->getBaseURL(true) . $urlToImage; $absoluteUrlToImg = preg_replace("/^https:/i", "http:", $absoluteUrlToImg); $image = new Image(); $image->id_product = $idProduct; $image->position = Image::getHighestPosition($idProduct) + 1; if (strpos($urlToImage, '_cover') !== false) { $image->cover = true; } else { $image->cover = false; } $image->add(); } Edited October 17, 2022 by Inter Svetainė (see edit history) Link to comment Share on other sites More sharing options...
Bonza Views Posted October 18, 2022 Share Posted October 18, 2022 (edited) This thread is fantasic, thanks to everyone who contributed. Does anyone know how to add "Attached files" to a product with PHP? Edited October 18, 2022 by Bonza Views (see edit history) Link to comment Share on other sites More sharing options...
Michael Shelest Posted October 18, 2022 Share Posted October 18, 2022 1 hour ago, Bonza Views said: This thread is fantasic, thanks to everyone who contributed. Does anyone know how to add "Attached files" to a product with PHP? I use the following code where $attachmentsArray is just comma-separated URLs of my PDF files for each product: $attachmentsArray = explode(',', $attachmentsUrls); $i = 0; foreach ($attachmentsArray as $attachmentPath) { $i++; $number = ''; if($i > 1) { $number = '_' . $i; } $fileName = 'Rules_'.$ref.$number.'.pdf'; try { $arrContextOptions=array( "ssl"=>array( "verify_peer"=>false, "verify_peer_name"=>false, ), ); copy($attachmentPath, _PS_DOWNLOAD_DIR_ . $fileName, stream_context_create($arrContextOptions)); }catch (Exception $exception){ echo $exception->getMessage() . '<br>'; continue; } $attachment = new Attachment(); $attachment->file = $fileName; $attachment->mime = 'application/pdf'; $attachment->file_name = $fileName; // Create name and description for each language $languages = Language::getLanguages(false); foreach ($languages as $language) { $attachment->name[(int)$language['id_lang']] = $fileName; $attachment->description[(int)$language['id_lang']] = ''; } // Put to DB $attachment->add(); // Attach to product $attachment->attachProduct($product->id); } 1 Link to comment Share on other sites More sharing options...
Inter Svetainė Posted March 9, 2023 Share Posted March 9, 2023 10 hours ago, aydam2728 said: PrestaShop version : 8.0.1 Hi all, The Crezzur code working partly. The product is created but is not appear in the category page. But I see him in the new products page, and it is in the products sheet. To show him in the category page, I need to save the product (gui) without any change. Then the miracle happens, the product appears. Do you have any idea to fix that ? Thanks in advance Please create another product/item with this script and inspect database tables such as `ps_category_product` do item is added into this table. And etc... Just more info is needed. Link to comment Share on other sites More sharing options...
Inter Svetainė Posted March 10, 2023 Share Posted March 10, 2023 19 hours ago, aydam2728 said: Thanks for your response. I was very focused on the problem without double-check the new object Crezzur with wrong category id in my case. it's my fault, sorry for the disagreement Everything is fine. Write here again if something does not work with the product creation programmatically. Link to comment Share on other sites More sharing options...
Fer Poblete Posted July 25, 2023 Share Posted July 25, 2023 Hi @Crezzur.com and thanks for your code, is has been very helpful. Is there a reason why you are creating the features and feature values using SQL instead of using the Feature and FeatureValue model classes? Link to comment Share on other sites More sharing options...
mfdenis Posted August 10, 2023 Share Posted August 10, 2023 (edited) @Fer Poblete I know you asked not me, but just in case: yeah, there are model classes Feature and FeatureValue, but there are no methods in those classes which would do simple job like Feature::addFeatureToProduct($product_id, $feature_id, $feature_value_id) to create necessary relation between product, feature and feature value. So the simplest way was just do it directly via DB/sql. If you have good proposal - just put your code here, contributions are always welcome! (probably, good starting point would be Product->addFeatureProductImport) (which also consists of single SQL query 😅) Edited August 10, 2023 by mfdenis additions (see edit history) Link to comment Share on other sites More sharing options...
Daniele Esposito Posted January 25 Share Posted January 25 Hello everyone, and congratulations on this fantastic thread. I just have a couple of doubts regarding two things: 1. With this script, I add products automatically, but what happens if I want to only update the quantity of an existing product? 2. What if I want to add different sizes and colors for the product along with their respective availability? For example: White T-shirt - qty 10 - price €20; Black T-shirt - qty 5 - price €20 Link to comment Share on other sites More sharing options...
mfdenis Posted January 26 Share Posted January 26 On 1/25/2024 at 2:17 PM, Daniele Esposito said: what happens if I want to only update the quantity of an existing product? on old versions (like 1.6..1.7) you'd just make something like: $my_product = new Product($id); // $id is id number of product to update $my_product->quantity = $quantity; // $quantity is your desired quantity to set for this product $my_product->save; but product->quantity property was deprecated since version 8 or a but earlier, so, you should use StockAvailable: StockAvailable::setQuantity( $product->id, // id of product null, // this is for attributes (int)$quantity // desired quantity ); But I'd recommend to read this part of documentation first:https://docs.prestashop-project.org/v.8-documentation/user-guide/selling/managing-catalog/managing-stock/stock-overviewhttps://docs.prestashop-project.org/v.8-documentation/user-guide/selling/managing-catalog/managing-stock/stock-movements Because it became overcomplicated now.. Link to comment Share on other sites More sharing options...
mfdenis Posted January 26 Share Posted January 26 On 1/25/2024 at 2:17 PM, Daniele Esposito said: What if I want to add different sizes and colors for the product along with their respective availability? First you have to create all these attributes. (probably, manually) Then when you should apply required attributes to product (suspect that this is also better perform manually, it's called "combinations") Then when every product's combination has its own reference number, you can easily update them like: $comb_product = new Product($id); $combinations = $comb_product->getAttributeCombinations(); foreach ($combinations as $combination) { if ($combination['reference'] == $your_reference_for_this_combination) { $current_comb = new Combination($combination["id_product_attribute"]); // updating price of specific combination $current_comb->price = $your_price_of_this_combination; $current_comb->save(); // updating stock of specific combination StockAvailable::setQuantity( $id, $combination["id_product_attribute"], $quantity ); } } This is just some guide code, you should set your reference number and price and test it. 1 Link to comment Share on other sites More sharing options...
Daniele Esposito Posted January 26 Share Posted January 26 Thank you for the response. This integration with the code is very interesting, but it seems we are assuming that we precisely know both the references of the various product combinations and the product ID, which in most cases does not reflect reality. The most realistic use case, or at least the one I am dealing with, is as follows: Integration with a corporate ERP: The products are exported in CSV format from the management system and sent to a directory on the website. This CSV file will be one for the parent products, which we'll call product.csv, and another will be combinations.csv. The first file will definitely have a unique reference, for example: A0GCTG00, which cannot be the ID that PrestaShop has assigned to the product upon its first upload, as the two systems are different. Therefore, the e-commerce products will be identified by the reference code, and that must be used to retrieve the product. As for the size and color combinations in the combitions.csv file, there will definitely be the reference of the product A0GCTG00, and it will have as many rows as the color and size variants and quantities that the ERP system tells me, for example: A0GCTG00, Navy, 38, 10 pieces; A0GCTG00, Navy, 40, 5 pieces, and so on. I believe that surely someone must have had experience with this use case, or at least I think it is the most common one. In this case, how do you think it should be approached? Link to comment Share on other sites More sharing options...
mfdenis Posted January 26 Share Posted January 26 (edited) 10 minutes ago, Daniele Esposito said: but it seems we are assuming that we precisely know both the references of the various product combinations and the product ID, which in most cases does not reflect reality. yep, that's why real reference number is always stored in product->reference property. Same about combinations. Each combination has exactly one reference number, which is the same that you have in your ERP. The rest is simple techniques to get data from cvs and save data to prestashop. (to get product ID from its reference, use Product::getIdByReference() static method..) Edited January 26 by mfdenis (see edit history) Link to comment Share on other sites More sharing options...
mfdenis Posted January 26 Share Posted January 26 11 minutes ago, Daniele Esposito said: As for the size and color combinations in the combitions.csv file, there will definitely be the reference of the product A0GCTG00, and it will have as many rows as the color and size variants and quantities that the ERP system tells me, for example: A0GCTG00, Navy, 38, 10 pieces; A0GCTG00, Navy, 40, 5 pieces, and so on. Didn't you studied your ERP data structure yet? I think, that's the good point to start from. Then your "will definitely be" going to become "I have following data ...., and here is the problem:...." which would be more realistic to solve 😉 Link to comment Share on other sites More sharing options...
Daniele Esposito Posted January 26 Share Posted January 26 1 minute ago, mfdenis said: Didn't you studied your ERP data structure yet? I think, that's the good point to start from. Then your "will definitely be" going to become "I have following data ...., and here is the problem:...." which would be more realistic to solve 😉 Thank you for your response. My "will definitely be" was meant to generalize my discussion. The real problem is that I do not have a precise reference to the product combination, or at least I find myself in a situation where the only information exported by the management system is the product reference to which this combination is connected, without a unique key for that combination. At this point, therefore, things evolve into two possible solutions, but I have a question. Let's start with the question: Is it possible to assign a reference code to a product combination just as it is done with products? In this case, would it also be possible to directly retrieve the size and color combination from the reference code? Now let's consider what the two solutions might be: For each retrieved product, at each update, all combinations should be deleted and created again with all those available, as without a reference code of the combination itself, it is not possible to query and update it only. Having the reference code of the product combination, I believe everything becomes easier. Assuming that there is a method to directly query the combination through a unique code, or simply using the above-mentioned code and checking the reference code within the foreach. Another question arises: if the main product to which the combinations are linked has pre-selected one of the combinations as the default, is it also possible to update this information? As it might happen that the one previously selected is no longer available. Link to comment Share on other sites More sharing options...
mfdenis Posted January 26 Share Posted January 26 @Daniele Esposito Did you even installed any Prestashop? Did you open backend? Did you open sample products with combinations? Just start there, and read my posts above, because there are all answers to your questions, like: 5 minutes ago, Daniele Esposito said: I have a question. Let's start with the question: Is it possible to assign a reference code to a product combination just as it is done with products? 3 hours ago, mfdenis said: Then when every product's combination has its own reference number, you can easily update them like: Link to comment Share on other sites More sharing options...
Daniele Esposito Posted January 26 Share Posted January 26 58 minutes ago, mfdenis said: @Daniele Esposito Did you even installed any Prestashop? Did you open backend? Did you open sample products with combinations? Just start there, and read my posts above, because there are all answers to your questions, like: Ok, thank you very much. I apologize for the repetitions, but I was simply trying to clarify and take note of your advice. I hope these comments can help others to clarify everything. 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