Vérification doublon dans import CSV

Résolu/Fermé
roms75001 Messages postés 395 Date d'inscription mercredi 26 septembre 2007 Statut Membre Dernière intervention 9 juillet 2017 - Modifié par roms75001 le 6/03/2017 à 11:57
 Utilisateur anonyme - 8 mars 2017 à 15:05
Bonjour,

J'ai fais un code afin d'insérer en base de données un fichier CSV, celui ci fonctionne très bien mais j'aimerais ajouté quelque chose :

Si le champs "E" est un doublon alors on retourne "doublon = 1" (je dois par la suite stocker le resultat en BDD)

J'ai donc fais le code suivant :


   $fp = fopen($fichier_dest, "r");
   //Lecture du fichier CSV
   if($fp){

    $ligne=0;

     while (($liste = fgetcsv($fp, 4096, ";")) !== FALSE)
     {

      $liste[0] = ( isset($liste[0]) ) ? $liste[0] : Null;
      $champsA = mysql_real_escape_string(implode('-', array_reverse(explode('/', $liste[0])))); 
      $champsE = mysql_real_escape_string (( isset($liste[4]) ) ? $liste[4] : Null); //ND
      $champsF = mysql_real_escape_string(( isset($liste[5]) ) ? $liste[5] : Null);
      $champsG = mysql_real_escape_string(( isset($liste[6]) ) ? $liste[6] : Null);
      $champsH = mysql_real_escape_string(( isset($liste[7]) ) ? $liste[7] : Null);
      $champsI = mysql_real_escape_string(( isset($liste[8]) ) ? $liste[8] : Null);
      $champsJ = mysql_real_escape_string(( isset($liste[9]) ) ? $liste[9] : Null);
      $champsK = mysql_real_escape_string(( isset($liste[10]) ) ? $liste[10] : Null);
      $champsL = mysql_real_escape_string(( isset($liste[11]) ) ? $liste[11] : Null);
      $champsM = mysql_real_escape_string(( isset($liste[12]) ) ? $liste[12] : Null);
      $champsO = mysql_real_escape_string(( isset($liste[14]) ) ? $liste[14] : Null);
      $champsP = mysql_real_escape_string(( isset($liste[15]) ) ? $liste[15] : Null);
      $liste[16] = ( isset($liste[16]) ) ? $liste[16] : Null;
      $champsQ = mysql_real_escape_string(implode('-', array_reverse(explode('/', $liste[16]))));  
      $nom_fichier = mysql_real_escape_string($_FILES['fichier']['name']);
      $cuid =  mysql_real_escape_string($_SESSION[_SESSION_IDENTIFIANT]);

      $indexAgent=selectionnerAgent($tbAgentsRef,$indexAgent);
      $tbAgentsRef[$indexAgent]['new']=$tbAgentsRef[$indexAgent]['new']-1;


      if (in_array($champsE, $liste)) {

       echo "<br />";
       echo"doublon = 1 ";
       echo $champsE;
       echo "<br/>";
       
      }

      else {
       echo "<br />";
       echo "doublon = 0 ";
       echo $champsE;
       echo "<br/>";
      }


      $ligne++; 
     }

   echo"<p>Importation Réussie</p>";

    fclose($fp);
   }



Mais ca me retourne toujours 1.

Savez vous m'aider ??

Merci d'avance

2 réponses

Utilisateur anonyme
6 mars 2017 à 16:37
Il y a quelques soucis avec ton code, car déjà
in_array
c'est juste pour savoir si une valeur se trouve dans un tableau, et non le nombre de fois, enfin je tiens à préciser à cause du message "doublon = 1".

Ensuite chercher le $champE dans la $liste, alors que le $champE est un élément de la liste,
in_array
va donc toujours retourner
true
.

Le mieux est d'utiliser
array_keys
, avec comme second paramètre le $champsE, et de compter le nombre d'élément retourné avec
count
, mais il faut aussi vérifier que le champ n'est pas vide ça donne:
if(!empty($champsE) && count(array_keys($liste, $champsE)) > 1) {echo "Doublon du champ E"}

Après les
isset
sont inutile car il retourne
true
dans tout les cas vu que si un champ n'est pas rempli dans le CSV la fonction
fgetcsv
remplacera par un champ vide jusqu'au dernier champ.

Enfin là j'ai du mal à m'expliquer avec un exemple ça sera mieux.

Si par exemple le champ P est rempli mais pas le B, comme P a un index plus grand que B, alors B existera (donc le
isset
retournera
true
) mais ça sera juste un champ vide (une chaîne vide
''
)

Mais si un coup sur deux (ou plus) le champ Q est rempli alors là le
isset
est utile car si c'est le dernier champ à être rempli, l'index n'est présent dans le tableau que si ce champ est rempli.

Puis pour tes conditions, il ne faut pas mettre le
null
dans la fonction
mysql_real_escape_string
car même si
mysql_real_escape_string(null)
vaut
null
si on fait une condition basique du genre
mysql_real_escape_string(null) == null
, ça te retourne
false
si tu fais
mysql_real_escape_string(null) === null
, car
mysql_real_escape_string(null)
équivaut à
''
(une chaîne vide).


if (($fp = fopen($fichier_dest, "r")) !== false) {
	$ligne=0;
	while (($liste = fgetcsv($fp, 4096, ";")) !== false) {
		//array_fill permet de remplir un tableau à partir d'un index de début (ici 0), avec le nombre d'éléments à ajouter (ici 17 [lettre Q]) avec une valeur (ici 'null')
		//Faire $array1 + $array2 permet de remplir les index manquant (isset = false) avec ceux de $array2.
		$liste = $liste + array_fill(0, 17, null);
		//range permet de créer un tableau partant d'un élément de début (A) faire un élément de fin (Q), ça peut être autre chose (comme 1,100)
		$lettres = range('A', 'Q');
		//On parcourt la liste
		foreach ($liste as $key => $value) {
			//trim permet de supprimer les espaces en début et fin de cĥaîne
			$value = trim($value);
			//Si l'index vaut 0 ou 16 alors on applique la modification
			//Même si je pense que c'est pour une date dans ce cas je préfère un preg_replace ou utiliser la fonction date pour avoir quelque chose de correct même si c'est identique au final.
			if ($key === 0 || $key === 16) {
				$value = implode('-', array_reverse(explode('/', $value)));
			}
			//Si la variable n'est pas vide on applique mysql_real_escape_string sinon null
			$liste[$key] = (!empty($value)) ? mysql_real_escape_string($value) : null;
			//Création des variables $champs dynamiquement donc on aura $champsA à $champsQ avec les éléments de la liste modifié.
			//Après je ne vois pas pourquoi créer des varibles alors que c'est identique à la $liste
			${'champs'.$lettres[$key]} = $value;
		}

		$nom_fichier = mysql_real_escape_string($_FILES['fichier']['name']);
		$cuid = mysql_real_escape_string($_SESSION[_SESSION_IDENTIFIANT]);

		$indexAgent = selectionnerAgent($tbAgentsRef,$indexAgent);
		//$tbAgentsRef[$indexAgent]['new']-- revient à faire $tbAgentsRef[$indexAgent]['new']=$tbAgentsRef[$indexAgent]['new']-1;
		$tbAgentsRef[$indexAgent]['new']--

		//Version simplifiée de la condition pour les doublons
		$condChampsE = (!empty($champsE) && count(array_keys($liste, $champsE)) > 1) ? 'true' : 'false';
		echo "<br>Doublon du \$champsE ($condChampsE), qui contient '$champsE'<br>";

		//Version détaillée
		if (!empty($champsE)) {
			$listDoublon = array_keys($liste, $champsE);
			if (count($listDoublon) > 1) {
				echo "<p>La variable \$champsE ('<b>$champsE</b>') est identique à d'autres variables qui sont:<ul>";
				//La condition évite d'avoir $champsE d'affiché
				foreach ($listDoublon as $key) if($key !== 4) echo '<li>$champs'.$lettres[$key]." / \$liste[$key]</li>";
				echo '</ul></p>';
			} else echo "<p>La variable \$champsE ('$champsE') est unique.</p>";
		} else echo '<p>La variable $champsE est vide.</p>';

		$ligne++; 
	}
	echo"<p>Importation Réussie</p>";

    fclose($fp);
}


Voilà le code optimisé.
1
roms75001 Messages postés 395 Date d'inscription mercredi 26 septembre 2007 Statut Membre Dernière intervention 9 juillet 2017 7
7 mars 2017 à 11:04
Wahouu, tout d’abord merci d'avoir pris le temps d'écrire ce beau code bien commenté.

Je l'ai testé, il manque juste un point virgule après $tbAgentsRef[$indexAgent]['new']-- (mais je t'en veux pas :p) par contre j'ai toujours le même problème, ça me retourne false sur toutes les lignes alors que dans mon jeux de données j'ai un doublons sur la colonne E

Petite préposition, j'ai vraiment besoin que ca me retourne 0 ou 1 car c'est ce qui est attendu par ma base de données :$
0
Utilisateur anonyme
8 mars 2017 à 00:02
Après j'ai testé vite fait sur un fichier CSV, en mettant la même chose dans plusieurs cellules et dont la E, mais il me faudrait un exemple de tes données où il y a un doublon et que le script doit retourné ce qu'il faut.
0
roms75001 Messages postés 395 Date d'inscription mercredi 26 septembre 2007 Statut Membre Dernière intervention 9 juillet 2017 7
8 mars 2017 à 14:48
Merci ZeNairolf pour ton aide !

Pour ceux que ca intéresse voici la modification qu'il faut faire afin d'avoir le résultat attendu :



if (($fp = fopen($fichier_dest, "r")) !== false) {
	$doublons = array();
	$ligne=0;

...

		$condChampsE = (!empty($champsE) && in_array($champsE, $doublons)) ? '1' : '0';
		echo "<br>Doublon du \$champsE ($condChampsE), qui contient '$champsE'<br>";

...

		$doublons[] = $champsE;
		$ligne++; 
	}
	echo"<p>Importation Réussie</p>";

    fclose($fp);
}
0
Utilisateur anonyme
8 mars 2017 à 15:05
Petite précision, ça permet de vérifier les doublons dans une colonne, et dans une ligne.
0