Liaison via une table de liaison en PHP
Supposons maintenant qu'un utilisateur ait été dans différentes villes. Dans ce cas, la table des utilisateurs pourrait avoir l'aspect suivant :
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
Il est clair que stocker les données ainsi est incorrect - les villes doivent être déplacées dans une table séparée. La voici :
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Cependant, nous devons faire en sorte que chaque utilisateur puisse être lié à plusieurs villes. Avec deux tables, cela est impossible.
Nous devons introduire ce qu'on appelle une table de liaison, qui reliera l'utilisateur à ses villes.
Chaque enregistrement de cette table stockera un lien entre un utilisateur et une ville. Ainsi, pour un utilisateur, il y aura autant d'enregistrements dans cette table que de villes où il est allé.
Voici notre table de liaison :
| id | user_id | city_id |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 2 | 2 |
| 6 | 3 | 2 |
| 7 | 3 | 3 |
| 8 | 4 | 1 |
La table des utilisateurs ne stockera que les noms des utilisateurs, sans les liens :
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Requêtes
Créons une requête qui récupérera les utilisateurs avec leurs villes. Pour cela, nous devons effectuer deux jointures : la première jointure reliera la table de liaison aux utilisateurs, et la seconde jointure reliera les villes via les liaisons :
SELECT
users.name as user_name, cities.name as city_name
FROM
users
LEFT JOIN users_cities ON users_cities.user_id=users.id
LEFT JOIN cities ON users_cities.city_id=cities.id
Résultat de la requête
Le résultat de notre requête en PHP contiendra le nom de chaque utilisateur autant de fois qu'il est lié à des villes :
<?php
$arr = [
['user_name' => 'user1', 'city_name' => 'city1'],
['user_name' => 'user1', 'city_name' => 'city2'],
['user_name' => 'user1', 'city_name' => 'city3'],
['user_name' => 'user2', 'city_name' => 'city1'],
['user_name' => 'user2', 'city_name' => 'city2'],
['user_name' => 'user3', 'city_name' => 'city2'],
['user_name' => 'user3', 'city_name' => 'city3'],
['user_name' => 'user4', 'city_name' => 'city1'],
];
?>
Il serait plus pratique de convertir un tel tableau et de le transformer en celui-ci :
<?php
$res = [
['user1' => ['city1', 'city2', 'city3']],
['user2' => ['city1', 'city2']],
['user3' => ['city2', 'city3']],
['user4' => ['city1']],
];
?>
Écrivons le code effectuant une telle conversion :
<?php
$res = [];
foreach ($data as $elem) {
$res[$elem['user_name']][] = $elem['city_name'];
}
var_dump($res);
?>
Tâches pratiques
Supposons qu'un produit puisse appartenir à plusieurs catégories. Décrivez la structure de stockage.
Écrivez une requête qui récupérera les produits avec leurs catégories.
Affichez les données obtenues sous forme de liste
ul de sorte que dans chaque li se trouve d'abord
le nom du produit, et après deux points, soient énumérées
les catégories de ce produit, séparées par des virgules.
Par exemple :
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>