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:

users
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:

cities
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:

users_cities
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:

users
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:

sqlSELECT
  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<?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<?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<?php
  $res = [];
  
  foreach ($data as $elem) {
    $res[$elem['user_name']][] = $elem['city_name'];
  }
  
  var_dump($res);
?>

Gyakorlati feladatok

Задание 1

Tegyük fel, hogy egy termék több kategóriába is tartozhat. Írja le a tárolás szerkezetét.

Задание 2

Írjon lekérdezést, amely kiszedi a termékeket a kategóriáikkal együtt.

Задание 3

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:

html<ul>
  <li>product1: category1, category2, category3</li>
  <li>product2: category1, category3</li>
  <li>product3: category1</li>
</ul>