What is the correct way to use flush(); and Sleep(); in a foreach?

Asked

Viewed 213 times

1

I made a page in php to generate a sales report in the format . csv through Woocommerce on the Wordpress system.

<?php 
//incluir as funções principais do WordPress
require("/home/site/public_html/wp-blog-header.php");
require_once("/home/site/public_html/wp-config.php");
require_once("/home/site/public_html/wp-includes/wp-db.php");
?>

<?php
$order_statuses = array( 'wc-completed');

$customer_orders = wc_get_orders( array (
    'date_completed' => '2020-09-14...2020-09-15',
    'meta_key' => '_customer_user',
    'post_status' => $order_statuses,
    'orderby' => 'date',
    'order' => 'ASC',
    'numberposts' => -1,
) );
$myfile1 = fopen("/home/site/public_html/shop/report/2020.csv", "w") or die("Erro ao abrir relatório!<br>");
fwrite($myfile1, "\"Data\",\"Pedido\",\"Item\",\"Categoria\",\"Quant.\",\"Valor\",\"Pagamento\",\"Usuário\"\r");
echo '<table><tbody>
        <tr>
            <th><strong>Data</strong></th>
            <th><strong>Pedido</strong></th>
            <th><strong>Item</strong></th>
            <th><strong>Categoria</strong></th>
            <th><strong>Quant.</strong></th>
            <th><strong>Valor</strong></th>
            <th><strong>Pagamento</strong></th>
            <th><strong>Usuário</strong></th>
            </tr>';

foreach($customer_orders as $order ){

    $order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;

    foreach($order->get_items() as $item_id => $item){

    $product_id = method_exists( $item, 'get_product_id' ) ? $item->get_product_id() : $item['product_id'];

    if( method_exists( $item, 'get_data' ) ) {
         $item_data = $item->get_data();
         $pedido = $item_data['order_id'];
         $item_name = $item->get_name();
         $produto = $item_data['product_id'];
         $quantity = $item_data['quantity'];
         $total = $item_data['total'];
         $total=str_replace(".", ",", $total);
         $pgto=$order->payment_method_title;
         $order_date_modified=$order->date_completed;
         $data=date_format($order_date_modified, "d/m/Y H:i:s");
         $userid=$order->customer_user;
         $user_info = get_userdata($order->user_id);
         $usuario = $user_info->user_login;
         //$email=$order->billing_email;
    } else {
         $total = wc_get_order_item_meta( $item_id, '_line_total', true );
    }

        foreach( wp_get_post_terms( $produto, 'product_cat' ) as $term ){
            if( $term ){
                $categoria = $term->name;
            }
        }
        
        echo '<tr><td>'.$data.'</td>';
        echo '<td>#'.$pedido.'</td>';
        echo '<td>'.$item_name.'</td>';
        echo '<td>'.$categoria.'</td>';
        echo '<td>'.$quantity.'</td>';
        echo '<td>'.$total.'</td>';
        echo '<td>'.$pgto.'</td>';
        echo '<td>'.$usuario.'</td>';
        
        fwrite($myfile1,"\"$data\",\"$pedido\",\"$item_name\",\"$categoria\",\"$quantity\",\"$total\",\"$pgto\",\"$usuario\"\r");
        
        flush();
        sleep(1);
    
    }
}

fclose($myfile1);
echo '</tbody></table>';
?>

I added the flush(); and Sleep(1); after recording each line in the . csv file, as I want the table to be created in the browser page, as in the example below. where a line appears every second:

<?php

    for($i=1;$i<=10;$i++){
        echo 'processing...<br>';
        flush();
        sleep(1);
    }
?>

But the page I created processes all the information at once and not slowly as expected.

I am looking for alternatives to record data without receiving an error from timeout, because when we run the script to pull all requests this year the process is simply stopped, sometimes it shows a timeout message in the browser, but does not generate any error log.

  • How it gives timeout error if the process is stopped without error?

  • @Woss explained me wrong in the last paragraph, sometimes shows a timeout message in the browser, but does not generate any error log.

  • What is the maximum time to give timeout that is configured on the server?

  • @Woss in php.ini is like 'max_execution_time = 5000000', yet the message "Request Timeout" appears after 2 minutes of execution

1 answer

2


In theory your script could work, but in the php manual it explains that many servers do not send the page until all the script has been completed, even if you buffer part of the code.

The explanation is on this link: manual flush

One solution for this would be to use ajax to load parts of the screen every second, or to load the entire screen with mostly hidden and go displaying with javascript (display:None => display:block) gradually. Particularly I would choose the second option.

  • I read some articles to learn how to use ajax, but I couldn’t understand how it worked and I couldn’t apply it to my current script. About gradually showing the result on the screen, it is not important, in the end I will end up working only with the . csv file created. I will continue looking for more information on ajax to try to apply here, thanks in advance.

  • what helps a lot is the jquery library that makes working with ajax a lot easier

  • thanks for the information, I have not yet achieved something 100%, on the server has something interrupting the execution of the page with 120 seconds only when I include the wordpress configuration files

  • If you keep using the flush to dump buffer every 1 second you end up reaching the page run time limit. You can use the set_time_limit() function to modify the time, but I still don’t think this is the best solution. Ideally check from time to time with ajax and use javascript appped() to add new fields

Browser other questions tagged

You are not signed in. Login or sign up in order to post.