Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [smarty] Pobieranie danych z 3 tabel i wyświetlanie
Forum PHP.pl > Forum > Gotowe rozwiązania > Systemy szablonów
matyskiewicz
Witam dość groźnie brzmi mój temat, lecz problem myślę że jest błachy, choć nie dla mnie.

Problem wygląda następująco:
  1. <?php
  2. $sqlConnect = mysql_connect($GLOBALS['sqlHost'], $GLOBALS['sqlUser'], $GLOBALS['sqlPassword'])
  3. or die('Nie można się połączyć: ' . mysql_error());
  4. $sqlDataBase = mysql_select_db($GLOBALS['sqlBase'])
  5. or die('Nie można się połączyć: ' . mysql_error());
  6. $sqlQuery_news = mysql_query("SELECT * FROM wdb_news WHERE newsStatus=1 ORDER BY newsId DESC LIMIT 0,10");
  7. $sqlQuery_category = mysql_query("SELECT * FROM wdb_category");
  8. $sqlQuery_author = mysql_query("SELECT * FROM wdb_user");
  9.  
  10. while ($sqlQuery_news && $sqlRow = mysql_fetch_array($sqlQuery_news)){
  11.  $news[] = array(
  12. 'newsId' => $sqlRow['newsId'],
  13. 'categoryId' => $sqlRow['categoryId'],
  14. 'authorId' => $sqlRow['authorId'],
  15. 'newsDate' => $sqlRow['newsDate'],
  16. 'newsTitle' => $sqlRow['newsTitle'],
  17. 'newsSmall' => $sqlRow['newsSmall'],
  18. 'newsText' => $sqlRow['newsText']
  19. );
  20. }
  21.  
  22. while ($sqlQuery_category && $sqlRow = mysql_fetch_array($sqlQuery_category)){
  23.  $category[] = array(
  24. 'categortId' => $sqlRow['categoryId'],
  25. 'categoryName' => $sqlRow['categoryName'],
  26. );
  27. }
  28. if ($news['categoryId'] == $category['categoryId']){
  29. $news['categoryName'] = $category['categoryName'];
  30. } else {
  31. $news['categoryName'] = 'brak kategorii';
  32. }
  33. ?>

  1. -- phpMyAdmin SQL Dump
  2. -- version 2.6.0-pl2
  3. --
  4. -- Host: localhost
  5. -- Czas wygenerowania: 29 Wrz 2007, 15:46
  6. -- Wersja serwera: 3.23.58
  7. -- Wersja PHP: 4.3.9
  8. --
  9. -- Baza danych: `dev-blog`
  10. --
  11.  
  12. -- --------------------------------------------------------
  13.  
  14. --
  15. -- Struktura tabeli dla `wdb_category`
  16. --
  17.  
  18. CREATE TABLE `wdb_category` (
  19. `categoryId` int(11) NOT NULL AUTO_INCREMENT,
  20. `categoryName` text NOT NULL,
  21. PRIMARY KEY (`categoryId`)
  22. ) TYPE=MyISAM AUTO_INCREMENT=2 ;
  23.  
  24. --
  25. -- Zrzut danych tabeli `wdb_category`
  26. --
  27.  
  28. INSERT INTO `wdb_category` VALUES (1, 'informacje');
  29.  
  30. -- --------------------------------------------------------
  31.  
  32. --
  33. -- Struktura tabeli dla `wdb_news`
  34. --
  35.  
  36. CREATE TABLE `wdb_news` (
  37. `newsId` int(11) NOT NULL AUTO_INCREMENT,
  38. `categoryId` int(11) NOT NULL DEFAULT '0',
  39. `authorId` int(11) NOT NULL DEFAULT '0',
  40. `newsStatus` int(11) NOT NULL DEFAULT '0',
  41. `newsDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  42. `newsDescription` text NOT NULL,
  43. `newsKeywords` text NOT NULL,
  44. `newsTitle` text NOT NULL,
  45. `newsSmall` text NOT NULL,
  46. `newsText` text NOT NULL,
  47. PRIMARY KEY (`newsId`)
  48. ) TYPE=MyISAM AUTO_INCREMENT=3 ;
  49.  
  50. --
  51. -- Zrzut danych tabeli `wdb_news`
  52. --
  53.  
  54. INSERT INTO `wdb_news` VALUES (1, 1, 1, 1, '2007-09-29 11:34:25', '', '', 'as', 'as. ', 'as');
  55. INSERT INTO `wdb_news` VALUES (2, 1, 1, 1, '0000-00-00 00:00:00', 'test', 'test', 'test', 'test', 'test');
  56.  
  57. -- --------------------------------------------------------
  58.  
  59. --
  60. -- Struktura tabeli dla `wdb_user`
  61. --
  62.  
  63. CREATE TABLE `wdb_user` (
  64. `userId` int(11) NOT NULL AUTO_INCREMENT,
  65. `userName` text NOT NULL,
  66. PRIMARY KEY (`userId`)
  67. ) TYPE=MyISAM AUTO_INCREMENT=2 ;
  68.  
  69. --
  70. -- Zrzut danych tabeli `wdb_user`
  71. --
  72.  
  73. INSERT INTO `wdb_user` VALUES (1, 'as');


Pobieram z bazy danych i przekazuje do tablicy wszystkie newsy, lecz zanim wyświetlę je na stronie musęe jeszcze zamienić wartość numeryczna autora oraz kategorii na wartość tekstową. I tu tkwi problem:

PLIK TPL
  1. {foreach item=news from=$news,}
  2. <div class=""># <span class="">{$category.categoryName} </span> # {$news.newsTitle} #</div>
  3. <div class="">autor: {$news.authorName}</div><div class=""> data: {$news.newsDate}</div>
  4. <div class="">{$news.newsSmall}</div>
  5. <div class=""> zalaczniki # wiecej</div>
  6. {/foreach}

Jak skonstruować plik TPL by wyświtelił mi żądaną ilość rekordów w sposób wyzej przedstawiony?
prgTW
Poczytaj o wewnętrznych/zewnętrznych (lewo i prawostronnych) złączeniach w MySQL (join/inner join, outer join), bo całą sytuację da się zrobić 1 zapytaniu SQL

  1. <?php
  2. $query = mysql_query('
  3. SELECT
  4. categoryId,
  5. categoryName,
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. FROM
  13. wdb_news news
  14. LEFT JOIN
  15. wdb_category cat ON cat.categoryId = news.categoryId
  16. LEFT JOIN
  17. wdb_user user ON user.userId = news.userId
  18. WHERE
  19. newsStatus = 1
  20. ORDER BY
  21. newsId DESC
  22. LIMIT
  23. 0, 10
  24. ');
  25.  
  26. $news = array();
  27. if(mysql_num_rows($query))
  28. while($news[] = mysql_fetch_assoc($query)){}
  29.  
  30. $smarty->assign('news', $news);
  31. ?>


  1. <?php
  2. {foreach name=news from=$news item=item}
  3. {$item.categoryId}
  4. {$item.categoryName|default:"Brak kategorii"}
  5. {$item.authorId}
  6. {$item.authroName|default:"Brak autora"}
  7.  ... itd.
  8. {/foreach}
  9. ?>
matyskiewicz
Dziękuję za podpowiedź jednakże, proszę jeszcze o pomoc:
  1. <?php
  2. if(mysql_num_rows($query))
  3. ?>

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in news.php on line 20

Nie rozumiem powyższego kodu, i dlaczego serwer zwraca ten błąd?

I dlaczego nie pobieramy newsId
prgTW
Kilka razy edytowałem posta i w którejś edycji zmieniłem
  1. <?php
  2. ?>

na
  1. <?php
  2. $query = mysql_query
  3. ?>

wiec zobacz czy jest "$query = "

A kod
  1. <?php
  2. if(mysql_num_rows($query))
  3. ?>

sprawdza czy zapytanie zwrocilo jakies rekordy, rownie dobrze moglem napisac
  1. <?php
  2. if(mysql_num_rows($query) > 0)
  3. ?>

ale PHP w blokach IF, WHILE itd. sprawdza warunek czy jest LOGICZNIE poprawny (true/false) wiec skoro mysql_num_rows zwraca liczbe od 0 do x to wartosc 0 w logice =falsz, wiec nie ma nawet sensu przeksztalcac rezultatu z typu numerycznego jaki zwraca mysql_num_rows na typ logiczny

Przyklady:
  1. <?php
  2. $wartosci = array(25, 0, 'trzysta', 'zero', '', true, false);
  3.  
  4. foreach($wartosci as $wartosc){
  5. var_dump($wartosc);
  6. $type = trim(strip_tags(ob_get_clean()));
  7. print 'Wartosc logiczna "' . $type . '" jest rowna: ' . (int)(bool)$wartosc . '<br />';
  8. // (int) bo wartosci logicznych print nie wypisuje, a typ numeryczny wypisze jako 0
     lub 1
  9. }
  10. ?>
matyskiewicz
Cytat(prgTW @ 29.09.2007, 18:58:40 ) *
A kod
  1. <?php
  2. if(mysql_num_rows($query))
  3. ?>

sprawdza czy zapytanie zwrocilo jakies rekordy, rownie dobrze moglem napisac
  1. <?php
  2. if(mysql_num_rows($query) > 0)
  3. ?>

ale PHP w blokach IF, WHILE itd. sprawdza warunek czy jest LOGICZNIE poprawny (true/false) wiec skoro mysql_num_rows zwraca liczbe od 0 do x to wartosc 0 w logice =falsz, wiec nie ma nawet sensu przeksztalcac rezultatu z typu numerycznego jaki zwraca mysql_num_rows na typ logiczny

Przyklady:
  1. <?php
  2. $wartosci = array(25, 0, 'trzysta', 'zero', '', true, false);
  3.  
  4. foreach($wartosci as $wartosc){
  5. var_dump($wartosc);
  6. print 'Wartosc logiczna "' . (string)$wartosc .'" jest rowna' . (int)(bool)$wartosc;
  7. // (int) bo wartosci logicznych print nie wypisuje, a typ numeryczny wypisze jako 0
     lub 1
  8. }
  9. ?>

Dziękuję za wytłumaczenie, przydało się.

###############################################################

Mam z $query Dlaczego nie pobieramy newsId
  1. <?php
  2. $query = mysql_query('
  3. SELECT
  4. categoryId, // czy tu nie powinno być
  5. categoryName,  // categoryId as categoryName,
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. FROM
  13. wdb_news news
  14. LEFT JOIN
  15. wdb_category cat ON cat.categoryId = news.categoryId
  16. LEFT JOIN
  17. wdb_user user ON user.userId = news.userId
  18. WHERE
  19. newsStatus = 1
  20. ORDER BY
  21. newsId DESC
  22. LIMIT
  23. 0, 10
  24. ');
  25. ?>


Proszę o pomoc w tym przykładzie bym lepiej mógł zrozumieć wspomniane funkcje MySql
prgTW
Ciesze sie ze moglem pomoc smile.gif

Cytat(matyskiewicz @ 29.09.2007, 19:03:52 ) *
Dlaczego nie pobieramy newsId
  1. <?php
  2. $query = mysql_query('
  3. SELECT
  4. categoryId, // czy tu nie powinno być
  5. categoryName,  // categoryId as categoryName,
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. FROM
  13. wdb_news news
  14. LEFT JOIN
  15. wdb_category cat ON cat.categoryId = news.categoryId
  16. LEFT JOIN
  17. wdb_user user ON user.userId = news.userId
  18. WHERE
  19. newsStatus = 1
  20. ORDER BY
  21. newsId DESC
  22. LIMIT
  23. 0, 10
  24. ');
  25. ?>


Proszę o pomoc w tym przykładzie bym lepiej mógł zrozumieć wspomniane funkcje MySql


Pobieramy newsId ale po prostu nie wpisałem - nieuwaga, no ale to już chyba wiesz co chcesz pobierać - prawda smile.gif

Analiza zapytania SQL:
- szukamy w bazie wdb_news rekordow których newsStatus = 1
- dla wszystkich znalezionych rekordow dolaczamy:
a) wiersz z tabeli wdb_category w ktorym categoryId = news_categoryId (dolaczamy informacje o kategorii uzytej zdla danego wiersza)
cool.gif analogicznie dolaczamy info. o uzytkowniku tym konkretnym ktory jest autorem (user.userId = news.userId)
- wynikiem mamy wszystkie kolumny z 3 tabel (wiersze z newsami, dolaczone kolumny z info o kategorii i userze), ale chcemy tylko wyjac te ktore nas interesuja wiec ich nazwy dajemy w select'a
- majac juz wybrane tylko kolumny sortujemy je po newsId najwiekszego
- ... i odrzucamy wszystkie spoza pierwszej 10-tki
matyskiewicz
Hmm...
Niby staram się zrozumieć przykład, lecz mi to nie wychodzi... A to chyba za sprawą, komunikatu który wyskakuje mi o wykonaniu funkcji:
Warning: mysql_num_rows(): supplied argument is not a valid MySQL i wskazuje na
  1. <?php
  2. if(mysql_num_rows($query)>0) {
  3. ?>


reszta kodu:
  1. <?php
  2. $query = mysql_query('
  3. SELECT
  4. categoryId,
  5. categoryName,  
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. FROM
  13. wdb_news news
  14. LEFT JOIN
  15. wdb_category cat ON cat.categoryId = news.categoryId
  16. LEFT JOIN
  17. wdb_user user ON user.userId = news.userId
  18. WHERE
  19. newsStatus = 1
  20. ORDER BY
  21. newsId DESC
  22. LIMIT
  23. 0, 10
  24. ');
  25.  
  26. $news = array();
  27.  
  28. if(mysql_num_rows($query)>0) {
  29. while($news[] = mysql_fetch_assoc($query)){
  30.  
  31. }
  32. }
  33. ?>



Kurcze a nie dałoby się tego problemu rozwiązać w inny sposób?
prgTW
Kod
mysql_num_rows(): supplied argument is not a valid MySQL ...

Po polsku: Podany argument nie jest prawidłowym wynikiem zapytania SQL (czyli wskaźnikiem na zasób zwróconych krotek/wierszy). Co to znaczy? To chyba łatwo się domyśleć że zapytanie jest błędnie skonstruowane i wywołało błąd SQL. Jak to sprawdzić - ano jest taka magiczna funkcja mysql_error() i mysql_errno() podające odowiednio tekst błędu i kod błędu, więc wystarczy debugować:
  1. <?php
  2. $query = mysql_query('...');
  3.  
  4. print 'Błąd w zapytaniu: ' . mysql_error();
  5. # ^^^ dodaj to
  6.  
  7. $news = array();
  8. # ...
  9. ?>


Jeżeli wyświetli się jakiś tekst po "Błąd w zapytaniu: " to tam będzie napisane co masz źle w zapytaniu (query), może gdzieś przecinka nie ma, może tabela nie istnieje, może kolumna tabeli nie istnieje itp.
matyskiewicz
magiczna funkcja zwróciła mi magiczny komunikat: Kolumna: 'categoryId' w field list jest dwuznaczna ... co to jest field list i co oznacza ze jes dwuznaczna? hmm...
prgTW
Field list - Lista pól zwracanych przez selecta
Dwuznaczna - Taka sama kolumna istnieje w 2 tabelach, przy złączeniu gdy pobieramy kolumnę o nazwie występującej w obu tabelach to pobierając kolumnę jako "categoryId" MySQL nie wiem z której tabeli wyjąć wartości, więc trzeba postawić prefix tabeli "wdb_news.categoryId" lub "wdb_categories.categoryId" - rozumiesz?

  1. <?php
  2. $query = mysql_query('
  3. select
  4. categories.categoryId, --dwuznaczna więc potrzeba prefiksu tabeli z której ma być wzięta ta kolumna
  5. categoryName, -- jednoznaczna, więc nie trzeba prefiksu, tak samo inne ...
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. from
  13. ...
  14. ');
  15. ?>
matyskiewicz
a można prosić jaśniej?
prgTW
Załóżmy że są 2 klatki schodowe i na każdej z nich mieszka Kowalski. Listonoszowi powiedzieli żeby zaniósł to panu Kowalskiemu. Listonosz podchodzi i nie wie któremu Kowalskiemu - z której klatki. Tak samo w SQL. Klatki to tabele, Kowalski to nazwa kolumny. W 2 tabelach są 2 takie same kolumny (np. A). Mówisz SQLowi żeby wybrał kolumnę A, a SQL się po prostu pyta z której kolumny, więc musisz napisać tabel1.A lub tabela2.A - rozumiesz, to jest niejednoznaczność.

Tabela1:
- kolumna A
- kolumna B

Tabela2:
- kolumna A
- kolumna C

Zapytanie:
  1. <?php
  2. select
  3. A, B, A, C
  4. from
  5. Tabela1 T1
  6. join
  7. Tabela2 T2
  8. ');
  9. ?>

zwróci błąd

Natomiast to:
  1. <?php
  2. select
  3. T1.A, B, T2.A, C
  4. from
  5. Tabela1 T1
  6. join
  7. Tabela2 T2
  8. ');
  9. ?>

lub to (bez aliasów):
  1. <?php
  2. select
  3. Tabela1.A, B, Tabela2.A, C
  4. from
  5. Tabela1
  6. join
  7. Tabela2
  8. ');
  9. ?>

zadziałają poprawnie
matyskiewicz
Pomnik temu człowiekowi który ma do mnie cierpliwość! ok a mógłbyś to zrobić na przykladzie mojego zapytania, bo kombinuje, i kombinuje i nic z tego nie czaje...
prgTW
  1. <?php
  2. $query = mysql_query('
  3. SELECT
  4. news.categoryId,
  5. categoryName,
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. FROM
  13. wdb_news news
  14. LEFT JOIN
  15. wdb_category cat ON cat.categoryId = news.categoryId
  16. LEFT JOIN
  17. wdb_user user ON user.userId = news.userId
  18. WHERE
  19. newsStatus = 1
  20. ORDER BY
  21. newsId DESC
  22. LIMIT
  23. 0, 10
  24. ');
  25.  
  26. $news = array();
  27.  
  28. if(mysql_num_rows($query)>0)
  29. while($news[] = mysql_fetch_assoc($query)){}
  30.  
  31. $smarty->assign('news', $news);
  32. ?>


Zmiana w linii nr 3 - dodany prefiks tabeli, skoro wartości są takie same w obu tabelach to pole categoryId można wyciągnąć zarówno z wdb_news/news jak i wdb_category/cat, czyli napisać: wdb_news.categoryId, news.categoryId, wdb_category.categoryId, cat.categoryId - wszystkie będą ok, natomiast bez prefiksu nazwy tabeli SQL nie będzie wiedział z której tabeli brać wartości, trzeba to jasno określić - stąd dwuznaczność.
matyskiewicz
Znalazłem jeszcze jeden błąd i poprawnie zapytanie powinno wygladać:
  1. <?php
  2. $query = mysql_query('
  3. SELECT
  4. news.categoryId,
  5. categoryName,
  6. authorId,
  7. userName as authorName,
  8. newsDate,
  9. newsTitle,
  10. newsSmall,
  11. newsText
  12. FROM
  13. wdb_news news
  14. LEFT JOIN
  15. wdb_category cat ON cat.categoryId = news.categoryId
  16. LEFT JOIN
  17. wdb_user user ON user.userId = news.authorId
  18. WHERE
  19. newsStatus = 1
  20. ORDER BY
  21. newsId DESC
  22. LIMIT
  23. 0, 10
  24. ');
  25. ?>
.
Super naprawdę dziękuję za szczegółowe wytłumaczenie problemu!

Zastanawia mnie jeszcze fakt iż:
Wywołuje
  1. {foreach name=news from=$news item=item}
  2. Kategoria: {$item.categoryName|default:"Brak kategorii"}<br>
  3. Autor: {$item.authorName|default:"Brak autora"}<br>
  4. Data: {$item.newsDate}<br>
  5. Tytuł: {$item.newsTitle}<br>
  6. Skrót: {$item.newsSmall}<br>
  7. Treść: {$item.newsText}<br> <br><br>
  8. {/foreach}

W bazie danych mam 2 rekordy, a na stronie wyskakują 3. Dlaczego?
prgTW
Aaa mój błąd:

  1. <?php
  2. if(mysql_num_rows($query)>0)
  3. while($news[] = mysql_fetch_assoc($query)){}
  4. ?>


zamień na
  1. <?php
  2. if(mysql_num_rows($query)>0)
  3. while($row = mysql_fetch_assoc($query))
  4. $news[] = $row;
  5. ?>


poprzedni kod przypisuje nowy element tablicy nawet jak mysql_fetch_assoc zwróci false - nawet wtedy powstaje kolejny element tablcy $news choc nie jest juz on wteydy tablica z polami z selecta ale zwykla stala tru/false
matyskiewicz
Naprawdę wielkie dzięki! Pozdrawiam!
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.