Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL] mysql_fetch_object i połączone tabele JOIN
Forum PHP.pl > Forum > PHP
Marcin Tabaka
Witam,

Chociaż od dawna biernie korzystam z tego forum (znajduje dużo interesujących informacji) to dopiero dzisiaj założyłem konto i postanowiłem napisać pierwszy temat.

Chciałbym się dowiedzieć czy macie jakiś rozsądny pomysł na pobranie z bazy danych połączonych tabel w postaci "połączonych" (hierarchicznych ?) obiektów?
Mam problem w dosyć rozbudowanym systemie, więc na potrzeby tego postu chciałbym zaprezentować na prostym przykładzie co mam na myśli. Mamy dwie tabele `news` oraz `comment` z relacją jeden do wielu:

  1. CREATE TABLE `news` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT,
  3. `title` varchar(100) NOT NULL,
  4. `content` text NOT NULL,
  5. `author` varchar(100) NOT NULL,
  6. PRIMARY KEY (`id`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
  8.  
  9. CREATE TABLE `comment` (
  10. `id` int(11) NOT NULL AUTO_INCREMENT,
  11. `id_news` int(11) NOT NULL,
  12. `content` text NOT NULL,
  13. `author` varchar(100) NOT NULL,
  14. PRIMARY KEY (`id`),
  15. KEY `id_news` (`id_news`)
  16. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
  17.  
  18. ALTER TABLE `comment`
  19. ADD CONSTRAINT `comment_ibfk_1` FOREIGN KEY (`id_news`) REFERENCES `news` (`id`);


Wypełnijmy je przykładowymi danymi.

  1. INSERT INTO `news` (`id`, `title`, `content`, `author`) VALUES
  2. (1, 'News 1', 'lorem ipsum', 'autor'),
  3. (2, 'News 2', 'donor lagos', 'inny autor');
  4.  
  5. INSERT INTO `comment` (`id`, `id_news`, `content`, `author`) VALUES
  6. (1, 1, 'Komentarz 1 do Newsa 1', 'autor'),
  7. (2, 1, 'Komentarz 2 do Newsa 1', 'autor'),
  8. (3, 2, 'Komentarz 1 do Newsa 2', 'autor'),
  9. (4, 2, 'Komentarz 2 do Newsa 2', 'autor'),
  10. (5, 2, 'Komentarz 3 do Newsa 2', 'autor');


Stórzmy dwie klasy odpowiadające tabelą w bazie (dla ułatwienia atrybuty będą publiczne). Dodatkowo classa news będzie posiadała dodatkowy atrybut $comments będący tablicą zawierającą wszystkie komentarze

  1. class news {
  2. public $id;
  3. public $title;
  4. public $content;
  5. public $author;
  6.  
  7. public $comments = array();
  8. }
  9.  
  10. class comment {
  11. public $id;
  12. public $id_news;
  13. public $content;
  14. public $author;
  15. }


W tym momencie w łatwy sposób możemy pobrać z bazy danych np wszystkie newsy:
  1. //...polaczenie z baza danych, itd.. $mysqli jest obiektem klasy MySQLi
  2. $result = $mysqli->query("SELECT id, title, content, author FROM news");
  3.  
  4. //stworzenie tablicy obiektow
  5. $objects = array();
  6. while ($obj = $result->fetch_object('news')) {
  7. $objects[] = $obj;
  8. }


W analogiczny sposób moglibyśmy pobrać wszystkie komentarze. Pytanie jest takie, czy istnieje możliwość pobranie wszystkich newsow tak aby ich atrybut comments zawieral obiekty komentarzy do nich nalezacych ?

  1. $result = $mysqli->query("SELECT n.id AS news_id, n.title AS news_title, n.content AS news_content, n.author AS news_author, c.id AS comment_id, c.id_news AS comment_id_news, c.content AS comment_content, c.author AS comment_author FROM news n LEFT JOIN comment c");
  2.  
  3. $objects = array();
  4. while ($obj = $result->fetch_object('questionmark.gif?')) {
  5. questionmark.gif?
  6. }

jarexx
Skoro masz klase comment, to moze po prostu:
  1. while($obj = $result->fetch_row()) {
  2. $objct[] = new comment($obj->id);
  3. }

Wynikiem bedzie tablica obiektow. Oczywiscie w klasie comment musisz stworzyc odpowiedni konstruktor.
Marcin Tabaka
Chodzi o to aby miał tablicę obiektów klasy news, w której każdy z nich będzie posiadał pole comments będące znów tablicą obiektów klasy comment. Oczywiście każdy news powinnien zawierać commenty dotyczace tylko jego (comment.id_news = news.id)

Możliwym rozwiązaniem jest pobranie najpierw tabeli news a potem w petli pobieranie odpowiednich komentarzy do nich, jednak jest to rozwiązanie moim zdaniem całkowicie niepoprawne ponieważ ilość zapytań będzie równa n+1 ilości newsów. Chodzi mi o to czy macie jakiś pomysł aby jednym (no może dwoma) zapytaniami pobrać i stworzyć taką hierarchie obiektów:

  1. (
  2. [0] => news Object
  3. (
  4. [id] => 1
  5. [title] => News 1
  6. [content] => Tresc
  7. [author] => autor
  8. [comments] => Array
  9. (
  10. [0] => comment Object
  11. (
  12. [id] => 1
  13. [id_news] => 1
  14. [content] => Komentarz 1 News 1
  15. [author] => autor
  16. )
  17.  
  18. [1] => comment Object
  19. (
  20. [id] => 2
  21. [id_news] => 1
  22. [content] => Komentarz 2 News 1
  23. [author] => autor
  24. )
  25.  
  26. )
  27.  
  28. )
  29.  
  30. [1] => news Object
  31. (
  32. [id] => 2
  33. [title] => News 2
  34. [content] => Tresc inna
  35. [author] => inny autor
  36. [comments] => Array
  37. (
  38. [0] => comment Object
  39. (
  40. [id] => 3
  41. [id_news] => 2
  42. [content] => Komentarz 1 News 2
  43. [author] => autor
  44. )
  45.  
  46. [1] => comment Object
  47. (
  48. [id] => 4
  49. [id_news] => 2
  50. [content] => Komentarz 2 News 2
  51. [author] => autor
  52. )
  53.  
  54. [2] => comment Object
  55. (
  56. [id] => 5
  57. [id_news] => 2
  58. [content] => Komentarz 3 News 2
  59. [author] => autor
  60. )
  61.  
  62. )
  63.  
  64. )
  65.  
  66. )
  67.  


To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.