0

I'm using a a php function to update quantites, prices etcc on my Wordpress website daily.

here's the function :

<?php

use Automattic\WooCommerce\Client;
function UpdateStock()
{
    require __DIR__ . '/vendor/autoload.php';
    
    set_time_limit(10000); //temps limite d'éxecution du code
    
    $filename = "path to csv file on a ftp"; //chemin vers le fichier csv du serveur ftp
   
    $handle = fopen($filename, "r");
    while (!feof($handle)) {
        $ligne[] = fgetcsv($handle, ',');

    }
  
    fclose($handle);
    $woocommerce = new Client(
    
        // Your store URL
      // Your consumer key
       // Your consumer secret
        [
            'wp_api' => true, // Enable the WP REST API integration
            'version' => 'wc/v3', // WooCommerce WP REST API version
            'query_string_auth' => true,
            'verify_ssl' => false
        ]
    );
     for ($item = 1; $item < count($ligne); $item++) {
        $cell = $ligne[$item];
         if ($cell[13] == "0") {       //change la valeur 0 en outofstock
            $statue = "outofstock";
        } elseif ($cell[13] == "1") {
            $statue = "instock";
        } elseif ($cell[13] == "backorder") {
            $statue = "onbackorder";
        } else {
            $statue = "outofstock";
        }


     if ($cell[1] == "simple") { // vérifie si le produit est un produit simple

            $data = [ //récupère les données descriptions, stoc_status, short description
                "description" => $cell[7],
                "name" => $cell[3],
                "stock_status" => $statue,
                "Short description" => $cell[8],
                "regular_price" => $cell[25],
                "sale_price" => $cell[24]
            
            ];
            try {
                $woocommerce->put('products/' . $cell[0], $data); // ajoute les données récupérées au produits
            } catch (Exception $e) {//si les infos n'ont pas été importés, affiche le message d'erreur
                echo 'une erreur est survenue à l article ' . $cell[0] . '</br>'; 
            }


        } else {
            $data = [
                "description" => $cell[7],
                "name" => $cell[3],
                "stock_status" => $statue,
                "regular_price" => $cell[25],
                "sale_price" => $cell[24]
            ];
            $path = 'products/' . $cell[43]. '/variations/'.$cell[0];
            echo $path;
            try {
                $woocommerce->put($path, $data);

            } catch (Exception $e) {
                echo 'une erreur est survenue à l article ' . $cell[0] . '</br>';
            }

        }
        
    }

}
?>

I'm using PHP Cron status to check if the function is executed but it always end up in a 5 min execution timeout and an 'Incomplete' status on PHP Cron Status. Also, I've set max memory allocated to 2048Mb because I had errors logs about not having enough memory.

Is there any way to get this working or to have more details on errors ? Thanks

MaxM
  • 45
  • 8
  • Maybe you just have too many lines in the file you are reading. Try to read and push to woocommerce line by line, e.g. don't save everything into the `ligne` for the whole time. – ozahorulia Dec 08 '21 at 15:37
  • Well the csv file has 30k lines so maybe that's the reason? – MaxM Dec 08 '21 at 15:39
  • Please see whether the reason(s) mentioned in this post are related to your case : [link](https://stackoverflow.com/questions/15115435/set-time-limit-does-not-work) – Ken Lee Dec 08 '21 at 15:41
  • My max_execution_time is set to 0 ... however i defined it to 1000 in wp-config.php Shouldn't the function exit instantly? – MaxM Dec 08 '21 at 15:49

1 Answers1

0

It's almost certainly a memory problem. Check the size of your excel file and see how much memory it might consume (and remember that php array requires much more memory than a CSV file for the same data set). You are looping through a very heave array (~2GB according to your memory limit) which makes execution very slow. Process one csv line at a time, so you don't have to keep all data in php memory all the time.

function updateStock()
{
    $filename = "path to csv file on a ftp"; //chemin vers le fichier csv du serveur ftp

    $woocommerce = new Client(
        [
            'wp_api' => true, // Enable the WP REST API integration
            'version' => 'wc/v3', // WooCommerce WP REST API version
            'query_string_auth' => true,
            'verify_ssl' => false
        ]
    );

    $handle = fopen($filename, "r");
    while (!feof($handle)) {
        $item = fgetcsv($handle, ',');
        processItem($woocommerce, $item);
        unset($item); // sometime php gc doesn't work properly, so it's better to explicitly free memory for heavy variables. 
    }

    fclose($handle);
}

function processItem(Client woocommerce, array $cell)
{
    if ($cell[13] == "0") {       //change la valeur 0 en outofstock
        $statue = "outofstock";
    } elseif ($cell[13] == "1") {
        $statue = "instock";
    } elseif ($cell[13] == "backorder") {
        $statue = "onbackorder";
    } else {
        $statue = "outofstock";
    }

    // ... the rest of your code here
}

By the way, why are you requiring autoload inside a function? It looks very strange.

ozahorulia
  • 9,798
  • 8
  • 48
  • 72
  • Thanks for answering, i tried your method, for some reason it doesn't work without autoload. I just launched the modified function but it still times out. I saw in PHP custom settings plugin that my max_execution_time is set to 0, is that related ? This function was created by another guy who left so some things are a bit obscure to me. – MaxM Dec 08 '21 at 16:29
  • Please measure how much time it takes to send request to woocommerce – ozahorulia Dec 08 '21 at 16:31
  • I'm sorry, I'm pretty new to wordpress so I have no clue how to measure that. I did a ping woocommerce.com in console and got 20ms average – MaxM Dec 08 '21 at 16:53
  • I don't know how do you exactly run the command but the goal is to put calls to woocommerce (for example your `$woocommerce->put`) between `$start = microtime(true);` and `$timeElapsed = microtime(true) - $start;` and then somehow print/save this value. Of course call `die();` right after the measurement code so it will not stuck again (just wait for a single api call). – ozahorulia Dec 08 '21 at 19:02
  • I run it in wordpress events. Thanks, I'll try that and let you know – MaxM Dec 09 '21 at 14:52
  • Ok so it's not display ping or i couldn't find it... On another hand, would that be related to the php array max size ? I've nerver worked with that big arrays so I'm not sure.. – MaxM Dec 10 '21 at 13:18