Probleme de array_unique dans une liste

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Probleme de array_unique dans une liste

par muriel » 04 sept. 2005, 20:42

tu es vraiment trop genial cyrano, je vais commencer à mettre tous cela en forme, et quand se sera fait je reviens pour dire ou j'en suis je pense que demain dans l'apres midi j'aurais du nouveau.

encore merci à vous tous, merci à toi cyrano pour tous ton travail et à tres bientot, bonne soirée à tous

par Cyrano » 04 sept. 2005, 19:50

Ok, alors mettons que tu as une commande pour le commercial "Pierre Dupont" par l'Annonceur "La voix de la Pub" pour diffusion de dix messages le 15 septembre.
<?php
/* Données du commercial */
$nom = "Dupont";
$prenom = "Pierre";
$num_portable = "0678901234";

/* Données de l'annonceur */
$nom_annonceur = "La voix de la Pub";
$tel_annonceur = "0145012345";
$fax_annonceur = "0145012346";
$region_annonceur = "Ile de France";

/* Données commandes */
$date_diffusion = 2005/09/15;
$nb_msgs = 10;

/* On construit les requêtes */
/* Ajout du commercial (si il n'existe pas déjà bien sûr) */
$sql_1 = "INSERT INTO commercial VALUES ('', '". $nom ."', '". $num_portable ."')";
/* Ajout de l'annonceur (S'il n'existe pas déjà dans la table bien sûr */
$sql_2 = "INSERT INTO annonceurs VALUES ('','". $nom_annonceur ."','".  $tel_annonceur."','". $fax_annonceur ."','". $region_annonceur ."')";
/* Ajout de la commande */
$sql_3 = "INSERT INTO details_commande VALUES('','". $date_diffusion ."','". $nb_msgs ."')";

/* Maintenant on exécute tout ça */
// ... ligne de connexinon à la base, on passe rapidement
$exec_1 = mysql_query($sql_1);
$cle_comm = mysql_insert_id($exec_1);
$exec_2 = mysql_query($sql_1);
$cle_ann = mysql_insert_id($exec_2);
$exec_3 = mysql_query($sql_1);
$cle_det = mysql_insert_id($exec_3);

/* Maintenant on peut complééter la table intermédiaire */
$sql_4 = "INSERT INTO commandes_2005 VALUES(". $cle_comm .",". $cle_ann .",". $cle_dat .")";
$fin = mysql_query($sql_4);
/* Terminé, tout est inséré */
?>
Mais regarde bien les commentaires: tu ne sera pas obligatoirement obligée d'ajouter un commercial ou un annonceur: s'il existe déjà dans la liste, tu as juste besoin de la clé primaire et tu ne fais une insertion QUE pour un nouvel annonceur et/ou un nouveau commercial.

Par contre tu auras en principe toujours une nouvelle commande. Mais dans l'ensemble, la procédure est toujours la même.

Suis-tu le schéma ?

par muriel » 04 sept. 2005, 19:15

là j'avoue j'ai un peu de mal, mais je vais m'accrocher et y arriver.
juste j'aurais besoin cyrano d'un petit exemple bien concret pour que je puisse mieux comprendre comment créer cette page d'insertion, car là j'avoue je suis un peu dépasser
"conserver une clé dans une variable et recommencer avec la table suivante en faisant la même chose et quand chacune des tables est mise à jour, je peux faire l'insertion des clés dans la table commandes_2005"
là, j'imagine meme pas par quoi il faut que je commence :oops:

en esperant que tu auras pitié d'une debutante qui s'accroche, mais qui face à l'impossible ne peut qu'esperer qu'une ame charitable aura pitié d'elle, je sais que je suis un peu exigeante, mais si je veux pouvoir continuer il va falloir m'aider un tout petit peu cyrano, por favor !!!

par Cyrano » 04 sept. 2005, 18:41

Tu as tout compris. :D
Alors on aurait pu ajouter une difficulté supplémentaire, mais par bonheur, MySQL offre un type de tables (MyISAM) qui permet de s'en dispenser. Je veux parler de ce qu'on nomme "l'intégrité référentielle". Si au lieu de table de type MyISAM on avait utilisé des tables de type InnoDB, on aurait pu appliquer cette intégrité. Mais je ne te le recommande pas.

Néanmoins, tu dois quand même assurer cette intégrité par programmation. Qu'est-ce que ça veut dire mon charabia ? (si, tu l'as pensé, j'ai entendu :langue: )

Suppose que lors de l'insertion d'une nouvelle série de données, tu commences par remplir la table commandes_2005 : Que vas-tu mettre dans les champs ? Tu ne peux rien mettre parce que tu as besoin de savoir quelle sera la clé primaire de chacune des autres tables. Si tu enregistrais des numéros arbitraires, tu aurais l'obligation d'utiliser ces mêmes numéros dans chacune des autres tables pour établir un lien logique. Mais si un de ces numéros existe déjà, MySQL va te jeter en te parlant de "duplicate key" : un doublon interdit par la clé primaire.

Donc la procédure consiste à remplir d'abord les autres table en récupérant à chaque fois la clé primaire générée. Et on revient doucement au PHP : pour avoir ceci, tu fais un enregistrement dans une table et tu utilises, juste après l'exécution de l'insertion, mysql_insert_id() qui te retourne la clé générée: tu conserves cette clé dans une variable, tu recommences avec la table suivante et faisant la même chose: quand chacune des tables est mise à jour, tu peux faire l'insertion des clés dans la table commandes_2005.

Est-ce que ça va mieux comme ça ?

par muriel » 04 sept. 2005, 18:29

c'est genial cyrano vraiment c'est genial, je crois avoir tous compris ou presque, mais concretement comment je les remplis ensuite mes tables, car je n'ai jamais travaillé avec plusieurs tables, je fais mon formulaire jusque là je suis ok, mais ensuite dans mon fichier en .php qui integre les données à la BD je dois lui indiquer comment ou je dois mettre mes informations dans quelle table etc... car jusqu'à aujourd'hui c'etait simple je lui disait mets tel informations dans tel champ et je m'occupait de la table qu'au debut style:
mysql_query ("INSERT INTO commandes_2005 VALUES
dois je faire plusieurs
mysql_query ("INSERT INTO commandes_2005 VALUES
l'une pour annonce, l'autre pour client et la derniere pour commandes_2005 ???

par Cyrano » 04 sept. 2005, 18:12

Absolument, j'ai une idée en arrière-plan.

Alors petite mise au point, ceci n'est pas du PHP mais du SQL, et même un peu avant ça, c'Est de la modélisation de base de données.

Explication de base : Prenons pour exemple imaginaire une table client et une table téléphone. Dans la table client, tu enregistres le nom, le prénom et l'adresse. Mais pour le téléphone, il pourrait y avoir un téléphone de domicile, un fax ou un portable ou les trois ou aucun. COmment éviter d'avoir des champs vides ? En créant une table à part avec deux champs : le numéro et le type de téléphone (domicile, fax, mobile) . Comment est-ce qu'on va relier les deux ? Chacune des deux tables doit avoir une clé primaire. ON ajoute donc à chacune un champ de type INT en auto_increment et en clé primaire. La clé primaire sert à identifier une ligne de façon unique puisque la valeur d'un champ de clé primaire n'accès aucun doublon. Tu ne l'utiliseras en principe pas pour sa valeur en tant que telle mais comme point de repère virtuel. Même chose pour les deux tables. Donc ma table client aura un champ cli_id et ma table telephone un champ tel_id.

Pourquoi et comment ?
Je sais au départ qu'un client peut avoir de zéro à n numéros de téléphones, mais je sais également que chaque téléphone ne correspond qu'à un et un seul client. Je peux donc ajouter dans ma table téléphone un nouveau champ qui sera une clé étrangère correspondant à la valeur de la clé primaire de ma table client. Comme ça, si mon client a 30 numéros de téléphones, j'aurai mes trente lignes dans la table téléphone mais je pourrai savoir lesquels grâce à la clé étrangère puisque c'est la même valeur que la clé primaire de ma table client : un requête pour obtenir tous les numéros et le type d'appareil pour un client précis se fera donc de la manière suivante:

Code : Tout sélectionner

SELECT tel_num, tel_type FROM telephone WHERE cli_id = 12;
Ici, j'ai mis 12 pour l'exemple, ça n,a aucune autre signification.

Je crois que jusque là, tu dne devrais pas avoir eu trop de difficultés à suivre.

Maintenant, revenons à ton problème qui est un poil plus complexe. Nous avons au départ deux tables : client et annonceur. Nous savons également qu'un client peut avoir affaire avec 0 à n annonceurs et qu'un annonceur peut traiter 0 à n clients : là, j'ai un problème d'identification: comment vais-je faire pour connaitre tous les clients d'un annonceur si je mets dans la table annonceurs la clé primaire de la table clients ? En mettant la clé dans ce sens, je pourrais facilement connaitre tous les annonceurs d'un client, mais pas l'inverse. Bon mais alors si j'inverse, je mets à la place en clé étrangère dans la table clients une clé étrangère correspondant à la clé primaire de l'annonceur. Je résouds mon permier problème et je peux connaître tous les clients d'un annonceur, mais je ne peux plus faire l'inverse.

Je te vois penser à l'idée : "alors mettons les deux, une dans chaque" : TU pourrais essayer et je te regarderai t'arracher les cheveux pour faire des requêtes après :langue:

Donc la solution simple : on crée ce qu'on appelle une relation, c'est à dire en fin de compte une table intermédiaire qui permet les deux sens: cette table intermédiaire va comporter en clé étrangères les ceux clés primaires des deux tables clients et annonceurs, c'est tout : et bien entendu selon ce schéma simple (on oublie la commande elle-même et les détails que j'ai évoqué dans une réponse précédente, la clé primaire de cette table intermédiaire est composite et faite des deux clés étrangères réunies. Il ne peut de cette façon jamais y avoir de doublons.

Mais alors me diras-tu : pourquoi une clé primaire en plus dans le schéma que j'ai envoyé tout à l'heure ? Si tu as lu attentivement ce que j'ai noté, j'ai évoqué une autre table detail_commande qui comporte les champs décrivant chaque commande : On doit la relier aussi bien à un lcient qu'à un annonceur : on passera par notre table intermédiaire commandes_2005 en ajoutant une troisième clé étrangère qui sera la clé primaire de la table details_commandes.

Mon schéma devient donc :

Code : Tout sélectionner

+-------------------------------------------+ | annonceur | +-------------------------------------------+ |ann_id INT NOT NULL Auto_increment <PK> | |ann_nom VARCHAR(32) | |ann_telephone VARCHAR(16) | |ann_fax VARCHAR(16) | |ann_region VARCHAR(32) | +-------------------------------------------+ | | +-------------------------------------------+ +-------------------------------------------+ | commandes_2005 | | details_commmande | +-------------------------------------------+ +-------------------------------------------+ |ann_id INT NOT NULL <PK, FK> |----------|det_id <PK>| |com_id INT NOT NULL <PK, FK> | |det_date_diff | |det_id INT NOT NULL <PK, FK> | |det_nb_msg | +-------------------------------------------+ +-------------------------------------------+ | | +-------------------------------------------+ | commercial | +-------------------------------------------+ |com_id INT NOT NULL Auto_increment <PK> | |com_portable VARCHAR(16) | +-------------------------------------------+
Là, je ne vais pas plus loin pour l'instant, dis-moi ce que tu n'as pas compris éventuellement ou ce qui n'est pas clair.

par muriel » 04 sept. 2005, 17:41

phpMyAdmin j'avoue que je n'y avait pas pensé je devrais peut etre m'y pencher serieusement vu mes erreurs !!!
alors pour les 3 tables, voici ce que j'ai compris (se sera plus rapide comme cela, je pense !!!) c'est pour que chacune des tables et des key differentes ??? que les informations soit mieux repartis par groupes et non pas tous dans la meme table (ça c'est ce que j'ai compris) chaque groupe a son id.
Par contre j'avoue que pour la table commandes_2005 je n'ai stritement rien compris, et je veux bien que tu m'expliques d'abord à quoi elle sert à part y mettre mes commandes mais alors comment ensuite faire le lien entre les annonceurs et les clients ??? ça c'est vrai que je ne comprend pas tres bien comment je vais faire ???
mais je te fais confiance cyrano je crois bien que tu as une idée derrière la tete ???

@++

par Cyrano » 04 sept. 2005, 17:05

Comme éditeur, pourquoi ne pas créer les tables directement via phpMyAdmin ? Sinon, l'éditeur d'apprentissage par excellence, c'est le bloc-notes. ;)

Mais je voudrais être sûr que tu as bien saisi le schéma et le pourquoi des trois tables, et par exemple pourquoi mettre les clés étrangères de la table commandes_2005 en INT plutôt qu'en VARCHAR :-k

par muriel » 04 sept. 2005, 16:56

Y am simple and stupid !!!!

j'ai tout simplement mon exemple de base qui est basé sur l'exportation de easyphp, c'est exactement comme cela qu'il me les exporte ensuite je vais dans mon bloc-notes et je fais mes changements (mais si je dois travailler avec un editeur en particulier dites le moi et je cours le telecharger) . Je crois que vous allez vous arracher les cheveux avec moi... je suis désolée de vous faire autant de soucis !!!!
pour la table intermediaire c'est une erreur de ma part je n'ai pas fais attention je le change de suite, et pour les clès en triple je fais la modif de suite aussi, lolll !!! je suis en train de prendre un cours privé de PHP...

encore merci pour tous cyrano j'espere juste que tu ne vas pas craquer à force !!!

par Cyrano » 04 sept. 2005, 16:40

Voudrais-tu m'Expliquer avec quoi tu crées tes tables : c'est quoi ces index triples à chaque fois ?
Et seconde question : pourquoi as-tu mis dans la table intermédiaire les clés étrangères en VARCHAR En champ NULL en plus ?

Je veux bien t'aider, mais si tu ne comprends pas un truc, on ira plus rapidement si tu me le dis au lieu d'interpréter de travers. J'ai l'impression que tu n'as pas saisi le tôle de la table commandes_2005 dans ce schéma:

Code : Tout sélectionner

CREATE TABLE `annonceur` ( `ann_id` int(11) NOT NULL Auto_increment, `ann_annonceur` VARCHAR(32) default NULL, `ann_nom` VARCHAR(32) default NULL, `ann_telephone` VARCHAR(16) default NULL, `ann_fax` VARCHAR(16) default NULL, PRIMARY KEY (`ann_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; CREATE TABLE `commandes_2005` ( `cmd_id` int(11) NOT NULL Auto_increment, `ann_id` int(11) NOT NULL , `com_id` int(11) NOT NULL , PRIMARY KEY (`cmd_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; CREATE TABLE `client` ( `com_id` int(11) NOT NULL Auto_increment, `com_client` VARCHAR(32) default NULL, `com_region` VARCHAR(32) default NULL, `com_commercial` VARCHAR(32) default NULL, `com_portable` VARCHAR(16) default NULL, PRIMARY KEY (`com_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

par muriel » 04 sept. 2005, 15:52

oki cyrano j'ai crée mes 3 tables j'ai fais quelques changements donc je te mets mes 3 tables pour que tu puisses me dire si c'est bon:

Code : Tout sélectionner

- Structure de la table `annonceur ` -- CREATE TABLE `annonceur` ( `ann_id` int(11) NOT NULL Auto_increment, `ann_annonceur` VARCHAR(32) default NULL, `ann_nom` VARCHAR(32) default NULL, `ann_telephone` VARCHAR(16) default NULL, `ann_fax` VARCHAR(16) default NULL, PRIMARY KEY (`ann_id`), UNIQUE KEY `ann_id_2` (`ann_id`), KEY `id` (`ann_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

Code : Tout sélectionner

-- Structure de la table `commandes_2005` -- CREATE TABLE `commandes_2005` ( `cmd_id` int(11) NOT NULL Auto_increment, `ann_id` VARCHAR(32) default NULL, `com_id` VARCHAR(16) default NULL, PRIMARY KEY (`cmd_id`), UNIQUE KEY `cmd_id_2` (`cmd_id`), KEY `id` (`cmd_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

Code : Tout sélectionner

-- Structure de la table `client` -- CREATE TABLE `client` ( `com_id` int(11) NOT NULL Auto_increment, `com_client` VARCHAR(32) default NULL, `com_region` VARCHAR(32) default NULL, `com_commercial` VARCHAR(32) default NULL, `com_portable` VARCHAR(16) default NULL, PRIMARY KEY (`com_id`), UNIQUE KEY `com_id_2` (`com_id`), KEY `id` (`com_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
comme tu peux le constater j'ai changé la table commercial en table client car dans access j'ai une table annonceur qui correspond à la premiere, ensuite j'ai une table commandes_2005 et pour terminer une table client.
En esperant avoir bien fait. Si ce n'etait pas le cas n'hesite pas à me le dire.

par Cyrano » 04 sept. 2005, 14:57

Pas de problème. Donc ta base sommairement modélisée devrait ressembler à une structure dans ce genre : Regarde si tu y vois plus de cohérence et éventuellement s'il manque des éléments ?

Code : Tout sélectionner

+-------------------------------------------+ | annonceur | +-------------------------------------------+ |ann_id INT NOT NULL Auto_increment <PK> | |ann_nom VARCHAR(32) | |ann_telephone VARCHAR(16) | |ann_fax VARCHAR(16) | |ann_region VARCHAR(32) | +-------------------------------------------+ +-------------------------------------------+ | commandes_2005 | +-------------------------------------------+ |cmd_id INT NOT NULL Auto_increment <PK> | |ann_id INT NOT NULL <FK> | |com_id INT NOT NULL <FK> | +-------------------------------------------+ +-------------------------------------------+ | commercial | +-------------------------------------------+ |com_id INT NOT NULL Auto_increment <PK> | |com_portable VARCHAR(16) | +-------------------------------------------+
La seule chose qui fait défaut dans l'histoire et qui m'a obligé à ajouter une clé primaire supplémentaire dans la table commandes_2005, c'est l'absence de la nature de la commande dont les détails sont, je suppose, décris dans une autre table, auquel cas, ce qui devrait remplacer cette clé primaire est une clé étrangère qui serait la clé primaire de la table détail_commande. Et la table commande_2005 aura donc en clé primaire une clé composite faite avec les trois clés étrangères.

Est-ce que tu t'y retrouves à peu près quand même dans ces explications (je conçois que ce n'est pas forcément évident à visualiser) ?

par muriel » 04 sept. 2005, 14:48

tu as tout à fait raison cyrano il en faut une troisieme en intermediaire car un annonceur peut faire affaire avec plusieurs commerciaux et qu'un commercial peut s'addresser à plusieurs annonceurs
et un client peux faire affaire avec plusieurs commerciaux (puisque si un commercial part il est remplacé par un autre donc c'est tout à fait possible)
donc je pense que je peux te confirmer qu'il faut une troisieme table cyrano.
Désolée de te faire faire tout ce travail cyrano, merci pour tous

par Cyrano » 04 sept. 2005, 14:41

Je me demande si tu réalises un truc : ce que tu me décris, ce sont donc deux entités distinctes : l'annonceur d'un coté, le commercial de l'autre : au départ, tu ne peux pas raisonnablement mettre tout ça en vrac dans la même table. Cependant, comme un annonceur peut faire affaire avec plusieurs commerciaux, et qu'un commercial peut s'addresser à plusieurs annonceurs, on va avoir une relation entre les deux qui va devenir une troisième table. À moins qu'un client ne puisse faire affaire qu'à un seul commercial ? (exclusivité ?) De toutes façons, on aura au minimum deux tables. Confirme s'il te plait pour savoir s'il en faut une troisième en intermédiaire.

par muriel » 04 sept. 2005, 14:15

oki, alors je t'explique les liens cyrano...
c'est une base de données pour une société qui fait des pubs pour les radios, alors l'annonceur c'est le magasin qui veut faire sa pub le nom ainsi que le telephone et le fax correspondent à cette annonceur, exemple:
magasin levis nom du client qui tiens ce magasin avec son tel ainsi que son fax
le client c'est la radio qui demande à faire la pub (à la société qui crée les pubs) avec la region ou est la radio ainsi que le commercial qui a demarché l'annonceur et le portable du commercial

voilà je crois avoir tout dit, du moins je l'espere.... sinon n'hesite pas à me poser d'autres questions je suis rivé à mon PC

et encore merci pour tous.....