Probleme de array_unique dans une liste

Mammouth du PHP | 19672 Messages

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.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 101 Messages

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 ???
muriel

Mammouth du PHP | 19672 Messages

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 ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 101 Messages

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 !!!
muriel

Mammouth du PHP | 19672 Messages

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 ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 101 Messages

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
muriel