get_posts / WP_Query Tamanho da memória de 134217728 bytes esgotados

4

Eu quero obter todos os IDs de postagens das minhas páginas de produtos. Mas o primeiro ou o segundo caminho são bem sucedidos ...

Eu sempre recebo:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 8388616 bytes) in /var/www/vhosts/httpdocs/wp-includes/wp-db.php on line 1842

Primeira maneira:

if ( ! defined('ABSPATH') ) {
    /** Set up WordPress environment */
    require_once( dirname( __FILE__ ) . '/wp-load.php' );
}

$posts_array = get_posts(array(
            'post_type' => 'product',
            'posts_per_page' => -1
        ));

$myfile = fopen("wp_all_import.txt", "a");

foreach ($posts_array as $value) {
    fwrite($myfile, $posts_array . "\n");
}

fclose($myfile);

Segunda via:

if ( ! defined('ABSPATH') ) {
    /** Set up WordPress environment */
    require_once( dirname( __FILE__ ) . '/wp-load.php' );
}

$products_IDs = new WP_Query( array(
            'post_type' => 'product',
            'posts_per_page' => -1
        ));
$myfile = fopen("wp_all_import.txt", "a");

while ($products_IDs->have_posts() ) : $products_IDs->the_post();
fwrite($myfile, get_the_ID() . "\n");
endwhile; wp_reset_query();

fclose($myfile);

Alguém sabe onde está minha falha e como posso consertar isso? Eu só quero obter todos os IDs dos meus posts de produtos.

Saudações e obrigado!

    
por Jan 05.03.2017 / 13:23

1 resposta

4
  1. Se tudo o que você deseja é imprimir um ID em um arquivo, você pode escrever uma consulta personalizada para ele. Dessa forma, você poderá evitar alguns processamentos internos que o WordPress faz.

  2. Muitas mensagens podem esgotar sua memória RAM, embora eu não ache que apenas selecionar ID de 2100 posts realmente deva consumir 134MB de RAM. Basta fazer as contas, ID pode ser salvo em apenas 1 byte, mas digamos que ele está tomando 4 bytes. Ainda, 2100 x 4 = 8400 bytes = 8,4 KB. Obviamente, o PHP precisa de mais memória interna para processar, criar objetos etc. Mas, com 134 MB de memória, eu poderia facilmente processar algumas centenas de milhares de IDs. Então, obviamente, você está fazendo errado em outro lugar.

De qualquer forma, por qualquer motivo (pode ser que você precise selecionar tudo de product , não apenas ID), você pode segmentar a consulta com limites. Como o seguinte CÓDIGO:

if ( ! defined('ABSPATH') ) {
    /** Set up WordPress environment */
    require_once( dirname( __FILE__ ) . '/wp-load.php' );
}
// $limit determines how many rows you want to handle at any given time
// increase / decrease this limit to see how much your server can handle at a time 
$limit = 100;
$start = 0;

// open file handle
$myfile = fopen( dirname( __FILE__ ) . '/wp_all_import.txt', 'a' );

$qry = "SELECT ID FROM '$wpdb->posts' where post_type='post' AND post_status='publish' limit %d, %d";
while( $result = $wpdb->get_results( $wpdb->prepare( $qry, array( $start, $limit ) ) ) ) {
    $write_data = '';
    foreach ( $result as $row ) {
        $write_data = $write_data . $row->ID . "\n";
    }
    // Generally speaking, writing immidiately to the file is better than
    // string concatination, because depending on what you concat and how many times,
    // the generated string may become too big (like MB size string).
    // On the other hand, writing to files thousands of times in a single script may
    // cause I/O delays. So, here I've done a combination of the two to keep both
    // string size & I/O within limits.
    // Adjust this according to your own situation.
    fwrite( $myfile, $write_data );
    $start = $start + $limit;
}

// close file handle
fclose( $myfile );

Desta forma, o PHP só irá lidar com o número máximo de $limit de linhas, portanto, o limite de memória não deve ser ultrapassado.

  

Nota: nunca concatene para fazer strings muito longas (como MB long), escreva imediatamente no arquivo antes que ele se torne muito longo. Pode produzir algum atraso de E / S, mas não esgotará o limite de memória.

    
por Fayaz 05.03.2017 / 15:02