Avatar billede Morten Professor
08. april 2021 - 13:20 Der er 12 kommentarer og
1 løsning

hmm min loop bliver ved i en uendlighed min xml fil bliver skrevet om igen og igen

Hej

Jeg har nogle problemer med at min loop til at ende.
Når den når de antal produkter der er skal den stoppe men det gør den ikke.

Vil i se om i kan se hvad der kan være galt.

<?php
global $wpdb;
$xml = new XMLWriter();

// Used to write to xml file - uncomment the next line to print xml to a file
$xml->openURI('umame_nyhedsbrev.xml');

// used for string output from memory
// $xml->openMemory(); // comment this line to print xml to a file

//set the indentation to true
$xml->setIndent(true);

//create the document tag
$xml->startDocument('1.0', 'utf-8');

$xml->startElement("items"); // start Items
// faste værdier
$antal_pr_side = 200; // denne værdi skal ændres
$offset = 0;
$data = array();
$run = true;
while ($run) {
    $con = $wpdb->__get('dbh');
    $stmt1 = $con->prepare("SELECT post_type FROM nw_posts WHERE post_type = 'product' ");
    $stmt1->execute();
    $rs1 = $stmt1->get_result();

    $stmt = $con->prepare("SELECT **_posts.ID, **_posts.post_modified, **_posts.post_title, **_posts.post_type, **_postmeta.post_id, **_postmeta.meta_value, **_postmeta.meta_key
    FROM **_posts INNER JOIN **_postmeta ON **_posts.ID = **_postmeta.post_id WHERE **_posts.post_type in ('product', 'attachment') and **_postmeta.meta_key in ('_wp_attached_file', '_sku', '_regular_price', '_sale_price') LIMIT " . $offset . "," . $antal_pr_side." ");
    $stmt->execute();
    $rs = $stmt->get_result();
    $lng = $rs1->num_rows;
    global $meta_regular_price;
    global $meta_sale_price;
    global $meta_sku;
    global $post_title;
    global $meta_stock;
    global $brand;
    global $post_parent;
    global $guid;
    global $image;

    while ($row = $rs->fetch_array(MYSQLI_ASSOC)) {
        $data[] = $row;

        if ($row['meta_key'] == "_sku") {
            $meta_sku = $row['meta_value'];
        }
        if ( is_array( get_the_terms($row['ID'], 'product_brand') ) ) {
            foreach (get_the_terms($row['ID'], 'product_brand') as $item) {
                $brand = $item->name;
            }
        }
        if ( is_array( get_the_terms($row['ID'], 'product_cat') ) ) {
            foreach (get_the_terms($row['ID'], 'product_cat') as $item) {
                $koenet = $item->parent;
            }
        }
        $koen = $koenet;

        $image = get_the_post_thumbnail_url($row['ID']);
        if ( is_array( get_the_terms($row['ID'], 'product_cat') ) ) {
            foreach (get_the_terms($row['ID'], 'product_cat') as $term) {
                if ($term->parent == 0) {
                    global $koen;
                    $koen = $term->name;
                }
            }
        }
        $post_title = $row['post_title'];

        $guid = get_permalink($row['ID']);

        if ($row['meta_key'] == "brand") {
            global $product_brand;
            $product_brand = $row['value'];

        }
        $post_modified = $row['post_modified'];

        $post_parent = $row['post_id'];


        if ($row['meta_key'] == "_regular_price") {
            $meta_regular_price = $row['meta_value'];

        }

        if ($row['meta_key'] == "_sale_price") {
            $meta_sale_price = $row['meta_value'];

        }




        if ($row['meta_key'] == "_stock_status") {
            if ($row['meta_value'] = 'outofstock') {
                global $meta_stock;
                $meta_stock = 0;
            } else {
                global $meta_stock;
                $meta_stock = 1;
            }
        }


        $xml->startElement("item"); // start Item

        $xml->writeAttribute('ExternalId', $meta_sku);
        $xml->writeAttribute('Modified', $post_modified);
        $xml->writeAttribute('Name', $post_title);
        $xml->writeAttribute('ImageLink', $image);
        $xml->writeAttribute('AdditionalImageLink', $image);
        $xml->writeAttribute('Link', $guid);
        $xml->writeAttribute('Gender', $koen);
        $xml->writeAttribute('Brand', $brand);
        $xml->writeAttribute('InStock', $meta_stock);
        $xml->writeAttribute('ItemGroupId', $post_parent);
        $xml->writeAttribute('RegularPrice', $meta_regular_price);
        $xml->writeAttribute('SalePrice', $meta_sale_price);

        $xml->endElement(); //End Item


    }


    if ($lng < $antal_pr_side) {
        $run = false;
    }
    if ($lng == 0) {
        break;
    }
    $offset += $antal_pr_side;
}
$xml->endElement();
// Display thue current buffer
$xml->flush();
}

Har kæmpet en del her inde og der har været meget hjælp at hente, og det er jeg så evig glad for.
Avatar billede acore Ekspert
08. april 2021 - 14:35 #1
Det er fordi du har to while løkker inden i hinanden. Det bliver ikke ved i en uendelighed, men den skriver filen lige så mange gange som der er rækker. Og da det er en stor fil, så bliver det til meget.

Jeg kan ikke helt gennemskue hvorfor du har to queries - et burde være nok og så en while løkke.
Avatar billede Morten Professor
08. april 2021 - 15:36 #2
Hej

$stmt1 = $con->prepare("SELECT post_type FROM **_posts WHERE post_type = 'product' ");
er for at få det rigtige antal produkter så den kan stoppe løkken når den når der til.

Fordi der er de to while er for at kunne få den automatisk til at køre sig færdig.
Avatar billede acore Ekspert
08. april 2021 - 15:59 #3
Koden

while (...) {
  while (...) {
    echo(...);

udskriver hele filen lige så mange gange som der er rækker i den. Det er det, du skriver om som dit problem, og det kan ikke være rigtigt.

Men jeg forstår ikke formålet med de 200 ad gangen. Som jeg husker den gamle tråd, skulle du ENTEN bruge LIMIT eller sørge for at der ikke blev skrevet til memory. Her prøver du begge dele - dit query brugr LIMIT og du kalder $xml->flush() løbende. En af delene skulle være nok.

Det letteste vil være et query, der henter alle rækker, og så

while ($row = $rs->fetch_array(MYSQLI_ASSOC))
{
  $xml->startElement("item");
  $xml->writeAttribute(...);
  $xml->writeAttribute(...);
  ...
  $xml->endElement();
  $xml->flush();
}
Avatar billede Morten Professor
08. april 2021 - 16:12 #4
Ja det er rigtigt, det er fordi som den gør nu forsøger den på at hente alle rows inde i databasen på den nøjes ikke med det antal af produkter, den tager også egenskaber af produktet.
det med den første query man ser er at den tager præcis de antal produkter der er.
Og derfor ville jeg bruge den i antal produkter den skulle ende på.
De 200 linjer af gangen er for ikke at bruge alt memory inden den tager outputtet. på den måde med de 200 tager den det ind af gangen i filen, og så tager den derfra . ligsom en limit som ses her i koden:

('_wp_attached_file', '_sku', '_regular_price', '_sale_price') LIMIT " . $offset . "," . $antal_pr_side."
Avatar billede acore Ekspert
08. april 2021 - 16:24 #5
Men med $xml->flush() bruger du jo netop IKKE al memory. Så hvorfor så...?
Avatar billede Morten Professor
08. april 2021 - 17:28 #6
Den dur ikke helt den stopper før den er færdig så den når ikke alle produkter igennem og så standser siden med en HTTP ERROR 500

Når jeg ikke kan dele indputtet op.
Avatar billede acore Ekspert
08. april 2021 - 17:39 #7
Ikke, hvis den er lavet rigtigt
Avatar billede Morten Professor
08. april 2021 - 18:15 #8
$con = $wpdb->__get('dbh');
$stmt1 = $con->prepare("SELECT post_type FROM **_posts WHERE post_type = 'product' ");
$stmt1->execute();
$rs1 = $stmt1->get_result();
$lng = $rs1->num_rows+100;
$stmt = $con->prepare("SELECT **_posts.ID, **_posts.post_modified, **_posts.post_title, **_posts.post_type, **_postmeta.post_id, **_postmeta.meta_value, **_postmeta.meta_key
    FROM **_posts INNER JOIN **_postmeta ON **_posts.ID = **_postmeta.post_id WHERE **_posts.post_type in ('product', 'attachment') and **_postmeta.meta_key in ('_wp_attached_file', '_sku', '_regular_price', '_sale_price') LIMIT ".$lng." ");
$stmt->execute();
$rs = $stmt->get_result();

global $meta_regular_price;
global $meta_sale_price;
global $meta_sku;
global $post_title;
global $meta_stock;
global $brand;
global $post_parent;
global $guid;
global $image;

while ($row = $rs->fetch_array(MYSQLI_ASSOC)) {
    $data[] = $row;

    if ($row['meta_key'] == "_sku") {
        $meta_sku = $row['meta_value'];
    }
    if ( is_array( get_the_terms($row['ID'], 'product_brand') ) ) {
        foreach (get_the_terms($row['ID'], 'product_brand') as $item) {
            $brand = $item->name;
        }
    }
    if ( is_array( get_the_terms($row['ID'], 'product_cat') ) ) {
        foreach (get_the_terms($row['ID'], 'product_cat') as $item) {
            $koenet = $item->parent;
        }
    }
    $koen = $koenet;

    $image = get_the_post_thumbnail_url($row['ID']);
    if ( is_array( get_the_terms($row['ID'], 'product_cat') ) ) {
        foreach (get_the_terms($row['ID'], 'product_cat') as $term) {
            if ($term->parent == 0) {
                global $koen;
                $koen = $term->name;
            }
        }
    }
    $post_title = $row['post_title'];

    $guid = get_permalink($row['ID']);

    if ($row['meta_key'] == "brand") {
        global $product_brand;
        $product_brand = $row['value'];

    }
    $post_modified = $row['post_modified'];

    $post_parent = $row['post_id'];


    if ($row['meta_key'] == "_regular_price") {
        $meta_regular_price = $row['meta_value'];

    }

    if ($row['meta_key'] == "_sale_price") {
        $meta_sale_price = $row['meta_value'];

    }




    if ($row['meta_key'] == "_stock_status") {
        if ($row['meta_value'] = 'outofstock') {
            global $meta_stock;
            $meta_stock = 0;
        } else {
            global $meta_stock;
            $meta_stock = 1;
        }
    }


    $xml->startElement("item"); // start Item

    $xml->writeAttribute('ExternalId', $meta_sku);
    $xml->writeAttribute('Modified', $post_modified);
    $xml->writeAttribute('Name', $post_title);
    $xml->writeAttribute('ImageLink', $image);
    $xml->writeAttribute('AdditionalImageLink', $image);
    $xml->writeAttribute('Link', $guid);
    $xml->writeAttribute('Gender', $koen);
    $xml->writeAttribute('Brand', $brand);
    $xml->writeAttribute('InStock', $meta_stock);
    $xml->writeAttribute('ItemGroupId', $post_parent);
    $xml->writeAttribute('RegularPrice', $meta_regular_price);
    $xml->writeAttribute('SalePrice', $meta_sale_price);

    $xml->endElement(); //End Item
}
$stmt->close();

$xml->endElement();

$xml->flush();

Kan du se hvad der skulle være galt
Avatar billede acore Ekspert
08. april 2021 - 19:16 #9
Nu skriver du ikke hvad fejlen er, men flush() skal i hvert fald indenfor while løkken.

$data[] = ... skal slettes - du bruger det ikke og det bruger bare memory.

Det første query skal slette s- linie 2-5

Og så skal

LIMIT ".$lng.

fjernes fra dit query.

Det er hvad jeg lige kan se
Avatar billede Morten Professor
08. april 2021 - 22:35 #10
Så har jeg været igang og fundet ud af hver anden gang jeg køre functionen virker det fint eller når den så køre igen og man ser cache nedeste linje af browseren når den loader.
Og så virker det ikke. Gør man det så igen virker det.
Har det så lige virker virker det ikke igen hvis man køre functionen igen...
Det virker mærkeligt...
Avatar billede Morten Professor
08. april 2021 - 23:25 #11
Nå men nu prøvede jeg lige på en staging server der virker det fint, og så har jeg cronjob på. Så det lykkedes til sidst. :-D

Tak for hjælpen
Jeg lukker tråd

Mvh.
Morten
Avatar billede acore Ekspert
09. april 2021 - 04:24 #12
Godt at det endelig lykkedes for dig, og max point til dig for at kæmpe for at finde en løsning.
Avatar billede Morten Professor
09. april 2021 - 06:42 #13
Takker
Og tak for al jeres hjælp :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester