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.
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.
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.
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();
}
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."
acore Ekspert
08. april 2021 - 16:24 #5
Men med $xml->flush() bruger du jo netop IKKE al memory. Så hvorfor så...?
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.
acore Ekspert
08. april 2021 - 17:39 #7
Ikke, hvis den er lavet rigtigt
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
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
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...
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
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.
Morten Professor
09. april 2021 - 06:42 #13
Takker
Og tak for al jeres hjælp :-)
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.

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





Premium
Bankdata klar med sin største it-leverance nogensinde: “Det er fire eller fem gange større end nogen andre projekter, vi har haft”
Om to måder går Bankdata ind i næste fase af det største initiativ i virksomhedens historie. “Det er fire eller fem gange større end nogen andre projekter, vi har haft. Det har været et stort og meget vigtigt projekt,” siger udviklingsdirektør hos Bankdata Christian Wiese.
Computerworld
Sikkerhedshul i sundhed.dk gør det let at snyde med coronapas
Et hul i sikkerheden hos sundhed.dk åbner op for, at coronapas-ejere kan ændre på de svar, der står i passet. Men det er dokumentfalsk, advarer sundhed.dks direktør.
CIO
Har du rost din mellemleder i dag? Snart er de uddøde - og det er et tab
Computerworld mener: Mellemledere lever livet farligt: Topledelsen får konstant ideer med skiftende hold i virkeligheden, og moden går mod flade agile organisationer. Men mellemlederen er en overset hverdagens helt med et kæmpe ansvar. Her er min hyldest til den ofte latterliggjorte mellemleder.
Job & Karriere
"Vi var nødt til at sige til dem, at I er nødt til at sende ham hjem nu, for han begynder at knække"
"Vi var nødt til at sige til dem, at I er nødt til at sende ham hjem nu, for han begynder at knække"
White paper
Udnyt ressourcerne bedre og skru op for overskuddet
Spildt arbejde, ineffektive processer og ringe forretningsindsigt er blot tre tegn på ringe ressourceudnyttelse. I dette whitepaper får du viden om, hvordan du måler ressourceudnyttelsen – og bruger indsigten operationelt, taktisk og strategisk.