Legătura prin tabela de legătură în PHP
Să presupunem acum că utilizatorul a fost în diferite orașe. În acest caz, tabela cu utilizatori ar putea avea următoarea formă:
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
Este clar că stocarea datelor în acest fel este incorectă - orașele trebuie mutate într-un tabel separat. Iată-l:
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Cu toate acestea, trebuie să facem astfel încât fiecare utilizator să poată fi legat de mai multe orașe. Folosind două tabele, acest lucru este imposibil.
Va trebui să introducem așa-numita tabelă de legătură, care va lega utilizatorul de orașele sale.
În fiecare înregistrare a acestui tabel se va stoca o legătură între un utilizator și un oraș. În același timp, pentru un utilizator, în acest tabel vor fi atâtea înregistrări, câte orașe a vizitat.
Iată tabela noastră de legătură:
| 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 |
Tabela cu utilizatori va stoca doar numele utilizatorilor, fără legături:
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Interogări
Să facem o interogare cu care vom extrage utilizatorii împreună cu orașele lor. Pentru aceasta, va trebui să facem două join-uri: primul join va atașa la utilizatori tabela de legătură, iar al doilea join prin legături va atașa orașele:
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
Rezultatul interogării
Rezultatul interogării noastre în PHP va conține numele fiecărui utilizator de atâtea ori, cu câte orașe este legat:
<?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'],
];
?>
Ar fi mai convenabil să convertim un astfel de vector și să-l transformăm în următorul:
<?php
$res = [
['user1' => ['city1', 'city2', 'city3']],
['user2' => ['city1', 'city2']],
['user3' => ['city2', 'city3']],
['user4' => ['city1']],
];
?>
Să scriem codul care realizează o astfel de conversie:
<?php
$res = [];
foreach ($data as $elem) {
$res[$elem['user_name']][] = $elem['city_name'];
}
var_dump($res);
?>
Sarcini practice
Să presupunem că un produs poate aparține mai multor categorii. Descrieți structura de stocare.
Scrieți o interogare care va extrage produsele împreună cu categoriile lor.
Afișați datele obținute sub forma unei liste
ul astfel încât în fiecare li la început
să fie numele produsului, iar după două puncte, prin
virgulă, să fie enumerate categoriile acestui produs.
Cam așa:
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>