Liên kết thông qua bảng liên kết trong PHP
Bây giờ giả sử người dùng đã ở nhiều thành phố khác nhau. Trong trường hợp này, bảng người dùng có thể có dạng sau:
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
Rõ ràng là lưu trữ dữ liệu như vậy không đúng - thành phố cần được tách ra thành một bảng riêng. Đây là bảng đó:
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Tuy nhiên, chúng ta cần làm sao để mỗi người dùng có thể tham chiếu đến nhiều thành phố. Chỉ với hai bảng thì không thể làm được điều này.
Chúng ta cần giới thiệu cái gọi là bảng liên kết, nó sẽ liên kết người dùng với các thành phố của họ.
Mỗi bản ghi trong bảng này sẽ lưu trữ một liên kết giữa một người dùng và một thành phố. Đồng thời, đối với một người dùng, trong bảng này sẽ có bao nhiêu bản ghi tương ứng với số thành phố mà họ đã từng ở.
Đây là bảng liên kết của chúng ta:
| 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 |
Bảng người dùng sẽ chỉ lưu trữ tên người dùng, không có các liên kết:
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Truy vấn
Hãy tạo một truy vấn, với sự trợ giúp của nó lấy ra người dùng cùng với các thành phố của họ. Để làm điều này, chúng ta cần thực hiện hai phép nối (join): phép nối đầu tiên sẽ kết nối bảng liên kết với người dùng, và phép nối thứ hai qua các liên kết sẽ kết nối các thành phố:
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
Kết quả truy vấn
Kết quả truy vấn của chúng ta trong PHP sẽ chứa tên của mỗi người dùng lặp lại bao nhiêu lần, tương ứng với số thành phố mà họ được liên kết:
<?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'],
];
?>
Sẽ thuận tiện hơn nếu chuyển đổi một mảng như vậy và biến nó thành mảng sau:
<?php
$res = [
['user1' => ['city1', 'city2', 'city3']],
['user2' => ['city1', 'city2']],
['user3' => ['city2', 'city3']],
['user4' => ['city1']],
];
?>
Hãy viết mã thực hiện việc chuyển đổi như vậy:
<?php
$res = [];
foreach ($data as $elem) {
$res[$elem['user_name']][] = $elem['city_name'];
}
var_dump($res);
?>
Bài tập thực hành
Giả sử một sản phẩm có thể thuộc về nhiều danh mục. Hãy mô tả cấu trúc lưu trữ.
Viết truy vấn lấy ra các sản phẩm cùng với danh mục của chúng.
Hiển thị dữ liệu thu được dưới dạng danh sách
ul sao cho trong mỗi li, đầu tiên
là tên sản phẩm, sau dấu hai chấm, liệt kê
các danh mục của sản phẩm này, cách nhau bằng dấu phẩy.
Ví dụ như sau:
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>