Problemen met het uitlezen van de RSS-feed via SimpleXML

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Tim Klein

Tim Klein

11/02/2020 18:33:14
Quote Anchor link
Hoi,

Ik ben bezig met het uitlezen van een Xml-feed, waarna ik deze wegschrijf in een SQL-database. Daarvoor gebruik ik de volgende code:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
$affectedRow
= 0;

$xml = simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");

foreach ($xml->channel->item as $row) {
    $Last_build = $row->lastBuildDate;
    
    //Select data from XML
    $title = $row->title;
    $pubDate = $row->pubDate;
    
    //Format the last date
    $unixtime = strtotime($pubDate);
    $Published_date = date("Y-m-d H:i:s",$unixtime);
    
    //Check if published date is the latest.
    $Check_last_date = mysqli_num_rows(mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'"));
    
    if($Check_last_date == '0'){    
        $sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
    }

    
    $result = mysqli_query($conn, $sql);
    
    if (! empty($result)) {
        $affectedRow ++;
    }
else {
        $error_message = mysqli_error($conn) . "\n";
    }
    
}

?>


<?php
if ($affectedRow > 0) {
    //$message = $affectedRow . " records inserted";
} else {
    //$message = "No records inserted";
}

?>


Nu heb ik alleen één probleem: enkel de eerste regel wordt 25 keer in de database weggeschreven als deze er niet in staat. Ik had het werkend toen ik de RSS-link als lokaal bestand had staan (met exact de inhoud van de RSS-feed ge copy-pasted), maar nu ik deze verander in een link, werkt alleen de bovenste regel 25 keer. Wat doe ik fout?

Tim

Tim
 
PHP hulp

PHP hulp

20/02/2020 15:56:00
 
- Ariën -
Beheerder

- Ariën -

11/02/2020 18:36:24
Quote Anchor link
Lijn 20, moet je niet die quotes weghalen? Het gaat immers om integers.
Ik zou toch aanraden om de query in een aparte variabele op te slaan. Zo kan je makkelijker debuggen, en makkelijker foutafhandeling toevoegen.
 
Tim Klein

Tim Klein

11/02/2020 19:15:26
Quote Anchor link
Hoi Ariën! Dank je wel voor je snelle reactie!

Ik heb - zoals je aangaf - inderdaad de quotes weggehaald op regel 20. Daarnaast heb ik SQL nu losgehaald. Mijn code ziet er nu zo uit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
$xml
= simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");

foreach ($xml->children() as $row1) {
    foreach($row1->item as $row){
        
        //Select data from XML
        $title = $row->title;
        $pubDate = $row->pubDate;
        
        //Format the last date
        $unixtime = strtotime($pubDate);
        $Published_date = date("Y-m-d H:i:s",$unixtime);
        
        //Check if published date is the latest.
        $Sql_check_las_date = "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'";
        $Check_last_date = mysqli_num_rows(mysqli_query($conn, $Sql_check_las_date));
        
        if($Check_last_date == 0){    
            $sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
        }

        
        mysqli_query($conn, $sql);
        
    }
}

?>


Zoals ik al aangaf, denk ik dat het licht aan de foreach. Immers, ik krijg wel 25 keer een regel erin. In eerste instantie laadt ik alles dus goed in. Als ik alleen één regel weg haal uit de SQL-database (lees: er komt een nieuwe post bij in de XML-file), gaat hij alle regels daaronder af, en worden alle onderstaande regels afgelopen.

Bijvoorbeeld:

Ik verwijder één regel uit de databsase, welke in de XML-file 10 items eronder heeft. Vervolgend worden er 10 regels met dezelfde datum en tekst in de SQL-database gezet.

Doe ik dit met een SQL-regel welke in de XML nog 19 regels eronder heeft, krijg ik 19 keer dezelfde alarmering in de tabel ge-insert.

Hoor graag van jullie!
 
- Ariën -
Beheerder

- Ariën -

11/02/2020 19:21:53
Quote Anchor link
Een geneste foreach? Dat lijkt mij niet echt logisch?
Je moet enkel de childs uitlezen. En daarbij controleer je in jouw geval welke de laatste is, waarna je een INSERT-query uitvoert.

Ik denk dat je met enig debugwerk al best wel ver moet komen. Dus sla de query eens los op, en kijk eens of die wel goed werkt. En check ook eens: $Check_last_date.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

11/02/2020 19:29:45
Quote Anchor link
Vervang regel 18 van je openings-post eens voor het volgende:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
    //Check if published date is the latest.
    $result = mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'");
    
    if($result === false) {
        echo mysqli_error($conn);
        exit;
    }

    $Check_last_date = mysqli_num_rows($result);
?>


Want als je query foutmeldingen oplevert zal num_rows uiteraard altijd gelijk zijn aan 0.
Gewijzigd op 11/02/2020 19:31:00 door Frank Nietbelangrijk
 
Thomas van den Heuvel

Thomas van den Heuvel

11/02/2020 19:45:46
Quote Anchor link
Maar ook: zijn het wel unieke publish dates, of zijn ze alle hetzelfde?

Ik zou @Ariën zijn voorstel volgen en alles eens debuggen.

Daarbij: het uitlezen van een feed en het wegschrijven naar een database zijn twee aparte dingen.

Die je prima in afzondering kunt behandelen.

Jouw vraagstuk is van de vorm: ik verricht achtereenvolgens handeling A B C D .... X Y Z en uit Z komt niet het gewenste resultaat. Waar gaat het mis? Sja... ergens tussen A en Z :).

Als je dit nu eens opsplitst in aparte onderdelen: zorg dat de uitvoer van A geschikt is als invoer van B et cetera. Op die manier deel je je probleem op in stukken.

Dus, lees eerst de feed eens uit en kijk wat voor data dit oplevert. Zorg dat dit geschikt is om in een database in te voeren. En daarbij moet je waarschijnlijk op een of andere manier vaststellen wat al in je database aanwezig is. Hiervoor heb je dus een of ander (uniek) criterium nodig waarbij je onderscheid kunt maken tussen reeds aanwezige en nieuwe items. Ook deze stap kun je in afzondering onderzoeken. En vervolgens (laatste) insert je enkel de nieuwe items.

Verdeel en heers.
 
Tim Klein

Tim Klein

11/02/2020 19:50:30
Quote Anchor link
Hoi allemaal!

Ik was een beetje blind voor mijn eigen fouten, maar heb het inmiddels opgelost.

Mijn probleem: de $result stond buiten de check. Daardoor werd deze voor iedere regel uitgevoerd, terwijl de $sql toch nog onthouden wordt uit de vorige (immers: ik definieer hem niet ergens op leeg). Ik heb deze nu binnen de if geplaatst, en nu werkt het wel zoals ik wil. Final code:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
$xml
= simplexml_load_file('https://alarmeringen.nl/feeds/user/76663/457abd70094d50a7d1dfde038f9e295c/timg.rss') or die("Error: Cannot create object");

foreach ($xml->channel->item as $row) {
        $Last_build = $row->lastBuildDate;
        
        //Select data from XML
        $title = $row->title;
        $pubDate = $row->pubDate;
        
        //Format the last date
        $unixtime = strtotime($pubDate);
        $Published_date = date("Y-m-d H:i:s",$unixtime);
        
        //Check if published date is the latest.
        $result = mysqli_query($conn, "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '$Published_date'");
        
        if($result === false) {
            echo mysqli_error($conn);
            exit;
        }

        
        $Check_last_date = mysqli_num_rows($result);    
        if($Check_last_date == '0'){    
            $sql = "INSERT INTO Deployment_registration_alarms(Alarm,Published_date) VALUES ('" . $title . "','" . $Published_date . "')";
            $result = mysqli_query($conn, $sql);
        }
        
}

?>


- Ariën - op 11/02/2020 19:21:53:
Een geneste foreach? Dat lijkt mij niet echt logisch?
Je moet enkel de childs uitlezen. En daarbij controleer je in jouw geval welke de laatste is, waarna je een INSERT-query uitvoert.

@Ariën, dit lijkt inderdaad niet logisch nee. Toch kan ik met de $xml->channel->item - string deze niet werkend krijgen. Vandaag deze dubbele foreache'jes.

Allen bedankt voor de hulp!
 
Michael -

Michael -

11/02/2020 19:51:21
Quote Anchor link
Ik zou beter naamgeving voor stellen. Ik vind 't nogal onoverzichtelijk om last_date en las_date te gebruiken.
Daarnaast pubDate en Published_date zeggen niet gelijk dat dit verschillende formaten zijn.
En waarom eerst $row->pubDate kopieren naar pubDate dan naar unixtime dan een nieuw format?
Je kunt deze stappen allemaal overslaan, en zelfs direct aan de query voeren mits je deze verder niet meer nodig hebt.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$Published_date
= (new \DateTime($row->pubDate))->format('Y-m-d H:i:s');

//of direct

$Sql_check_las_date = "SELECT ID FROM Deployment_registration_alarms WHERE Published_date = '" . (new \DateTime($row->pubDate))->format('Y-m-d H:i:s') . "'";
?>


Toevoeging op 11/02/2020 20:34:54:

En in plaats van de check door eerst een SELECT uit te voeren en dan een INSERT als Published_date niet bestaat, kun je ook het veld Published_date een "UNIQUE KEY" geven. Dan gebruik je "INSERT IGNORE". Mocht de Published_date dat al bestaan, slaat die deze ook over.
 
Thomas van den Heuvel

Thomas van den Heuvel

11/02/2020 21:32:25
Quote Anchor link
Of: op het moment dat je een record tegenkomt wat je al kent ben je toch klaar, aangenomen dat alles op volgorde staat en er geen items met terugwerkende kracht worden toegevoegd? Hier zou je dan eventueel een break in kunnen bouwen.

Ook zouden prepared statements hier meerwaarde kunnen hebben omdat het elke keer eenzelfde soort query betreft.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.