Hello I'm new in magento, I create a PHP script to create categories based in an XML file, the problem is that when I run my script magento is showing the error message
SQLSTATE[HY000] [1226] User 'x' has exceeded the 'max_user_connections' resource (current value: 15)
and also the memory usage is incremented after save the category
I use memory_get_peak_usage() to see that
Inside nodeStringFromXMLFile memory usage38721912
Category ACCESORIOS
Category already exist23
After add category memory usage41928272
Inside nodeStringFromXMLFile memory usage41928272
Category RACK
Category already exist25
After add category memory usage45135720
This is my code
<?php use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem\Io\File; require __DIR__ . '/app/bootstrap.php'; ini_set('max_execution_time', 500); // Open the XML $handle = fopen('./XmlFile/AllCVAProductsOK.xml', 'r'); //fclose($handle); // Get the nodestring incrementally from the xml file by defining a callback // In this case using a anon function. nodeStringFromXMLFile($handle, '<item>', '</item>', function($nodeText){ // Transform the XMLString into an array and //print_r(getArrayFromXMLString($nodeText)); $price=0; $specialPrice=0; $exchangeRate=0; $currency=''; $currencySpecialPrice=''; $item = getArrayFromXMLString(utf8_encode($nodeText)); $producto=json_decode(json_encode($item),FALSE); //Para <grupo> $category=$producto->grupo; echo 'Inside nodeStringFromXMLFile memory usage'.memory_get_peak_usage(); echo '<br>'; echo ' Category '.$category; echo '<br>'; addCategory($category); echo '<br>'; echo 'After add category memory usage'.memory_get_peak_usage(); echo '<br>'; echo '<br>'; $category=NULL; }); fclose($handle); $handle=NULL; /** * For every node that starts with $startNode and ends with $endNode call $callback * with the string as an argument * * Note: Sometimes it returns two nodes instead of a single one, this could easily be * handled by the callback though. This function primary job is to split a large file * into manageable XML nodes. * * the callback will receive one parameter, the XML node(s) as a string * * @param resource $handle - a file handle * @param string $startNode - what is the start node name e.g <item> * @param string $endNode - what is the end node name e.g </item> * @param callable $callback - an anonymous function */ function nodeStringFromXMLFile($handle, $startNode, $endNode, $callback=null) { $cursorPos = 0; while(true) { // Find start position $startPos = getPos($handle, $startNode, $cursorPos); // We reached the end of the file or an error if($startPos === false) { break; } // Find where the node ends $endPos = getPos($handle, $endNode, $startPos) + mb_strlen($endNode); // Jump back to the start position fseek($handle, $startPos); // Read the data $data = fread($handle, ($endPos-$startPos)); // pass the $data into the callback $callback($data); // next iteration starts reading from here $cursorPos = ftell($handle); } } /** * This function will return the first string it could find in a resource that matches the $string. * * By using a $startFrom it recurses and seeks $chunk bytes at a time to avoid reading the * whole file at once. * * @param resource $handle - typically a file handle * @param string $string - what string to search for * @param int $startFrom - strpos to start searching from * @param int $chunk - chunk to read before rereading again * @return int|bool - Will return false if there are EOL or errors */ function getPos($handle, $string, $startFrom=0, $chunk=1024, $prev='') { // Set the file cursor on the startFrom position fseek($handle, $startFrom, SEEK_SET); // Read data $data = fread($handle, $chunk); // Try to find the search $string in this chunk $stringPos = mb_strpos($prev.$data, $string); // We found the string, return the position if($stringPos !== false ) { return $stringPos+$startFrom - mb_strlen($prev); } // We reached the end of the file if(feof($handle)) { return false; } // Recurse to read more data until we find the search $string it or run out of disk return getPos($handle, $string, $chunk+$startFrom, $chunk, $data); } /** * Turn a string version of XML and turn it into an array by using the * SimpleXML * * @param string $nodeAsString - a string representation of a XML node * @return array */ function getArrayFromXMLString($nodeAsString) { $simpleXML = simplexml_load_string($nodeAsString); //$simpleXML = utf8_encode($simpleXML); if(libxml_get_errors()) { user_error('Libxml throws some errors.', implode(',', libxml_get_errors())); } return simplexml2array($simpleXML); } /** * Turns a SimpleXMLElement into an array * * @param SimpleXMLelem $xml * @return array */ function simplexml2array($xml) { if(is_object($xml) && get_class($xml) == 'SimpleXMLElement') { $attributes = $xml->attributes(); foreach($attributes as $k=>$v) { $a[$k] = (string) $v; } $x = $xml; $xml = get_object_vars($xml); } if(is_array($xml)) { if(count($xml) == 0) { return (string) $x; } $r = array(); foreach($xml as $key=>$value) { $r[$key] = simplexml2array($value); } // Ignore attributes if (isset($a)) { $r['@attributes'] = $a; } return $r; } return (string) $xml; } function addCategory($fcategory) { //require __DIR__ . '/app/bootstrap.php'; $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER); $objectManager = $bootstrap->getObjectManager(); $state = $objectManager->get('Magento\Framework\App\State'); $state->setAreaCode('frontend'); ///$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER); //$objectManager = $bootstrap->getObjectManager(); //$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager try { $category = $objectManager->create('Magento\Catalog\Model\Category'); $cate = $category->getCollection()->addAttributeToFilter('name',$fcategory)->getFirstItem(); if (!$cate->getId()) { echo 'Category not exist'; $url = \Magento\Framework\App\ObjectManager::getInstance(); $storeManager = $url->get('\Magento\Store\Model\StoreManagerInterface'); /// Get Store ID $store = $storeManager->getStore(); /*$storeId = $store->getStoreId(); echo " storeId: ".$storeId." ";*/ $cat=$fcategory; //echo " cat:".$cat; $nameCat=ucfirst($cat); //echo " name:".$nameCat; $url=strtolower($cat); //echo " url:".$url; $cleanurl = trim(preg_replace('/ +/', '', preg_replace('/[^A-Za-z0-9 ]/', '', urldecode(html_entity_decode(strip_tags($url)))))); //echo " cleanurl:".$cleanurl; $categoryFactory=$objectManager->get('\Magento\Catalog\Model\CategoryFactory'); /// Get Root Category $rootCat = $objectManager->get('Magento\Catalog\Model\Category'); /// Add a new sub category under root category $categoryTmp = $categoryFactory->create(); $categoryTmp->setName($nameCat); $categoryTmp->setIsActive(true); $categoryTmp->setUrlKey($cleanurl); $categoryTmp->setData('description', $fcategory); $categoryTmp->setParentId($rootCat->getId()); $mediaAttribute = array ('image', 'small_image', 'thumbnail'); //$categoryTmp->setImage('/m2.png', $mediaAttribute, true, false);// Path pub/meida/catalog/category/m2.png $categoryTmp->setStoreId(0); $categoryTmp->setPath(1); $categoryTmp->save(); } else { $IdCat=$cate->getId(); echo "Category already exist".$IdCat; //$product->setCategoryIds($cate->getId()); } $category =NULL; $cate =NULL; $IdCat=NULL; $fcategory=NULL; }catch(Exception $e){ echo <<<HTML <div style="font:12px/1.35em arial, helvetica, sans-serif;"> <div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;"> <h3 style="margin:0;font-size:1.7em;font-weight:normal;text-transform:none;text-align:left;color:#2f2f2f;"> Autoload error</h3> </div> <p>{$e->getMessage()}</p> </div> HTML; exit(1); } } ?>
Hi @jesus fernando_torres hernandez,
It seems your making more database connections at the same time than you can (that is a configuration value on your database server).
Maybe you could use an external PHP scrtips that use Magento 2 API?
Here you'll find the whole list of endpoints: https://devdocs.magento.com/guides/v2.0/rest/list.html#catalog
And here you can explore each one using swagger: https://devdocs.magento.com/swagger/
Hello @jesus fernando_torres hernandez
There is one module fast import
https://github.com/firegento/FireGento_FastSimpleImport2
Documation:http://firegento-fastsimpleimport2.readthedocs.io/en/latest/
Where you need to pass array to import category, can you please try it.
Hope it will help you.
If work then marks as a solution or give kudos.
Hi @jesus fernando_torres hernandez,
If you want to install that module you can use Composer.
You just need to run these commands:
composer require firegento/fastsimpleimport bin/magento module:enable FireGento_FastSimpleImport bin/magento setup:upgrade