Länkning via kopplingstabell i PHP
Antag nu att en användare har varit i olika städer. I det här fallet skulle tabellen med användare kunna ha följande utseende:
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
Det är tydligt att det är felaktigt att lagra data på detta sätt - städerna bör flyttas till en separat tabell. Här är den:
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Men vi behöver se till att varje användare kan referera till flera städer. Det är omöjligt att göra detta med bara två tabeller.
Vi behöver införa en så kallad kopplingstabell , som kommer att länka användaren till hans/hennes städer.
I varje post i denna tabell lagras en koppling mellan en användare och en stad. Samtidigt kommer det för en användare att finnas lika många poster i denna tabell som antal städer hen har varit i.
Här är vår kopplingstabell:
| 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 |
Tabellen med användare kommer endast att lagra användarnamn, utan kopplingar:
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Frågor
Låt oss skapa en fråga som hämtar användare tillsammans med deras städer. För detta behöver vi göra två kopplingar (joins): den första joinen kommer att koppla användarna till kopplingstabellen, och den andra joinen kommer via kopplingarna att ansluta städerna:
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
Frågeresultat
Resultatet av vår fråga i PHP kommer att innehålla varje användares namn lika många gånger som antalet städer hen är kopplad till:
<?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'],
];
?>
Det vore bekvämare att konvertera en sådan array och omvandla den till följande:
<?php
$res = [
'user1' => ['city1', 'city2', 'city3'],
'user2' => ['city1', 'city2'],
'user3' => ['city2', 'city3'],
'user4' => ['city1'],
];
?>
Låt oss skriva kod som utför en sådan konvertering:
<?php
$res = [];
foreach ($data as $elem) {
$res[$elem['user_name']][] = $elem['city_name'];
}
var_dump($res);
?>
Praktiska uppgifter
Antag att en produkt kan tillhöra flera kategorier. Beskriv lagringsstrukturen.
Skriv en fråga som hämtar produkter tillsammans med deras kategorier.
Visa erhållna data som en lista
ul så att i varje li först
står produktens namn, och efter ett kolon, separerade med
kommatecken, listas kategorierna för denna produkt.
Ungefär så här:
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>