Seostamine läbi seostustabeli PHP-s
Oletame nüüd, et kasutaja on käinud erinevates linnades. Sel juhul võiks kasutajate tabel välja näha järgmine:
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
On selge, et andmeid niimoodi salvestada on vale - linnad tuleks viia eraldi tabelisse. Siin on see:
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Siiski peame me tegema nii, et iga kasutaja saaks viidata mitmele linnale. Seda kahe tabeliga teha on võimatu.
Meil on vaja kasutusele võtta nn seostustabel, mis seob kasutaja tema linnadega.
Selle tabeli igas kirjes hoitakse seost kasutaja ja ühe linna vahel. Samas ühe kasutaja jaoks on selles tabelis nii palju kirjeid, kui paljudes linnades ta on käinud.
Siin on meie seostustabel:
| 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 |
Kasutajate tabel hoiab ainult kasutajate nimesid, ilma seosteta:
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Päringud
Teeme päringu, mille abil võtame kasutajad koos nende linnadega. Selleks peame tegema kaks ühendust (JOIN): esimene JOIN ühendab kasutajatega seostustabeli, ja teine JOIN ühendab linnad seoste kaudu:
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
Päringu tulemus
Meie päringu tulemus PHP-s sisaldab iga kasutaja nime nii mitu korda, kui paljude linnadega ta on seotud:
<?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'],
];
?>
Oleks mugavam sellist massiivi ümber teha ja muuta see järgnevasse vormi:
<?php
$res = [
'user1' => ['city1', 'city2', 'city3'],
'user2' => ['city1', 'city2'],
'user3' => ['city2', 'city3'],
'user4' => ['city1'],
];
?>
Kirjutame koodi, mis teeb sellise teisenduse:
<?php
$res = [];
foreach ($data as $elem) {
$res[$elem['user_name']][] = $elem['city_name'];
}
var_dump($res);
?>
Praktilised ülesanded
Oletagem, et toode võib kuuluda mitmesse kategooriasse. Kirjeldage salvestusstruktuuri.
Kirjutage päring, mis võtab tooted koos nende kategooriatega.
Kuva saadud andmed loendina
ul nii, et igas li-s oleks algul
toote nimi ja peale koolonti loetletud
selle toote kategooriad komadega.
Umbes nii:
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>