Linkkaus liitostaulun kautta PHP:ssä

Oletetaan nyt, että käyttäjä on käynyt eri kaupungeissa. Tässä tapauksessa käyttäjät taulukko voisi näyttää seuraavalta:

users
id name city
1 user1 city1, city2, city3
2 user2 city1, city2
3 user3 city2, city3
4 user4 city1

On selvää, että tällainen tietojen tallennus on väärin - kaupungit on siirrettävä erilliseen taulukkoon. Tässä se on:

cities
id name
1 city1
2 city2
3 city3

Meidän on kuitenkin tehtävä niin, että jokainen käyttäjä voi viitata useaan kaupunkiin. Kahdella taulukolla tätä ei ole mahdollista tehdä.

Tarvitsemme niin kutsutun liitostaulun, joka linkittää käyttäjän hänen kaupunkeihinsa.

Jokaisessa tämän taulukon tietueessa tallennetaan yhteys käyttäjän ja yhden kaupungin välillä. Samalla yhdelle käyttäjälle tässä taulukossa on niin monta tietuetta, kuin monessa kaupungissa hän on käynyt.

Tässä on liitostaulumme:

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

Käyttäjien taulukko tallentaa vain käyttäjien nimet ilman linkityksiä:

users
id name
1 user1
2 user2
3 user3
4 user4
5 user5

Kyselyt

Tehdään kysely, jonka avulla haemme käyttäjät yhdessä heidän kaupunkien kanssa. Tätä varten tarvitsemme kaksi liitosta: ensimmäinen liitos yhdistää käyttäjiin liitostaulun, ja toinen liitos liittyy kaupunkeihin linkkien kautta:

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

Kyselyn tulos

Kyselymme tulos PHP:ssä sisältää jokaisen käyttäjän nimen niin monta kertaa, kuin monen kaupungin kanssa hän on linkitetty:

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'],
  ];
?>

Olisi kätevämpää muuntaa tällainen taulukko ja muuttaa se seuraavaksi:

php<?php
  $res = [
    ['user1' => ['city1', 'city2', 'city3']],
    ['user2' => ['city1', 'city2']],
    ['user3' => ['city2', 'city3']],
    ['user4' => ['city1']],
  ];
?>

Kirjoitetaan koodi, joka suorittaa tällaisen muunnoksen:

php<?php
  $res = [];
  
  foreach ($data as $elem) {
    $res[$elem['user_name']][] = $elem['city_name'];
  }
  
  var_dump($res);
?>

Käytännön tehtävät

Задание 1

Oletetaan, että tuote voi kuulua useisiin kategorioihin. Kuvaile tallennusrakenne.

Задание 2

Kirjoita kysely, joka hakee tuotteet yhdessä niiden kategorioiden kanssa.

Задание 3

Näytä saadut tiedot listana ul siten, että jokaisessa li aluksi on tuotteen nimi, ja kaksoispisteen jälkeen pilkuilla eroteltuina luetellaan tämän tuotteen kategoriat. Suunnilleen näin:

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