Kapcsolótáblán keresztüli összekapcsolás PHP-ban
Tegyük fel, hogy a felhasználó különböző városokban járt. Ebben az esetben a felhasználók táblája a következőképpen nézhet ki:
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
Érthető, hogy az adatok ily módon történő tárolása helytelen - a városokat ki kell szervezni egy külön táblába. Itt van:
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Azonban úgy kell eljárnunk, hogy minden felhasználó több városra is hivatkozhat. Két táblával ezt lehetetlen megtenni.
Be kell vezetnünk egy úgynevezett kapcsolótáblát, amely összekapcsolja a felhasználót a városaival.
Ennek a táblának minden egyes bejegyzésében egy felhasználó és egy város közötti kapcsolat lesz tárolva. Egy felhasználó esetében ebben a táblában annyi bejegyzés lesz, ahány városban járt.
Itt van a kapcsolótáblánk:
| 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 |
A felhasználók táblája csak a felhasználók neveit fogja tárolni, kapcsolatok nélkül:
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Lekérdezések
Készítsünk egy lekérdezést, amellyel ki tudjuk szedni a felhasználókat a városaikkal együtt. Ehhez két összekapcsolásra lesz szükségünk: az első összekapcsolja a felhasználókat a kapcsolótáblával, a második összekapcsolás pedig a kapcsolatokon keresztül csatolja hozzá a városokat:
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
A lekérdezés eredménye
Lekérdezésünk eredménye PHP-ban annyiszor fogja tartalmazni minden egyes felhasználó nevét, ahány várossal kapcsolódik:
<?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'],
];
?>
Kényelmesebb lenne egy ilyen tömböt átkonvertálni és a következővé alakítani:
<?php
$res = [
['user1' => ['city1', 'city2', 'city3']],
['user2' => ['city1', 'city2']],
['user3' => ['city2', 'city3']],
['user4' => ['city1']],
];
?>
Írjunk kódot, amely végrehajtja az ilyen átalakítást:
<?php
$res = [];
foreach ($data as $elem) {
$res[$elem['user_name']][] = $elem['city_name'];
}
var_dump($res);
?>
Gyakorlati feladatok
Tegyük fel, hogy egy termék több kategóriába is tartozhat. Írja le a tárolás szerkezetét.
Írjon lekérdezést, amely kiszedi a termékeket a kategóriáikkal együtt.
Jelenítse meg a kapott adatokat egy ul listaként
úgy, hogy minden egyes li elemen először
álljon a termék neve, majd kettőspont után vesszővel
elválasztva felsorolva a termék kategóriáit.
Hozzávetőlegesen így:
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>