8791 sujets

Développement web côté serveur, CMS

Bonjour à tous,

Je suis en train de créer un petit script qui viendra effacer la BDD d'un site propulsé avec SPIP (rubrique et articles), et qui recréera le nouveau contenu (article et rubrique et donc aussi arborescence) à partir d'un fichier XML.

Je suis très loin d'être un expert en PHP. J'ai cependant à moitié réussi à obtenir le résultat souhaité. Cependant deux problèmes persistes et j'ai peur qu'ils caches un gros défaut de conception.

Le premier problème étant que tout les articles sont créés en double. Pourtant quand je fais un var_dump sur ma requête final tout semble ok.

Voici la partie du code incriminé :

	// on créer une variable qui contiendra tous les updates des articles
	$req_articles = array();
	$req_articles[0] = "INSERT INTO `spip_moulinette`.`spip_articles` (`id_article`, `surtitre`, `titre`, `soustitre`, `id_rubrique`, `descriptif`, `chapo`, `texte`, `ps`, `date`, `statut`, `id_secteur`, `maj`, `export`, `date_redac`, `visites`, `referers`, `popularite`, `accepter_forum`, `date_modif`, `lang`, `langue_choisie`, `id_trad`, `extra`, `id_version`, `nom_site`, `url_site`) VALUES ";
       $categorie_existantes = array();
       $sous_categorie_existantes = array();
       $i = 0;
       $j = 0;
       $k = 1;
	foreach ($armes as $arme) {
	    /* les rubriques */
		// si il existe déjà une rubrique de ce nom
	    
		foreach($categorie_existantes as $cat_exist)
		{
		    if($cat_exist == $arme->Type)
		    {
			$test_existence_categorie = true;
		    }
		}
		    // si il est négatif
		if(!$test_existence_categorie) {
		    $req = "SELECT * FROM spip_rubriques WHERE `titre` = :titre;";
		    $res = $cnx -> prepare($req);
		    $res -> bindParam(':titre', $arme->Type);
		    $res -> execute();
		    $rubriquePremierNiv = $res -> fetch();
		    $id_rubrique_parente = $rubriquePremierNiv['id_rubrique'];

		    if(!$rubriquePremierNiv['titre']) {
			$req = "INSERT INTO `spip_moulinette`.`spip_rubriques`
				(`id_rubrique`, `id_parent`, `titre`, `descriptif`, `texte`, `id_secteur`, `maj`, `export`, `id_import`, `statut`, `date`, `lang`, `langue_choisie`, `extra`, `statut_tmp`, `date_tmp`)
				VALUES
				(NULL, '0', :nomRubrique, '', '', '0', CURRENT_TIMESTAMP, 'oui', '0', 'publie', '0000-00-00 00:00:00', '', 'non', NULL, '0', '0000-00-00 00:00:00');";
			$res = $cnx -> prepare($req);
			$res -> bindParam(':nomRubrique', $arme->Type);
			$res -> execute();
			$categorie_existantes[$i] = $arme->Type;
			$i++;
		    }
		}
	    /* les sous rubriques */
		foreach($sous_categorie_existantes as $sous_cat_exist)
		{
		    // le test est positif
		    if($sous_cat_exist == $arme->Marque)
		    {
			$test_existence_sous_categorie = true;
		    }
		}
		    // si il est négatif
		if(!$test_existence_categorie) {
		    $req = "SELECT * FROM spip_rubriques WHERE `titre` = :titre;";
		    $res = $cnx -> prepare($req);
		    $res -> bindParam(':titre', $arme->Marque);
		    $res -> execute();
		    $rubriquePremierNiv = $res -> fetch();
		    $id_rubrique_article = $rubriquePremierNiv['id_rubrique'];

		    if(!$rubriquePremierNiv['titre']) {
			$req = "INSERT INTO `spip_moulinette`.`spip_rubriques`
				(`id_rubrique`, `id_parent`, `titre`, `descriptif`, `texte`, `id_secteur`, `maj`, `export`, `id_import`, `statut`, `date`, `lang`, `langue_choisie`, `extra`, `statut_tmp`, `date_tmp`)
				VALUES
				(NULL, :id_rubrique_parent, :nomRubrique, '', '', '0', CURRENT_TIMESTAMP, 'oui', '0', 'publie', '0000-00-00 00:00:00', '', 'non', NULL, '0', '0000-00-00 00:00:00');";
			$res = $cnx -> prepare($req);
			$res -> bindParam(':id_rubrique_parent', $id_rubrique_parente);
			$res -> bindParam(':nomRubrique', $arme->Marque);
			$res -> execute();
			$sous_categorie_existantes[$j] = $arme->Marque;
			$j++;
			
		    }
		}
		$test = "'<multi> [fr]" . mysql_escape_string($arme->LibelleFR) . "  [nl] " . mysql_escape_string($arme->LibelleVL) . "</multi>'";
		$req_articles[$k] = "(NULL, '', $test, '" . mysql_escape_string($arme->CdART) . "', '" . $id_rubrique_article . "', '".mysql_escape_string($arme->PV)."', '', '', '', '0000-00-00 00:00:00', 'publie', '0', CURRENT_TIMESTAMP, 'oui', '0000-00-00 00:00:00', '0', '0', '0', '', '0000-00-00 00:00:00', '', 'non', '0', NULL, '0', '', ''),";
		$k++;
	}
	
	$string = implode(" ", $req_articles);
	//supprimer la dernière virgule
	$resultat = substr($string,0,strlen($string)-1);
	
	//echo $resultat;
	$res = $cnx -> query($resultat);
	$res -> execute();


Mon deuxième problème, c'est que j'ai essayer de mettre dans un tableau les nouvelles rubriques créer pour tester leurs existence à chaque tour de boucle. Malheureusement la condition "if($cat_exist == $arme->Type)" n'est jamais vrai. Pourtant le script crée quand même les 3000 articles, de plus je ne vois pas le rapport avec le fait qu'il crée tout les articles deux fois.

Voilà j'espère avoir été clair. Je sais que c'est pas toujours évident de plonger dans le code de quelqu'un d'autre sans trop connaitre le contexte (surtout quand c'est un code aussi barbare). Je tire donc mon chapeau à celui qui aura le courage de se pencher sur mon problème ^^.

Merci d'avance.
Modifié par Gili (22 Jun 2012 - 14:55)
Teste ça pour voir :


// on créer une variable qui contiendra tous les updates des articles
$req_articles = array();
$req_articles[0] = "INSERT INTO `spip_moulinette`.`spip_articles` (`id_article`, `surtitre`, `titre`, `soustitre`, `id_rubrique`, `descriptif`, `chapo`, `texte`, `ps`, `date`, `statut`, `id_secteur`, `maj`, `export`, `date_redac`, `visites`, `referers`, `popularite`, `accepter_forum`, `date_modif`, `lang`, `langue_choisie`, `id_trad`, `extra`, `id_version`, `nom_site`, `url_site`) VALUES ";
$categorie_existantes = array();
$sous_categorie_existantes = array();
$i = 0;
$j = 0;
$k = 1;
foreach ($armes as $arme) {
  /* les rubriques */
  // si il existe déjà une rubrique de ce nom

  $test_existence_categorie = false;

  if (in_array($arme->Type, $categorie_existantes)) {
    $test_existence_categorie = true;
  }

  // si il est négatif
  if (false === $test_existence_categorie) {
    $req = "SELECT * FROM spip_rubriques WHERE `titre` = :titre;";
    $res = $cnx->prepare($req);
    $res->bindParam(':titre', $arme->Type);
    $res->execute();
    $rubriquePremierNiv = $res->fetch();
    $id_rubrique_parente = $rubriquePremierNiv['id_rubrique'];

    if (!$rubriquePremierNiv['titre']) {
      $req = "INSERT INTO `spip_moulinette`.`spip_rubriques`
				(`id_rubrique`, `id_parent`, `titre`, `descriptif`, `texte`, `id_secteur`, `maj`, `export`, `id_import`, `statut`, `date`, `lang`, `langue_choisie`, `extra`, `statut_tmp`, `date_tmp`)
				VALUES
				(NULL, '0', :nomRubrique, '', '', '0', CURRENT_TIMESTAMP, 'oui', '0', 'publie', '0000-00-00 00:00:00', '', 'non', NULL, '0', '0000-00-00 00:00:00');";
      $res = $cnx->prepare($req);
      $res->bindParam(':nomRubrique', $arme->Type);
      $res->execute();
      $categorie_existantes[$i] = $arme->Type;
      $i++;
    }
  }

  $test_existence_sous_categorie = false;

  if (in_array($arme->Marque, $sous_categorie_existantes)) {
      $test_existence_sous_categorie = true;
  }

  // si il est négatif
  if (false === $test_existence_sous_categorie) {
    $req = "SELECT * FROM spip_rubriques WHERE `titre` = :titre;";
    $res = $cnx->prepare($req);
    $res->bindParam(':titre', $arme->Marque);
    $res->execute();
    $rubriquePremierNiv = $res->fetch();
    $id_rubrique_article = $rubriquePremierNiv['id_rubrique'];

    if (!$rubriquePremierNiv['titre']) {
      $req = "INSERT INTO `spip_moulinette`.`spip_rubriques`
				(`id_rubrique`, `id_parent`, `titre`, `descriptif`, `texte`, `id_secteur`, `maj`, `export`, `id_import`, `statut`, `date`, `lang`, `langue_choisie`, `extra`, `statut_tmp`, `date_tmp`)
				VALUES
				(NULL, :id_rubrique_parent, :nomRubrique, '', '', '0', CURRENT_TIMESTAMP, 'oui', '0', 'publie', '0000-00-00 00:00:00', '', 'non', NULL, '0', '0000-00-00 00:00:00');";
      $res = $cnx->prepare($req);
      $res->bindParam(':id_rubrique_parent', $id_rubrique_parente);
      $res->bindParam(':nomRubrique', $arme->Marque);
      $res->execute();
      $sous_categorie_existantes[$j] = $arme->Marque;
      $j++;
    }
  }
  $test = "'<multi>  fr " . mysql_escape_string($arme->LibelleFR) . "   nl  " . mysql_escape_string($arme->LibelleVL) . "</multi>'";
  $req_articles[$k] = "(NULL, '', $test, '" . mysql_escape_string($arme->CdART) . "', '" . $id_rubrique_article . "', '" . mysql_escape_string($arme->PV) . "', '', '', '', '0000-00-00 00:00:00', 'publie', '0', CURRENT_TIMESTAMP, 'oui', '0000-00-00 00:00:00', '0', '0', '0', '', '0000-00-00 00:00:00', '', 'non', '0', NULL, '0', '', ''),";
  $k++;
}

$string = implode(" ", $req_articles);
//supprimer la dernière virgule
$resultat = substr($string, 0, strlen($string) - 1);

//echo $resultat;
$res = $cnx->query($resultat);
$res->execute();


Au passage, avec PDO la méthode pour échaper les données c'est quote(), ton mysql_escape_string() ne fait rien, il est pour l'extension mysql. J'ai pas corrigé, je te laisse faire.
Modifié par jb_gfx (20 Jun 2012 - 20:06)
Tiens j'ai nettoyé un peu ton code (mais je peux pas tester donc ça merdouille probablement quelque part Smiley smile ):


function machin($cnx, $arme) {
  $req = "SELECT * FROM spip_rubriques WHERE `titre` = :titre;";
  $res = $cnx->prepare($req);
  $res->bindParam(':titre', $arme);
  $res->execute();
  $rubriquePremierNiv = $res->fetch();
  $id_rubrique_parente = $rubriquePremierNiv['id_rubrique'];

  if (!$rubriquePremierNiv['titre']) {
    $req = "
        INSERT INTO `spip_moulinette`.`spip_rubriques`
        (`id_rubrique`, `id_parent`, `titre`, `descriptif`, `texte`, `id_secteur`, `maj`, `export`, `id_import`, `statut`, `date`, `lang`, `langue_choisie`, `extra`, `statut_tmp`, `date_tmp`)
        VALUES
        (NULL, :id_rubrique_parent, :nomRubrique, '', '', '0', CURRENT_TIMESTAMP, 'oui', '0', 'publie', '0000-00-00 00:00:00', '', 'non', NULL, '0', '0000-00-00 00:00:00');";

    $res = $cnx->prepare($req);
    $res->bindParam(':nomRubrique', $arme);
    $res->bindParam(':id_rubrique_parent', $id_rubrique_parente);
    $res->execute();
  }
}

$req_articles = $categorie_existantes = $sous_categorie_existantes = array();
$req_articles[0] = "INSERT INTO `spip_moulinette`.`spip_articles` (`id_article`, `surtitre`, `titre`, `soustitre`, `id_rubrique`, `descriptif`, `chapo`, `texte`, `ps`, `date`, `statut`, `id_secteur`, `maj`, `export`, `date_redac`, `visites`, `referers`, `popularite`, `accepter_forum`, `date_modif`, `lang`, `langue_choisie`, `id_trad`, `extra`, `id_version`, `nom_site`, `url_site`) VALUES ";

foreach ($armes as $arme) {
  if (in_array($arme->Type, $categorie_existantes)) {
    machin($cnx, $arme->Type);
    $categorie_existantes[] = $arme->Type;
  }

  if (in_array($arme->Marque, $sous_categorie_existantes)) {
    machin($cnx, $arme->Marque);
    $sous_categorie_existantes[] = $arme->Marque;
  }

  $test = "'<multi>  fr " . mysql_escape_string($arme->LibelleFR) . "   nl  " . mysql_escape_string($arme->LibelleVL) . "</multi>'";
  $req_articles[] = "(NULL, '', $test, '" . mysql_escape_string($arme->CdART) . "', '" . $id_rubrique_article . "', '" . mysql_escape_string($arme->PV) . "', '', '', '', '0000-00-00 00:00:00', 'publie', '0', CURRENT_TIMESTAMP, 'oui', '0000-00-00 00:00:00', '0', '0', '0', '', '0000-00-00 00:00:00', '', 'non', '0', NULL, '0', '', ''),";
}

$resultat = implode(" ", $req_articles);
//supprimer la dernière virgule
$resultat[strlen($resultat) - 1] = "\0";

$res = $cnx->query($resultat);
$res->execute();


Modifié par jb_gfx (21 Jun 2012 - 01:41)
Salut jb,

Je sais pas comment te remercier sérieux. Ça fonctionne impec et en plus ça résous un autre problème que j'avais. Je ne connaissais pas la fonction in_array() bien pratique ^^.

Par contre il ne semble pas reconnaitre la fonction quote(), mais bon ça fonctionne bien ainsi.

En tout cas merci mille fois t'es trop un boss sérieux ! merci merci merci merci !
Cool, content que ça fonctionne.

Pour quote() j'ai oublié de le changer dans le code. Si tu utilises mysql_escape_string() avec un objet PDO y'a rien qui dit que tes valeurs seront échappées correctement donc il vaut mieux passer par la méthode quote() qui est native de PDO.

Il suffit de remplacer mysql_escape_string($valeur) par $pdo->quote($valeur) (où $pdo est ton object PDO, donc dans ton cas $cnx).

Après je serais toi je passerai uniquement par des requêtes préparées dans tous les cas. Ainsi tu t'évites les risques d'oublier d’échapper ou transtyper une variable et tu réduis ainsi au maximum les risques d'injection SQL. Et surtout t'as plus jamais à y penser, faut aimer être fainéant quand on code. Mais y'a le bon et le mauvais fainéant. Smiley lol
Modifié par jb_gfx (22 Jun 2012 - 16:12)
jb_gfx a écrit :
Il suffit de remplacer mysql_escape_string($valeur) par $pdo->quote($valeur) (où $pdo est ton object PDO, donc dans ton cas $cnx).

Ah oki c'est une méthode de PDO, j'avais pas capté, j'avais simplement mis quote(), simpliste que je suis.

jb_gfx a écrit :
Après je serais toi je passerai uniquement par des requêtes préparées dans tous les cas

Merci j'en prend bonne note Smiley cligne

Merci encore en tout cas, au plaisir de te rendre l'appareil ^^