Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: OOP problem z klasą
Forum PHP.pl > Forum > PHP
ziomek32
Witam wszystkich bardzo serdecznie;)

Mam oto taki kod:
  1. <?php
  2.  
  3.  
  4. try
  5. {
  6. @ $db = new PDO('mysql:host=localhost;dbname=baza', 'user', 'haslo');
  7. }
  8. catch(PDOException $e)
  9. {
  10. die('Brak połączenia');
  11.  
  12. }
  13.  
  14.  
  15. class wybierz
  16. {
  17. public function dalej()
  18. {
  19.  
  20.  
  21. $bb = $db->query('Select nazwa from tabela order by pole ASC');
  22.  
  23. $wybierz = $bb->fetch();
  24.  
  25. echo $wybierz['nazwa'];
  26.  
  27. }
  28.  
  29. }
  30.  
  31. $a = new wybierz();
  32. $a->dalej();
  33.  
  34.  
  35.  
  36.  
  37. ?>


Gdy wchodzę na plik wywala mi taki błąd:
Fatal error: Call to a member function query() on a non-object in /adres_do_pliku on line 22
Dlaczego?

Proszę o pomoc.

Pozdrawiam:)
blooregard
$db nie jest widzialny w klasie 'wybierz' i dlatego tam nie istnieje jako obiekt PDO.
Musisz go przekazać tej klasie.
ziomek32
Czy mógłbyś mi powiedzieć jak go przekazać?
Dopiero zaczynam swoją przygodę z OOP więc byłbym bardzo wdzięczny za pomoc.
zzeus
Jakoś tak mniej więcej:
  1. <?php
  2. try
  3. {
  4. $db = new PDO('mysql:host=localhost;dbname=baza', 'user', 'haslo');
  5. }
  6. catch(PDOException $e)
  7. {
  8. die('Brak połączenia');
  9. }
  10.  
  11. class wybierz
  12. {
  13. private $db;
  14. public function __construct(PDO $db)
  15. {
  16. $this->db = $db;
  17. }
  18.  
  19. public function dalej()
  20. {
  21. $bb = $this->db->query('Select nazwa from tabela order by pole ASC');
  22. $wybierz = $bb->fetch();
  23. echo $wybierz['nazwa'];
  24. }
  25. }
  26.  
  27. $a = new wybierz($db);
  28. $a->dalej();
  29.  
  30. ?>


ps. nie ten dział
ziomek32
Działa Dziękuję za pomoc:)
Pilsener
Naucz się korzystać z dziedziczenia, przecież nie będziesz przekazywał lub tworzył obiektu DB za każdym razem, gdy tworzysz nowy model danych, model danych powinien dziedziczyć połączenie z bazą, klasa np. "model_danych_artykuły" dziedziczy wszystkie podstawowe metody i pola z klasy "baza_danych", która obsługuje bazę, a w klasie "model_danych_artykuły" tylko definiujesz jakieś skomplikowane zapytania (bo proste są już zaimplementowane w klasie baza_danych), klasy i metody pobierające dane z bazy są jej integralną częścią i nie powinny funkcjonować jako samodzielne obiekty.
Crozin
@Pilsener: ale stek bredni...
1) Utworzenie 10 obiektów ma skutkować nawiązaniem 10 połączeń do bazy danych?
2) Tzw. Model to nie tylko baza danych... będzie miał model pobierający dane z XMLa, to też będzie łączyć się z bazą danych?
3) Niby jakie metody mogłoby dziedziczyć "ModelDanychArtykuły" po "ModelDanych"? Nawet najprostszego wybierania jednego elementu po kluczu głównym nie da się zaimplementować
4) To Tobie radzę nauczyć się korzystania z dziedziczenia, bo chyba nie uważasz, że telefonistka dziedziczy po telefonie?

@ziomek32: zabrakło Ci jeszcze obsługi wyjątków wyrzucanych przez metody PDO::Query() oraz PDOStatement::fetch() jak również i ta klasa "Wybierz" jest trochę bez sensu (a przynajmniej jej nazwa...) - od razu dodam, że metoda Wybierz::dalej() nie powinna raczej niczego wyświetlać tylko zwracać dane.

btw: po co Ci ten die(...)? Wyjątek zawiera dużo więcej informacji, niż jakiś komunikat "nie udało się"
Pilsener
Przecież napisałem, za każdym razem ma powtarzać taki kod:
  1. private $db;
  2. public function __construct(PDO $db)
  3. {
  4. this->db = $db;
  5. }
? A jak będzie chciał zmienić sterownik? Nic nie pisałem na temat ilości połączeń. Jak potrzebuję np. dostępu do tabeli artykuły to robię:
  1. class Model_Articles extends Db{
  2.  
  3. public function get_articles(){
  4.  
  5. }
  6. public function delete_articles(){
  7.  
  8. }
  9. //i tak dalej
  10.  
  11. }
- i to klasa db martwi się o to, jakiego użyć sterownika bazy danych i nawiązuje połączenie z bazą danych, nie wyobrażam sobie przekazywać za każdym razem połączenia w konstruktorze, bo nie po to używam jakiegoś algorytmu czy wzorca, by komplikować sobie życie. Skoro dziedziczenie złe, singleton zły, registry złe (a i tak każdy tego używa) to co zostaje? Te rzeczy powstały, by aplikacja była wygodna i nieprzekombinowana.
Crozin
Cytat
A jak będzie chciał zmienić sterownik?
Wiesz czym jest w ogóle PDO? Raczej mało prawdopodobne by chciał go zamienić... zresztą jeżeli już się na takie coś zdecyduje to akurat tamten fragment kodu będzie jego najmniejszym zmartwieniem.
Cytat
Nic nie pisałem na temat ilości połączeń.
Utworzenie wielu obiektów Model_Artickes czy podobnych (dziedziczących po Db) będzie skutkowało wielokrotnym wywołaniem konstruktora z Db co zapewne nawiąże wiele połączeń z bazą danych.
Cytat
Jak potrzebuję np. dostępu do tabeli artykuły to robię:
  1. class Model_Articles extends Db{
Czyli jednak uważasz, że telefonistka to jest coś co jest rozszerzeniem telefonu?

Cytat
Skoro dziedziczenie złe
Dziedziczenie jest złe jeżeli jest źle używane - tak jak tutaj.
Cytat
singleton zły
Singleton też jest zły tylko wtedy, gdy jest źle używany (zwróć uwagę, że celem jego stosowania powinno być zagwarantowanie dokładnie jednej instancji danej klasy, a nie globalnego dostępu do owej instancji)
Cytat
registry złe (a i tak każdy tego używa)
A to to akurat - w kontekście do jakiego się zapewne odnosisz - jest złe, gdyż całe modelowanie aplikacji idzie się @#$@#%^* dzięki temu - ja (i nie tylko) nie używam
Cytat
to co zostaje?
Nauczenie się doboru odpowiednich narzędzi i technik do danych zadań.
Cytat
Te rzeczy powstały, by aplikacja była wygodna i nieprzekombinowana.
Nie będę się sprzeczał - ale wygodne są tylko wtedy, gdy są poprawnie użyte. A o przypadkach w projektach z serii "hello world" gdzie global, @, eval itp są fajne to się tutaj nie wypowiadam - tam, to wszystko jest fajne.
Pilsener
Cytat
Nauczenie się doboru odpowiednich narzędzi i technik do danych zadań.
- a jak wywołujesz proste zapytania w kontrolerze, co ja robię tak:
  1. $a = new model_articles;
  2. $a->delete('id='.$this->request->id);
  3. $b = new model_articles_comments;
  4. $b->delete('id_article='.$this->request->id);
- tworzyć metodę delete dla każdego modelu? Dlaczego dziedziczenie poszczególnych tabel po obiekcie baza_danych w takim przypadku jest złe? Jest to niezgodne z teorią czy niesie w sobie jakieś inne, ukryte zagrożenia? Czy po prostu niepraktyczne, bo ten aspekt akurat interesuje mnie najbardziej, by kod był prosty i przejrzysty.
Crozin
Cytat
- a jak wywołujesz proste zapytania w kontrolerze
Zapytania w kontrolerze? A co ma Kontroler do zapytań? Tuż to działa Modelu, którego sposób działania jest transparentny dla Kontrolera.
Cytat
Dlaczego dziedziczenie poszczególnych tabel po obiekcie baza_danych w takim przypadku jest złe?
Ponieważ w Twoim przypadku ten obiekt "baza danych" to obiekt na kształt PDO - odpowiedzialny tylko za wywoływanie/obsługę samych zapytań. Konkretna tabela nie jest rozszerzeniem czegoś takiego, ona z tego korzysta.
Cytat
est to niezgodne z teorią czy niesie w sobie jakieś inne, ukryte zagrożenia?
To i to. Kod jest nielogiczny, wcale jakiś prosty nie jest (po co delete('id=123') zamiast delete(123), po co usuwanie komentarzy z poziomu aplikacji skoro tym może zająć się sama baza? A jeżeli ona tego nie może to powinna to zrobić metoda delete obiektu model_articles), a w dodatku w przypadku gdybyś go kiedyś jakoś rozbudował czy zaczął pracować w grupie nad nim zaraz by powychodziło to jaki jest on nieelastyczny i mało funkcjonalny.
Cytat
Czy po prostu niepraktyczne, bo ten aspekt akurat interesuje mnie najbardziej, by kod był prosty i przejrzysty.
Kod nie ma być zawsze prosty i przejrzysty... ma być odpowiednio elastyczny i łatwy w końcowym użyciu. Oczywiście aspekt jego rozbudowy jest nie mniej ważny.
jaslanin
dziedziczenie po bazie danych to zły pomysł.

jest lepsza metoda, tworzysz sobie klasę będącą przodkiem dla wszystkich Twoich modeli które będą używały bazy danych i w jego konstruktorze tworzysz sobie instancję klasy obsługi bazy danych z mniej więcej takim konstruktorem:

Kod
public function __construct ()
    {

        if (! is_object($this->db))
        {
            // Load the default database
            $this->db = Database::instance($this->db);
        }
    }

(przykłąd z Kohana framework)

potem Twoje modele dziedziczą po tym przodku i nie musisz się martwić o to że za każdym razem musisz ładować bazę danych. Jak Ci jest zbędna db, lub chcesz coś innego Tworzysz innego przodka z obsługą xml, txt, nosql itd.

PS. polecam ten framework (Kohana) do nauki OOP, podglądając jak oni to zrobili powinieneś szybko załapać idee OOP i MVC
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.