cancel
Showing results for 
Search instead for 
Did you mean: 

Magento is connecting every time I create a category

Magento is connecting every time I create a category

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

?>
4 REPLIES

Re: Magento is connecting every time I create a category

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/

--
If you've found one of my answers useful, please give "Kudos" or "Accept as Solution"

Re: Magento is connecting every time I create a category

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.

 

 

Re: Magento is connecting every time I create a category

Thanks, I only have a doubt how should I install this module in my host ,
I'm using hostinger

Re: Magento is connecting every time I create a category

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
--
If you've found one of my answers useful, please give "Kudos" or "Accept as Solution"