БлогNot. PHP: связь "многие ко многим" между двумя таблицами

Помощь дата->рейтинг Поиск Почта RSS канал Статистика nickolay.info Домой

PHP: связь "многие ко многим" между двумя таблицами

Задача будет не слишком отличаться от аналогичной для "оффлайновой" СУБД вроде ACCESS, по крайней мере, мы по-прежнему реализуем связь "многие ко многим" как пару связей "один ко многим".

При использовании связки PHP+MySQL нам достаточно продемонстрировать, как извлекать категории для заданного объекта и объекты, относящиеся к заданной категории, а исключение дублирующихся связей можно сделать просто с помощью дополнительного запроса. Структура БД может быть в простейшем случае такой (выполните этот запрос в PHPMyAdmin после создания пустой базы с именем my):

create table if not exists categories (
 id int primary key auto_increment, 
 category varchar(32)
);

create table if not exists objects (
 id int primary key auto_increment, 
 object varchar(32)
);

create table if not exists links (
 id_category int, 
 id_object int
);

insert into categories (id,category) values 
 (1,'Notes'),
 (2,'Balls'),
 (3,'Rating');

insert into objects (id,object) values 
 (1,'Admin'),
 (2,'User');

insert into links (id_category,id_object) values 
 (1,1), (2,1), (2,2), (3,2);

Заодно добавлено несколько записей и связей, чтоб было что выводить.

Напишем скрипт, показывающий получение всех объектов категории, всех категорий, имеющихся у объекта, а также добавление/удаление связей.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
 "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
 <meta content="text/html; charset=Windows-1251" http-equiv="content-type">
 <title>Many-to-Many Relationship</title>
</head><body>

<?php
 define ('DB_HOST','localhost'); //имя хоста //(*) 1
 define ('DB_LOGIN','root'); //логин
 define ('DB_PASSWORD','root'); //пароль
 define ('DB_NAME','my'); //имя БД
 mysql_connect (DB_HOST, DB_LOGIN, DB_PASSWORD);
 mysql_select_db (DB_NAME);
 $action = ''; $cat = $obj = '';
 if (isset($_GET['cat'])) $cat = abs(intval(trim($_GET['cat'])));
 if (isset($_GET['obj'])) $obj = abs(intval(trim($_GET['obj'])));
 if (isset($_GET['action'])) $action = htmlspecialchars(trim($_GET['action']));
 if (!empty($action)) {
  if (!empty($cat)) {
   $result1 = mysql_fetch_array(mysql_query('select id from categories where id='.$cat));
   if (!$result1) { 
    $cat='';
    echo '<br>Передан несуществующий id категории скорректировано на "пусто"';
   }
  }
  if (!empty($obj)) {
   $result2 = mysql_fetch_array(mysql_query('select id from objects where id='.$obj)); //(*) 2
   if (!$result2) { 
    $obj='';
    echo '<br>Передан несуществующий id объекта скорректировано на "пусто"';
   }
  }
 } 
 if (!empty($cat) && !empty($obj)) {
  $sql = 'select * from links where id_category='.$cat.' and id_object='.$obj;
  $result = mysql_query ($sql);
  $n = mysql_num_rows ($result);
  switch ($action) {
   case 'add':
    if ($n==0) {
     $sql = 'insert into links (id_category,id_object) values ('.$cat.','.$obj.')';
     $result = mysql_query ($sql);
     echo '<br>Запрос на добавление выполнен';
    }
    else echo '<br>Связь уже существует, повторно не добавляем';
   break;
   case 'del':
    if ($n>0) {
     $sql = 'delete from links where id_category='.$cat.' and id_object='.$obj;
     $result = mysql_query ($sql);
     echo '<br>Запрос на удаление выполнен';
    }
    else echo '<br>Связь не задана, нечего удалять';
   break;
   default:
    echo '<br>'.($n==0?'Не связано':'Связано');
   break;
  }
 }
 else {
  $action='show';
  if (!empty($cat) && empty($obj)) $sql = 'select * from categories where id='.$cat.' order by id asc';
  else if (empty($cat) && !empty($obj)) $sql = 'select * from objects where id='.$obj.' order by id asc';
  else $sql =  //(*) 3
   'select * from links,categories,objects where links.id_category=categories.id && links.id_object=objects.id';
  $result = mysql_query ($sql);
  if ($result) {
   $n = mysql_num_rows ($result);
   if ($n>0)  while ($row = mysql_fetch_assoc ($result)) {
    echo '<br>';
    foreach ($row as $key=>$val) echo $key.'=>'.$val.' ';
   } 
   else echo '<br>Результат запроса пуст (выбрано 0 строк)';
  }
  else echo '<br>Ошибка SQL: '.mysql_error();
 } 
 echo '<form method="get" action="'.$_SERVER['PHP_SELF'].'">
  <p>Введите натуральные числа или оставьте поля пустыми</p>
  <p>Категория 
  <input type="text" name="cat" maxlength="2" size="2" value="'.(empty($cat)?'':$cat).'"> 
  Объект 
  <input type="text" name="obj" maxlength="2" size="2" value="'.(empty($obj)?'':$obj).'"> 
  <select name="action" size="1">
   <option value="show" '.($action=='show'?'selected':'').'>показать
   <option value="add" '.($action=='add'?'selected':'').'>связать
   <option value="del" '.($action=='del'?'selected':'').'>удалить
  </select>
  <input type="submit" value="Выполнить"></p>
 </form></body></html>';
?>

Примечания к листингу (*)

1. Не забудьте скорректировать данные доступа к БД, заданные константами define

2. Во избежание дублирования кода здесь лучше сделать функцию-обработчик допустимых значений параметров $cat и $obj

3. В нагруженных скриптах с потенциально большими объёмами данных не стоит делать запросов к двум, а тем более, к трём таблицам. Старайтесь всегда обойтись запросами типа "выбрать все объекты данной категории" или "выбрать все категории для данного объекта"

 Демо-скрипт "многие ко многим" в работе


теги: php mysql

комментарии (0)

20.01.2015, 09:17; рейтинг: 7115

  в началопоиск по блогунаписать авторустатистика

Наверх Яндекс.Метрика
© PerS
вход