Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

3 Stron V   1 2 3 >  
Reply to this topicStart new topic
> PDO i współpraca z własnymi klasami
Jawor
post 9.11.2008, 16:26:41
Post #1





Grupa: Zarejestrowani
Postów: 73
Pomógł: 2
Dołączył: 1.10.2003

Ostrzeżenie: (0%)
-----


Witam

Mam pytanie odnośnie współpracy PDO z własnymi klasami.

Ktory sposob powinno sie uzywac:

1. Polaczenie z baza poza klasa (wlasna) i przekazywanie do niej obiektu typu PDO. Wszystkie zapytania, operacje na danych z bazy odbywaja sie we wlasnej klasie.

2. Wszystkie operacje zwiazane z baza odbywaja sie poza wlasna klasa (zapytania, pobieranie danych), a do mojej klasy przekazuje juz np. pobrane z bazy dane.


Do tej pory caly czas pisalem strukturalnie, ale postanowilem to zmienic i oto pierwszy dylemat jaki napotkalem na swojej drodze smile.gif

Ten post edytował Jawor 9.11.2008, 16:27:35
Go to the top of the page
+Quote Post
LBO
post 9.11.2008, 16:37:47
Post #2





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Przekazuj obiekt PDO i wykorzystuj go w klasach służących do interakcji z danymi w bazie; w tzw. modelach.

Najprostszy przykład:

  1. <?php
  2. class News
  3. {
  4.    protected $pdo;
  5.  
  6.    public function __construct(PDO $pdo)
  7.    {
  8.        $this->pdo = $pdo;
  9.    }
  10.  
  11.    public function getAllNews()
  12.    {
  13.        $statement = $this->pdo->query('SELECT * FROM news');
  14.        return $statement->fetchAll();
  15.    }
  16.  
  17.    // etc
  18. }
  19. ?>


Są oczywiście lepsze rozwiązania smile.gif

Edit:

Klasa news nie powinna mieć nic wspólnego z prezentacją danych.
Może pobierać, kasować i zmieniać newsy w bazie, ale na przykład nie może wypluć HTML.

Ten post edytował LBO 9.11.2008, 16:40:35
Go to the top of the page
+Quote Post
Jawor
post 9.11.2008, 16:40:46
Post #3





Grupa: Zarejestrowani
Postów: 73
Pomógł: 2
Dołączył: 1.10.2003

Ostrzeżenie: (0%)
-----


Cytat(LBO @ 9.11.2008, 18:37:47 ) *
Są oczywiście lepsze rozwiązania smile.gif

Rozwiniesz snitch.gif ?

Ten post edytował Jawor 9.11.2008, 16:41:38
Go to the top of the page
+Quote Post
LBO
post 9.11.2008, 16:47:15
Post #4





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(Jawor @ 9.11.2008, 16:40:46 ) *
Rozwiniesz snitch.gif ?


Możesz przekazywać do klasy jakiś obiekt, który przetrzymuje w sobie więcej rzeczy niż samo PDO.

  1. <?php
  2. class News
  3. {
  4.   protected $context;
  5.  
  6.   public function __construct(Context $context)
  7.   {
  8.       $this->context = $context;
  9.   }
  10.  
  11.   public function getAllNews()
  12.   {
  13.       // context może przekazać obiekt PDO.
  14.       // Możesz w nim trzymać również inne obiekty związane z Twoim systemem, jak
  15.       // loggery błędów lub translatory
  16.       try {
  17.           $statement = $this->context->getPDO()->query('SELECT * FROM news');
  18.           return $statement->fetchAll(); // model przekazuje czyste dane.
  19.       catch (Exception $e) {
  20.           // logujesz błąd
  21.           $this->context->getLogger()->log($e->getMessage());
  22.       }
  23.       return false; // nie udało się pobrać newsów.
  24.   }
  25.  
  26.   // etc
  27. }
  28. ?>


Ten post edytował LBO 9.11.2008, 16:50:09
Go to the top of the page
+Quote Post
Jawor
post 9.11.2008, 16:51:35
Post #5





Grupa: Zarejestrowani
Postów: 73
Pomógł: 2
Dołączył: 1.10.2003

Ostrzeżenie: (0%)
-----


Ok. Dzieki za pomoc.

Pozdrawiam
Go to the top of the page
+Quote Post
Black-Berry
post 9.11.2008, 17:31:14
Post #6





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Z ostatnich testów i odrobiony teoretyzowania wyszło mi że nie bardzo opłaca się przekazywać context w konstruktorze bo wyobraźmy sobie następującą systuację:

  1. <?php
  2.    $context = new Context(); // obiekt $context nie zawiera listy obiektów
  3.    $config = New Config($context); // obiekt $config dopisuje sam siebie do obierktu $context;
  4.    $log = New Log($context); // obiekt $context zawiera teraz $config + $log;
  5.    $dbDriver = new Db_Driver($context) // w tym miejscu $context ma juz 3 obiekty;
  6. ?>

I teraz przykłąd użycia $log'u wewnątrz metody $dbDrver'a

  1. <?php
  2.    (..)
  3.    public function printLoggedErrors()
  4.    {
  5.        $this->log->printErrors(QUERY_ERRORS); //ten przykład zadziała bezproblemowo;
  6.    }
  7.    (..)
  8. ?>

problem pojawia się kiedy chcemy za pomocą $log'u wywołać $dbDriver. Systuacja taka przytrafia się jeśli log ma zapisać cos do bazy danych. Ponieważ $dbDriver został utowrzony po obiekcie $log, log nie moze z niego korzystać.

Rozwiązaniem tego może więc być metoda ustawiająca context:


  1. <?php
  2.    $context = new Context();
  3.    $config = New Config();
  4.    $log = New Log();
  5.    $dbDriver = new Db_Driver();
  6.    //inicjowanie kontextu:
  7.    $config->setContext($context);
  8.    $log->setContext($context);
  9.    $dbDriver->setContext($context);
  10. ?>


Proszę o komentarz do takiego rozwiązania ponieważ ciągle jeszcze staram się to udoskonalić.

Ten post edytował Black-Berry 9.11.2008, 17:32:05


--------------------
Go to the top of the page
+Quote Post
LBO
post 9.11.2008, 17:35:59
Post #7





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Prędzej

  1. <?php
  2. $context = new Context();
  3. $context->setDbDriver($dbDriver);
  4. $context->setLogger($logger);
  5.  
  6. // a potem
  7.  
  8. $controller = new News_Controler();
  9. $controller->setContext($context);
  10.  
  11. // albo
  12.  
  13.  
  14. $model = new NewsModel();
  15. $model->setContext($context);
  16. ?>
Go to the top of the page
+Quote Post
Black-Berry
post 9.11.2008, 17:43:27
Post #8





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


A nie tak:
  1. <?php
  2. $context = new Context();
  3.    $context->setDbDriver($dbDriver = new dbDriver);
  4.    $context->setLogger($logger = new Logger);
  5. ?>

?

Czy nie jest wadą, że obiekty $dbDriver i $log będą niewidoczne dla całej apilikacji? Wygodne byłoy przecież w stopce aplikacji wywyołać sobie np:

  1. <?php
  2.    $log->printErrors();
  3. ?>

a nie:
  1. <?php
  2.    $someControlerOrModel->log->printErrors();
  3. ?>


--------------------
Go to the top of the page
+Quote Post
LBO
post 9.11.2008, 17:50:47
Post #9





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Ja za stopkę aplikacji uważam na przykład ostatni filtr kontrolera (coś jak pluginy front controlera w zendzie) i tam tez mam dostęp do kontekstu.

Jest hermetycznie, poza aplikacja nie ma dostępu do żadnych driverów, loggerów etc.
Go to the top of the page
+Quote Post
Black-Berry
post 9.11.2008, 17:57:49
Post #10





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Racja. Twoje rozwiązanie jest bardziej eleganckie.

pozdrawiam.


--------------------
Go to the top of the page
+Quote Post
markac
post 9.11.2008, 20:15:48
Post #11





Grupa: Zarejestrowani
Postów: 83
Pomógł: 0
Dołączył: 23.02.2005

Ostrzeżenie: (10%)
X----


Dajcie już spokój z tymi kontekstami i kopiowaniem wszystkiego z Javy... Ja do tego wykorzystuje wzorzec Registry.

  1. <?php
  2. class ApplicationRegistry extends Registry {
  3.    private static $instance;
  4.      private $values = array();
  5.      
  6.    private function __construct() {
  7.    }
  8.    
  9.    /**
  10.      * Enter description here...
  11.      * @return ApplicationRegistry
  12.      */
  13.    public static function getInstance() {
  14.      return self::$instance ? self::$instance : self::$instance = new self();
  15.    }
  16.      
  17.    /**
  18.      * Gets PDO Database Access
  19.      * @return PDO
  20.      */
  21.    public static function getPDO() {
  22.      return self::getInstance()->get('pdo');
  23.    }
  24.    
  25.    public static function setPDO($object) {
  26.      if ($object instanceof PDO)
  27.        self::getInstance()->set('pdo', $object);
  28.      else
  29.        throw new Exception('Obiekt musi być instancją klasy PDO.');
  30.    }
  31.      
  32.  }
  33. ?>


Wywołanie:

  1. <?php
  2. $pdo = ApplicationRegistry::getPDO();
  3. ?>


Ten post edytował markac 9.11.2008, 20:17:28
Go to the top of the page
+Quote Post
LBO
post 9.11.2008, 20:21:05
Post #12





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Rejestr to tylko niechlujność architektów :/

Przeczy hermetyzacji OOP. Po to mam obiekt kontekstu, żeby go przekazywać gdzie chcę, a tam, gdzie nie - to go nie ma.

Cytat
Dajcie już spokój z tymi kontekstami i kopiowaniem wszystkiego z Javy... Ja do tego wykorzystuje wzorzec Registry.


A nie wiesz, że poniekąd z Javy wywodzą się najlepsze praktyki programistyczne?

Ten post edytował LBO 9.11.2008, 20:34:25
Go to the top of the page
+Quote Post
Black-Berry
post 10.11.2008, 09:45:02
Post #13





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Singletony są złe. A poza tym działają wolniej niż context.


--------------------
Go to the top of the page
+Quote Post
phpion
post 10.11.2008, 09:48:23
Post #14





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




@BlackBerry:
A czy przypadkiem nie jest tak, że context powinien być singletonem? Przykład:
http://www.symfony-project.org/api/1_1/sfC...hod_getinstance
Chyba nie powiesz, że Symfony projektowały osoby nie znające się na OOP...
Go to the top of the page
+Quote Post
LBO
post 10.11.2008, 09:51:13
Post #15





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


No i w tym momencie masz z poziomu szablonu dostęp do bazy, o! A nie powiesz mi chyba, że to dobrze?


Zrobili to dla wygody tylko.

edit

Wynika to z architektury Mojavi, gdzie aplikacja jest uruchamiana z poziomu kontekstu, a ten trzeba jakoś pozyskać.

Ten post edytował LBO 10.11.2008, 09:54:19
Go to the top of the page
+Quote Post
markac
post 10.11.2008, 11:20:28
Post #16





Grupa: Zarejestrowani
Postów: 83
Pomógł: 0
Dołączył: 23.02.2005

Ostrzeżenie: (10%)
X----


Tak się składa, że obiekt bazy danych ma być dostępny w większości przypadków wszędzie i przekazywanie tego uchwytu do każdego obiektu, np. przez konstruktor to dla mnie przerost formy nad treścią. A jak byście nie wiedzieli, kontekst także jest singletonem, czyli co, źle? Ależ skąd. Kontekstu nie używa się tylko po to, żeby zapewnić dostęp dostęp do wspólnych obiektów, które posiadają tylko jedną instancję. Używa go się tam, gdzie zachodzi możliwość uruchomienia skryptu w innym środowisku (kontekście), że tak to ujmę smile.gif W tym wypadku kontekst wykorzystujecie tylko i wyłącznie do przekazania obiektu bazy danych i ja mówię temu nie. Lepszym rozwiązaniem jest dla mnie w tym wypadku Rejestr, ale jak kto woli...
Go to the top of the page
+Quote Post
Black-Berry
post 10.11.2008, 11:23:43
Post #17





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Dlaczego na miłość Boga kontekst miałby być singletonem questionmark.gif Dlaczego mielibyśmy przekazywać coś w konstruktorach ?
  1. <?php
  2. //creating core objects...
  3.    $config = new Config();
  4.    $log = new Log();
  5.    $dbDriver = new Db_Driver();
  6.    $session = new Session();
  7.    
  8.    //creating context...
  9.    $context = new Core_Context();
  10.    $context->setConfig($config);
  11.    $context->setLog($log);
  12.    $context->setDbDriver($dbDriver);
  13.    $context->setSession($session);
  14.    
  15.    //setting context...
  16.    $log->setContext($context);
  17.    $dbDriver->setContext($context);
  18.    $session->setContext($context);
  19. ?>


--------------------
Go to the top of the page
+Quote Post
LBO
post 10.11.2008, 11:37:02
Post #18





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Kto Ci powiedział, że obiekt kontekstu ma być wszędzie?

To ja napiszę tak i się powtórzę - singletony PRZECZĄ hermetyzacji. Idealna aplikacja powinna wyglądać tak, że ją odpalasz jakimś obiektem aplikacji i koniec, wszystko się dzieje wewnątrz, a ty nie masz do niczego dostępu, zarazem zachowując pełną kontrolę.

Niech szlak trafi ZF za rozpropagowanie tego cholernego wzorca. Zrobili zbiór klas, które działają tak luźno, że nie sposób nie korzystać z rejestru.

Nie po to w architekturze oprogramowania wymyśla się nieprzepuszczalne warstwy (czyli nie mówię tylko o MVC), żeby jakiś rejestr odstawił wszystko do lamusa. Weźmy na przykład aplikacje GUI, które trzymają się MVC - gdyby we frameworkach wspomagających tworzenie takiego oprogramowania warstwy by rzeczywiście na siebie nie zachodziły to by było super - a tak nadal się zdarza, że żółtodziub siada do klawy i zasysa dane bezpośrednio w akcji np. Button.onClick (co zasadniczo jest widokiem, a raczej szablonem jeżeli przerzucić to na myślenie WWW).

Rejestr to taki kontekst dla leniwych.
Go to the top of the page
+Quote Post
xmarcin
post 22.11.2008, 16:26:45
Post #19





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 19.07.2006

Ostrzeżenie: (0%)
-----


troche odgrzewam temat, ale przyznam, że cos mnie gryzie
jak poinien wygladac element, ktory jest trzymany jako $context?
  1. <?php
  2. $this->context->getPDO()->query('SELECT * FROM news');
  3. ?>

bo z tego co rozumiem, $context to klasa, ktora zawieta min jakies odwolnie do PDO.
czy nie lepiej przed wywolaniem instancji naszej klasy News() wywoalac instacje od PDO() i pozniej przekazac uchwyt do News() ?
Sory, jesli cos pomieszalem, ale to moje poczatki w oop
Go to the top of the page
+Quote Post
LBO
post 22.11.2008, 17:12:06
Post #20





Grupa: Zarejestrowani
Postów: 1 415
Pomógł: 117
Dołączył: 7.09.2005
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Tak też można, jeżeli nie chcesz by News miał dostęp do czegokolwiek innego niż PDO to możesz o tak:
  1. <?php
  2. class Model
  3. {
  4.    private $context;
  5.    
  6.    public function initialize(Context $context)
  7.    {
  8.        $this->context = $context;
  9.    }
  10.  
  11.    protected function getPDO()
  12.    {
  13.        return $this->context->getPDO();
  14.    }
  15. }
  16.  
  17.  
  18. class News extends Model
  19. {
  20.     public function getAllNewsByPage($page)
  21.     {
  22.         $pdo = $this->getPDO();
  23.         // tutaj robisz selecty etc.
  24.     }
  25. }
  26. ?>


Ten post edytował LBO 22.11.2008, 17:13:17
Go to the top of the page
+Quote Post

3 Stron V   1 2 3 >
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.06.2025 - 14:38