IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Un foreach qui ne traite qu'un fichier


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2014
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms

    Informations forums :
    Inscription : Avril 2014
    Messages : 27
    Par défaut Un foreach qui ne traite qu'un fichier
    Salut à tous,
    j'ai un foreach pour traiter des fichiers xml du genre
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="UTF-8"?>
    <notification>
       <alerte>HOST</alerte>
       <typenotif>RECOVERY</typenotif>
       <service></service>
       <hote>info_stage_1</hote>
       <adresse_ip>192.168.12.89</adresse_ip>
       <etat>UP</etat>
       <id_etat>0</id_etat>
       <descr>PING OK -  Paquets perdus = 0%, RTA = 2.07 ms</descr>
       <timestamp>2014-05-20 08:37:09</timestamp>
    </notification>

    et avec ce code ci-dessous, je n'ai que le premier qui est traité et inséré en base.
    Pourquoi ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
        foreach ($liste as $file) 
    {
        $contenu = file_get_contents($file);
        $xml = simplexml_load_string($contenu);
        print_r($xml);
        $params = array();
     
        foreach ($xml as $notification) {
            $param[] = trim($notification);
        }
        list($alerte, $typenotif, $service, $hote, $adresse_ip, $etat, $id_etat, $descr, $timestamp) = $param;
        echo $alerte, PHP_EOL;
        echo $typenotif, PHP_EOL;
        echo $service, PHP_EOL;
        echo $hote, PHP_EOL;
        echo $adresse_ip, PHP_EOL;
        echo $etat, PHP_EOL;
        echo $id_etat, PHP_EOL;
        echo $descr, PHP_EOL;
        echo $timestamp, PHP_EOL;
     
        $insertion = mysqli_query($mysqli, "INSERT INTO notifications (`Type_Alerte`, `Type_Notification`, `Service`, `Hote`, `Adresse_IP`, `Type_Etat`, `ID_Etat`, `Descriptif`, `Date_Heure`) VALUES ('$alerte','$typenotif','$service','$hote','$adresse_ip','$etat','$id_etat','$descr','$timestamp')");
    	}
    // deconnexion de la base
    $mysqli->close();
    et en sortie j'ai plusieurs fois le meme enregistrement même si dans la console en debut de chaque ligne il m'affiche traitement de fichier "1", puis "2" etc, j'ai toujours les memes données qui s'affichent correspondantes au premier fichier.

    Ou ai-je foiré ?

    Merci de votre aide.

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Par défaut
    Tu as contrôlé $liste ?
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  3. #3
    Membre averti
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2014
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms

    Informations forums :
    Inscription : Avril 2014
    Messages : 27
    Par défaut Oui mais
    Je viens de m'apercevoir que dans le print_r des fichiers xml il me met bien tous les fichiers avec leurs données très bien
    comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    traitement de C:/Documents and Settings/900204/Bureau/Test/20140523030255012345678.xml
    SimpleXMLElement Object
    (
        [alerte] => HOST
        [typenotif] => PROBLEM
        [service] => spouleur_dimpression
        [hote] => iris
        [adresse_ip] => 172.19.0.205
        [etat] => CRITICAL
        [id_etat] => 3
        [descr] => CRITIQUE - H├┤te inaccessible (172.19.0.205)
        [timestamp] => 2014-05-23 03:02:55
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Par contre pour le
    echo $alerte
    echo $typenotif
    etc..
    Il m'affiche que ceux du premier fichier et donc toujours les mêmes comme si le foreach ne marcahit pas.

    J'ai du foirer dans le code en rouge:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
        $xml = new SimpleXMLElement(file_get_contents($file));
        print_r($xml);
        $params = array();
        foreach ($xml as $notification) {
            $param[] = trim($notification);
        }
        list($alerte, $typenotif, $service, $hote, $adresse_ip, $etat, $id_etat, $descr, $timestamp) = $param;
        echo $alerte, PHP_EOL;
        echo $typenotif, PHP_EOL;
        echo $service, PHP_EOL;
        echo $hote, PHP_EOL;
        echo $adresse_ip, PHP_EOL;
        echo $etat, PHP_EOL;
        echo $id_etat, PHP_EOL;
        echo $descr, PHP_EOL;
        echo $timestamp, PHP_EOL;
    Merci de ton aide

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 418
    Par défaut
    C'est bien imprudent de faire un list() à l'aveugle. Et s'il manquait des champs dans le fichier xml ?

    Et maintenant que tu utilises mysqli c'est le moment de faire des requêtes préparées puisque le contexte s'y prête (requêtes dans une boucle).

    Ton code pourrait ressembler à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    <?php 
     
    $dossier = 'à renseigner';
     
    $liste = new RegexIterator(new DirectoryIterator($dossier),'/^[0-9]{23}\.xml$/i');
     
    if(iterator_count($liste) > 0)
    {
     
            $mysqli = 'connexion_bdd à renseigner';
     
    	$champs_bdd_xml = array();
     
            // Tableau de correponsdance champs bdd -> champs xml
    	$champs_bdd_xml['Type_Alerte'] = 'alerte';
    	$champs_bdd_xml['Type_Notification'] = 'typenotif';
    	$champs_bdd_xml['Service'] = 'service';
    	$champs_bdd_xml['Hote'] = 'hote';
    	$champs_bdd_xml['Adresse_IP'] = 'adresse_ip';
    	$champs_bdd_xml['Type_Etat'] = 'etat';
    	$champs_bdd_xml['ID_Etat'] = 'id_etat';
    	$champs_bdd_xml['Descriptif'] = 'descr';
    	$champs_bdd_xml['Date_Heure'] = 'timestamp';
     
            $query = "INSERT INTO notifications (".implode(",",array_keys($champs_bdd_xml)).") VALUES (".implode(',',array_fill (0,count($champs_bdd_xml),'?')).")";
     
    	if($stmt = mysqli_prepare($mysqli,$query))
    	{
     
    		$type_champs = 'ssssssiss';// voir les types des champs dans la doc http://www.php.net/manual/fr/mysqli-stmt.bind-param.php
     
    		mysqli_stmt_bind_param($stmt, $type_champs, $Type_Alerte, $Type_Notification, $Service, $Hote, $Adresse_IP, $Type_Etat,$ID_Etat, $Descriptif, $Date_Heure);
     
     
    		foreach ($liste as $fichier) 
    		{
    			$content = file_get_contents($fichier->getPathname());
     
    			if($xml = @simplexml_load_string($content))
    			{	
    				foreach ($champs_bdd_xml as $ch_bdd => $val_xml)
    				{
    					$$ch_bdd = isset($xml->$val_xml) ? trim($xml->$val_xml) : null;
    				}
     
    				mysqli_stmt_execute($stmt);	
     
    				// efface les fichiers traités si l'insertion en bdd est ok
    				//if(mysqli_stmt_affected_rows($stmt) == 1) unlink($fichier->getPathname());
    			}
    			else echo 'erreur dans la structure xml du fichier: '.$fichier->getPathname();
    		} 
    	}
    	else echo 'erreur dans la préparation de la requête: '.$query;
    }
    ?>
    On pourrait faire plus classe pour gérer l'erreur si le xml est mal formé plutôt que d'utiliser @... mais bon

  5. #5
    Membre averti
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2014
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms

    Informations forums :
    Inscription : Avril 2014
    Messages : 27
    Par défaut Tu es un GENIE
    Cher ABCIWEB,
    Tu es un GENIE.
    Ça marche au poil.

    Pour le reste je vais étudier ton script et apprendre ce que c'est $$ ou ?

    Par contre j'ai encore 4 PETITES questions:
    1.
    à la fin du script j'avais mis ces lignes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $filename = basename($file); //nom du fichier
    rename($file,"$dossiertraite/${filename}_fini.xml"); //déplace
    pour transférer les fichiers vers un autre dossier (pour les archives) et ça marche
    mais après comme vider le dossier des autres fichiers. (En effet il reste des fichiers qui avaient été crées par le même script qui récupère les infos. En effet le tuteur voulait "fichier.xml" et fichier_OK).
    Une fois que j'ai transféré les "fichiers.xml" traités je voudrais effacer les autres, les "fichiers_OK".

    2. Je sais pas si je te l'avais dit, mais ce script sera lancé par un cron tous les 5 minutes.
    Si lors de l’exécution du script un fichier venait a être écrit dans le dossier est-ce que il serait traité par la prochaine exécution du script ou alors ça pourrait poser problème (genre lecture à moitie).
    Ai je besoin de donner une condition genre:
    si le fichier est complet, ou lisible continue?

    3. Mon tuteur me dit:
    "Il faut verifier les champs avant de les inserer"
    mais il y en a que un à verifier le id_etat qui doit etre compris entre 0 et 3
    puisque les autres ce sont des strings ou alors vérifier que ces sont bien des strings, mais je crois que c'est fait avec ta chaine sssssiss, ou non ?
    Comment faire, quelle est la ligne adaptée?

    4. Je ne dois pas fermer la connexion à la base? avec:
    et ça veut dire quoi ? et le trim qui suit et le null ?

    MERCI ENCORE POUR TON AIDE
    T'AS ÉTÉ TROP COOL.

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 418
    Par défaut
    Salut,

    1/ La première question est largement accessible pour un débutant, je le laisse travailler un peu. Regardes vers strpos, strrpos, substr puis is_file si tu veux savoir si un fichier "fichier1.xml" a son équivalent "fichier1_OK.xml".

    2/ Si un fichier est en cours d'écriture, on ne pourra pas l'ouvrir et à fortiori il ne sera pas valide xml et donc il ne sera pas traité. D'ailleurs j'avais repris ton code mais tu peux replacer ces deux lignes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $content = file_get_contents($fichier->getPathname());
    if($xml = @simplexml_load_string($content))
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if($xml = @simplexml_load_file($fichier->getPathname()))
    3/ Les champs sont bien vérifiés dans la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    foreach ($champs_bdd_xml as $ch_bdd => $val_xml)
    {
        $$ch_bdd = isset($xml->$val_xml) ? trim($xml->$val_xml) : null;
    }
    puisque je teste s'ils existent et sinon je mets la valeur nulle. Pour les tester nominativement tu possède plus qu'il n'en faut avec $ch_bdd, $val_xml et isset($xml->$val_xml).
    Dans cette boucle si tu ne veux pas enregistrer le fichier si ID_Etat n'est pas un numérique compris entre 0 et 3 on peut faire par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    $test_id = true;
    foreach ($champs_bdd_xml as $ch_bdd => $val_xml)
    {
        switch($ch_bdd)
        {
            case 'ID_Etat' : $$ch_bdd = isset($xml->$val_xml) && is_numeric(trim($xml->$val_xml)) && trim($xml->$val_xml) >= 0 &&  trim($xml->$val_xml) <= 3 ? intval(trim($xml->$val_xml)) : null;
                                 if(!isset($$ch_bdd)) {$test_id = false;} break;
     
            default : $$ch_bdd = isset($xml->$val_xml) ? trim($xml->$val_xml) : null;
        }
    }
    if ($test_id) mysqli_stmt_execute($stmt);
    Les $$ c'est pour créer des variables dont le nom correspond à la clé dans le tableau qui elle même est égale au nom du champ en bdd. Ces variables sont nommées de cette façon pour avoir le même nom que les variables indiquées dans mysqli_stmt_bind_param. C'est pour binder (associer) les variables dans la requête préparée. Renseigne-toi ici.

    4/ par définition tout ce qui sort d'un fichier xml est du type string donc pas la peine de vérifier que c'est de type string.

    5/ La fermeture de la connexion va se faire automatiquement, mais tu peux l'indiquer si tu veux à la fin du script (attention en fin de script mais pas dans une boucle).

    6/ Si tu peux avoir plusieurs notifications dans un même fichier il faudra modifier le script en testant le tag xml 'notification' (par rapport au dernier exemple de xml que tu avais donné).

    Tu écris à 9h30, en admettant que tu ai débuté ta journée à 8h ça fait une heure trente maxi pour comprendre ce que j'ai fait. Pour un débutant c'est largement insuffisant. Fais des var_dump() et autre print_r() pour comprendre le contenu des variables. Lis aussi la doc sur la préparation des requêtes, lis la doc sur toutes les fonctions que tu utilise.

    Regarde aussi http://www.php.net/manual/fr/languag...comparison.php et notamment la rubrique "L'opérateur ternaire" pour comprendre les ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [phpBB] Connaissez vous un forum qui permet l'upload de fichier
    Par lil-works dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 10
    Dernier message: 27/09/2006, 08h13
  2. Controle qui permet de selectionner un fichier
    Par sundjata dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 06/08/2006, 17h36
  3. [Debutant] Servlet qui permet d'afficher un fichier
    Par ganga dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 30/05/2006, 16h33
  4. Réponses: 4
    Dernier message: 03/02/2006, 18h02
  5. [JAR] pb class qui fait référence à un fichier property
    Par yanagiba dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 11/08/2005, 11h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo