Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: PDO i współpraca z własnymi klasami
Forum PHP.pl > Forum > PHP > Object-oriented programming
Stron: 1, 2
Jawor
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
LBO
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.
Jawor
Cytat(LBO @ 9.11.2008, 18:37:47 ) *
Są oczywiście lepsze rozwiązania smile.gif

Rozwiniesz snitch.gif ?
LBO
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. ?>
Jawor
Ok. Dzieki za pomoc.

Pozdrawiam
Black-Berry
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ć.
LBO
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. ?>
Black-Berry
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. ?>
LBO
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.
Black-Berry
Racja. Twoje rozwiązanie jest bardziej eleganckie.

pozdrawiam.
markac
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. ?>
LBO
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?
Black-Berry
Singletony są złe. A poza tym działają wolniej niż context.
phpion
@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...
LBO
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ć.
markac
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...
Black-Berry
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. ?>
LBO
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.
xmarcin
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
LBO
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. ?>
markac
Cytat(LBO @ 10.11.2008, 11:37:02 ) *
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.


Kolego, nie bulwersuj się tak... nikt tu nie pisał, że kontekst ma być widoczny wszędzie, a dobrze by było aby uchwyt do bazy był. Co do idealnej aplikacji, to jeszcze taka nie powstała, więc zejdź na ziemię, bo popadasz w pewien wir, jak każdy, który dopiero co zachłysnął się wzorcami projektowymi. Aplikacja ma przede wszystkim działać i nie powinna być przekombinowana. Nie opowiadaj też o aplikacjach typowo desktopowych, bo mówimy o innym zastosowaniu. MVC nie powstał dla www! Nie da się w pełni zaimplementować wzorca MVC na potrzeby strony www! Na tą okoliczność powstał Model 2 i używajmy odpowiedniego nazewnictwa.

Cytat(LBO @ 10.11.2008, 09:51:13 ) *
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ć.


Znowu popadamy w obsesję? Wiadomym jest, że jeśli szablon jest wykonany w PHP to mamy dostęp do rożnych rzeczy, do których mieć byśmy nie chcieli, prawda? Przecież nic nie stoi na przeszkodzie, żebym utworzył np. nową instancję np. front controlla (o ile nie korzysta z singletona, których używania nie popierasz!). Co mnie przed tym powstrzyma? A co z innymi zmiennymi globalnymi i samym global? Jak się zabezpieczysz na tą okolicznosc, że coś nadpisze? Może w ogóle zrezygnować z szablonów w PHP i zrobić coś ala BBCode? smile.gif Powtarzam, nie ma idealnej aplikacji. KOMPROMIS KOMPROMIS KOMPROMIS.
LBO
Cytat(markac @ 22.11.2008, 18:17:09 ) *
Kolego, nie bulwersuj się tak... nikt tu nie pisał, że kontekst ma być widoczny wszędzie, a dobrze by było aby uchwyt do bazy był. Co do idealnej aplikacji, to jeszcze taka nie powstała, więc zejdź na ziemię, bo popadasz w pewien wir, jak każdy, który dopiero co zachłysnął się wzorcami projektowymi. Aplikacja ma przede wszystkim działać i nie powinna być przekombinowana.

Kolego

Doświadczenie i styczność z dobrze zaprojektowanym kodem, nie zachłyśnięcie. Aplikacja przekombinowana być nie musi, ale to co pod Nią leży jak najbardziej - w tym tkwi siła. I nie zgadzam się, że uchwyt powinien być widoczny wszędzie - perzystencja powinna być izolowana od pewnych części aplikacji inaczej będą problemy.
Cytat(markac @ 22.11.2008, 18:17:09 ) *
Nie opowiadaj też o aplikacjach typowo desktopowych, bo mówimy o innym zastosowaniu. MVC nie powstał dla www! Nie da się w pełni zaimplementować wzorca MVC na potrzeby strony www! Na tą okoliczność powstał Model 2 i używajmy odpowiedniego nazewnictwa.

Przecież Model 2 to wariacja MVC, ale wciąż MVC tak samo HMVC, MVC-pull/push etc. Więc też nie szastaj nomenklaturą.
Cytat(markac @ 22.11.2008, 18:17:09 ) *
Znowu popadamy w obsesję? Wiadomym jest, że jeśli szablon jest wykonany w PHP to mamy dostęp do rożnych rzeczy, do których mieć byśmy nie chcieli, prawda? Przecież nic nie stoi na przeszkodzie, żebym utworzył np. nową instancję np. front controlla (o ile nie korzysta z singletona, których używania nie popierasz!).

Ja nie piszę o programiście idiocie kolego, tylko takim, który nie do końca wie co jest dla Niego dobre.

oraz

Da się napisać FC o jakim piszesz bez Singletona.
Cytat(markac @ 22.11.2008, 18:17:09 ) *
Co mnie przed tym powstrzyma? A co z innymi zmiennymi globalnymi i samym global? Jak się zabezpieczysz na tą okolicznosc, że coś nadpisze?

GLOBALi... nie używaj smile.gif albo się potem męcz.
Cytat(markac @ 22.11.2008, 18:17:09 ) *
Może w ogóle zrezygnować z szablonów w PHP i zrobić coś ala BBCode? smile.gif

Przeczytałeś to w ogóle??
Cytat(markac @ 22.11.2008, 18:17:09 ) *
Powtarzam, nie ma idealnej aplikacji. KOMPROMIS KOMPROMIS KOMPROMIS.

Jedno nie wyklucza drugiego. Jak mam kontrolę nad całym kodem, to mam pisać z globalami bo tak wygodniej?
Wiem, że czasami się nie da i właśnie to jest przyczyną wielu straconych godzin k***ienia na klawiaturą smile.gif

Pozdrawiam, Alan
wlamywacz
Dołączę się do tematu. Jak napisać obsługę DB tak aby nie korzystać z singletona i registry ? Jak złapać uchwyt? Czy po prostu zrobić tak aby router wywołując daną klasę przekazywał do niej uchwyt ?
Maciekbjw
Cytat(Jawor @ 9.11.2008, 16:40:46 ) *
Rozwiniesz snitch.gif ?


Możesz też zrobić tak (rozwiązanie raczej nieeleganckie, ale jedno z możliwych tongue.gif)

  1. <?php
  2. class News {
  3.  
  4. public function __construct()
  5. {
  6.  global $pdo;
  7.  $this->pdo = $pdo;
  8. }
  9. public function GetAll()
  10. {
  11. return $this->pdo->query("SELECT * FROM `news` ORDER BY `id_news` DESC");
  12.  
  13. }
  14. }
  15. ?>

Pozdrawiam.
Mize
Przeczytaj cały wątek i potem swój kod.

Ale o co tu sie spieramy, czy to jest dobre, że np. w szablonie możemy zrobić coś takiego...

  1. <div id="foo">
  2.  
  3. <?php Registry::getInstance()->Get('DB')->Execute( ... ); ?>
  4.  
  5. </div>


Skoro ma to być możliwe to po co te warstwy, jak widok grzebie w bazie.

Cytat
Aplikacja ma przede wszystkim działać...


To po co pisać obiektowe frameworki, skoro można napisać prawie wszystko strukturalnie. PHP4 wita. smile.gif
xmarcin
Cytat(LBO @ 22.11.2008, 17:12:06 ) *
Tak też można, jeżeli nie chcesz by News miał dostęp do czegokolwiek innego niż PDO to możesz o tak:


ok, ale jakie elemnty sa godne umieszczenia tam? moze jakas funkcja od bbcode, czy cos innego?
nie wiem, co tam jeszcze moze sie nadawac (stad sie wzielo to moje pytanie powyzej)
Mize
To co Ci będzie potrzebne ?
Skąd mamy wiedzieć co tam umieścić skoro nie wiemy co chcesz osiągnąć ? worriedsmiley.gif
xmarcin
fakt... troche nie sprecyzowalem...
juz nie bede drazyc tego watku, bo robie offtop blinksmiley.gif
wrzasq
Ot, i najlepiej jeszcze podciągnijcie pod to walkę o wolność tybetu i ochronę pingwinów w okresie godowym.

Owszem, dobre praktyki dobrymi praktykami, ale autor tematu zapytał się, jak lepiej opracować połączenie z bazą danych. A wy jak w niemal każdym wątku na forum zaczynacie walkę w stylu Singleton <> Registery <> Context <> FooBar. Ludzie - to wszystko jest tworzone po to, aby ułatwiać życie, a nie komplikować. Podstawową zasadą każdego programu/skryptu jest to, ze ma działać dobrze i wydajnie. Jak ktoś to potrafi osiągnąć w inny sposób to nie znaczy, że ten sposób jest z zły. W PHP przecież i tak jest sporo niespójności w samym języku, więc samobiczowanie się tak ciągle i tak wcale nie sprawi, że wszystko będzie super tongue.gif.

I co do mnie prywatnie, tak wracając do tematu, to do połączeń z bazą danych używam swojej klasy, która po prostu dziedziczy po PDO i ustawiam ją w rejestrze. Uważam, że nie ma potrzeby pałować się z jakimiś elokwencjami w przekazywaniu wszędzie tej instancji - na poziomie modelu/kontrolera i tak będzie ona potrzebna niemal wszędzie, więc ciągłe dopisywanie tego samego jest bez sensu - po to stworzone pewne konstrukcje, żeby zadania automatyzować.
Black-Berry
@wrzasq Zgadzam się z tobą. Co byś nei zrobił zawsze zostanie niedosyt ale żeby nie było niedomówień:

Jeśli masz jeden obiekt główny po którym dziedziczą inne to ustwaiasz kontekst za pomocą odziedziczonej metody initialize(Context $context); Rejestr ma swoje zalety tak jak i singleton ale jak dla mnie to singleton jest czymś nienormalnym i źle mi się to w głowie układa. Raz miałem serwer z jakąś dziwną wersją PHP i przez tego singletona musiałem klientowi przepisać spory kawałek kodu bo nie chciał działać. Poza tym singleton kojarzy mi się z jakimś "szarlataństwem" programistycznym. To jakaś sztuczka smile.gif

Pozdrawiam.
starach
Troszkę się zastanawiałem nad tą dyskusją i najpierw doszedłem do wniosku że rejestru faktycznie nie należy używać, mimo iż sam go stosuję.
Z drugiej jednak strony rejestr ( a dokładniej Registry + Abstract Factory, w moim przypadku ) ma jedną niepodważalną zaletę.

Czytelność...

  1. <?php
  2. // Załaduj plik klasy, utwórz nowy obiekt i nie zapisuj w rejestrze tylko zwróć
  3. $ob = Instance::Get('library.template.cache.data.package.collection', '', Instance::RETURN_INSTANCE);
  4. // Pobierz obiekt z rejestru, ładując plik klasy jeśli nie ma go w rejestrze
  5. $ob = Instance::Get('library.template.cache.data.package.collection');
  6.  
  7. // A mógłbym mieć tak
  8. $ob = new Template_Cache_Data_Package_Collection();
  9. ?>
Moim skromnym zdaniem o wiele czytelniejszy jest mój sposób.
Brak konieczności używania __autoload() / include / require czy przestrzeni nazw.
Oczywiście istnieje cały czas ryzyko nadpisania obiektu w rejestrze przez nieuwagę, ale jest to cena z jaką mogę żyć...
Poza tym zawsze można dodać mechanizm blokowania nadpisania niektórych obiektów. Wczytywanych powiedzmy z pliku konfiguracyjnego.

Wpadłem również na inny pomysł. Dodam do klasy Instance wykrywanie prefiksów - ARI_ oraz ARR_ - do nazw klas. W pierwszym przypadku będzie to informacja żeby Instance zawsze zwracała nową klasę - Always Return Instance. Natomiast w drugim tylko referencję - Always Return Reference. I problem nadpisywania mam niejako z głowy. smile.gif

Chociaż oczywiście jak to ktoś miał tutaj w sygnaturce "Jeśli ktoś wynajdzie idioto-odporny system, ktoś inny zawsze wynajdzie lepszego idiotę" - Czy jakoś tak - ale tą zasadę można odnieść również do wzorca Context jak i pozostałych. Czyli innymi słowy nie ma rzeczy doskonałych.
dr_bonzo
  1. <?php
  2. // Załaduj plik klasy, utwórz nowy obiekt i nie zapisuj w rejestrze tylko zwróć
  3. $ob = Instance::Get('library.template.cache.data.package.collection', '', Instance::RETURN_INSTANCE);
  4. // Pobierz obiekt z rejestru, ładując plik klasy jeśli nie ma go w rejestrze
  5. $ob = Instance::Get('library.template.cache.data.package.collection');
  6. ?>


Yh, i walsnie podpowiadanie skladni (metod, itd) poszlo sie je*****c. Jak dla mnie to MEGA wada. Ja moze pamietam z 5% nazw metod, do tego czesto miewaja dlugie nazwy.
U siebie mam kontekst z glownymi danymi (GET, POST, sesja i inne), do tego kilka singletonow (fabryki ktore musze skonfigurowac raz, a potem tworza mi konkretne obiekty)
starach
Tak coś właśnie czułem że ktoś będzie miał uraz do tego. biggrin.gif

Zwróć uwagę na to że ta ścieżka to są katalogi, przedzielone kropkami. Z czego ostatni jest plikiem wczytywanym lub zarówno katalogiem i plikiem wczytywanym. Czyli data.package.collection może być Data/Package/Collection.php albo Data/Package/Collection/Collection.php dzięki temu zamiast wpisywać data.package.package żeby dostać obiekt reprezentujący element kolekcji wpisuję data.package.

Chyba zapamiętasz rozmieszczenie katalogów, patrząc chwilę na drzewo katalogów projektu w edytorze.
Reszta to tylko kwestia szybkości pisania na klawiaturze. A sądząc po tym forum przeciętna prędkość pisania jego użytkowników to dwie klawiatury na rok ^^.

edit>
Co do metod to też miałbym z tym problemy. Jednak składnia PHPDocumentator'a rozwiązuje ten problem.
Używa jej w mechanizmie podpowiadania składni np. Zend Studio czy PHP Eclipse. A założę się że nie są to wszystkie kombajny które to obsługują.
Jedynym tego mankamentem jest konieczność korzystania z minimum 4 linijkowej deklaracji zmiennych klasowych.

edit>>
Może niech któryś przeciwnik Rejestru wrzuci tutaj przykładową klasę, a ja ją chętnie napiszę po swojemu.
Tak naprawdę sam nie jestem do końca przekonany co do słuszności mojego rozwiązania i chętnie bym je sprawdził nieco dokładniej. smile.gif
dr_bonzo
Cytat
Chyba zapamiętasz rozmieszczenie katalogów, patrząc chwilę na drzewo katalogów projektu w edytorze.
Reszta to tylko kwestia szybkości pisania na klawiaturze. A sądząc po tym forum przeciętna prędkość pisania jego użytkowników to dwie klawiatury na rok ^^.

Rozmieszczenie to nie problem, szczegolnie ze nazwa klasy == katalog.

Ale! Nie bede pamietal nazw tysiaca metod jakie zdefiniowalem: http://a1.s3.p.quickshareit.com/files/picture2e92b0.png

a u ciebie trace informacje jakiej klasy to obiekt, wiec nie moge skorzystac z podpowiadania metod.
starach
Heh. Edytowałem post przy użyciu szybkiej edycji i nie zauważyłem że odpowiedziałeś wcześniej. tongue.gif

Cytat
edit>
Co do metod to też miałbym z tym problemy. Jednak składnia PHPDocumentator'a rozwiązuje ten problem.
Używa jej w mechanizmie podpowiadania składni np. Zend Studio czy PHP Eclipse. A założę się że nie są to wszystkie kombajny które to obsługują.
Jedynym tego mankamentem jest konieczność korzystania z minimum 4 linijkowej deklaracji zmiennych klasowych.

edit>>
Może niech któryś przeciwnik Rejestru wrzuci tutaj przykładową klasę, a ja ją chętnie napiszę po swojemu.
Tak naprawdę sam nie jestem do końca przekonany co do słuszności mojego rozwiązania i chętnie bym je sprawdził nieco dokładniej. smile.gif


edit>
Dodatkowo ZS ma jeszcze inny rodzaj podpowiadania składni
  1. <?php
  2. $ob = Instance etc.
  3. /* @var $ob Moj_Przefajny_Obiekt */
  4. $ob->typeHintingJakTaLala()
  5. ?>
No my tu gadu gadu a tutaj już po 4. Dobranoc.
P.S. Chętnie przepiszę jakąś twoją klasę na swój styl. Ciekawość mnie zżera czy nie próbuję wyważyć otwartych drzwi. smile.gif
markac
Sorry orglee, ale ja już wolę __autoload. W systemie nie powinny wystąpić klasy o tych samych nazwach i dlatego ryzyko kolidowania klas spada do minimum. Przykład:

Andrew: 03-Nov-2006 12:26

  1. <?php
  2.    function __autoload($class_name)
  3.    {
  4.        //class directories
  5.        $directorys = array(
  6.            'classes/',
  7.            'classes/otherclasses/',
  8.            'classes2/',
  9.            'module1/classes/'
  10.        );
  11.      
  12.        //for each directory
  13.        foreach($directorys as $directory)
  14.        {
  15.            //see if the file exsists
  16.            if(file_exists($directory.$class_name . '.php'))
  17.            {
  18.                require_once($directory.$class_name . '.php');
  19.                //only require the class once, so quit after to save effort (if you got more, then name them something else
  20.                return;
  21.            }          
  22.        }
  23.    }
  24. ?>


Mamy w ten sposób także uzupełnianie kodu w Eclipse, oczywiście jeśli zastosujemy odpowiednie tagi dokumentujące same klasy. Co do Registry, chyba Ty to napisałeś, że istnieje możliwość nadpisania? Mylisz się. W takich przypadkach nie stosuje się get() i set(), a odpowiednio nazwane metody, np. getPDO(), getSession(). Mamy w ten sposób załatwione także uzupełnianie kodu i wykluczenie możliwości nadpisania kodu. Samo zastosowanie get i set jest to po prostu lenistwem, niedoświadczeniem i posiadaniem złych nawyków, o dziwo, dotyczy tylko programistów PHP?
dr_bonzo
@orgle: ZS ma, eclipse nie ma, mi wystarczy jak napisze phpdoc'e od metody - nie chce mi sie dodatkowo dla kazdej zmiennej pisac /* @var */.

@markac
Cytat
Sorry orglee, ale ja już wolę __autoload. W systemie nie powinny wystąpić klasy o tych samych nazwach i dlatego ryzyko kolidowania klas spada do minimum. Przykład:

Eh, ja w generatorze mapy (skanuje pliki php i zapisuje w ktorym jest ktora klasa, a aplikacja korzysta potez z samej mapy) mam sprawdzenie czy aby nazwy klas sie nie powtarzaja (ile to godzin kurwowania - czemu tych zmian nie widac; a mialem skopiowane klasy pod nowy modul, ale im nazw nie zmienilem, i nie te klasy sie zalaczaly co mialy smile.gif)
mike
Cytat(dr_bonzo @ 3.12.2008, 10:29:37 ) *
@orgle: ZS ma, eclipse nie ma, (...)
O kurcze, to ja cały czas piszę w Eclipse i korzystam z czegoś czego on nie ma? tongue.gif
Eclipse również podpowiada składnię w ten sposób.
starach
Cytat(markac @ 3.12.2008, 09:23:38 ) *
Sorry orglee, ale ja już wolę __autoload. W systemie nie powinny wystąpić klasy o tych samych nazwach i dlatego ryzyko kolidowania klas spada do minimum.
Nie ma możliwości że wystąpią.
  1. <?php
  2. $ob = Instance::Get('library.template.cache.data.package.collection');
  3. ?>
Kod załaduje plik w katalogu "[projekt_root]/library/Template/Cache/Data/Package/Collection.php" ( wielkość liter nieprzypadkowa ) i utworzy obiekt klasy Template_Cache_Data_Package_Collection lub zwróci go z rejestru jeśli był już utworzony wcześniej.
W zmiennych klasowych stosuję nazewnictwo rozróżniające czy dana zmienne jest obiektem czy prymitywem ( $this->counter - obiekt $this->_counter = integer / float / double / etc. ). Mimo to nie wyobrażam sobie żeby nie napisać PHPDoc'owego @var celem lepszej czytelności i przejrzystości.

Cytat(markac @ 3.12.2008, 09:23:38 ) *
Co do Registry, chyba Ty to napisałeś, że istnieje możliwość nadpisania? Mylisz się. W takich przypadkach nie stosuje się get() i set(), a odpowiednio nazwane metody, np. getPDO(), getSession(). Mamy w ten sposób załatwione także uzupełnianie kodu i wykluczenie możliwości nadpisania kodu. Samo zastosowanie get i set jest to po prostu lenistwem, niedoświadczeniem i posiadaniem złych nawyków, o dziwo, dotyczy tylko programistów PHP?
Stosowanie setterów i getterów dla poszczególnych obiektów moim zdaniem nie jest wygodnym rozwiązaniem bo kompletnie burzy intuicyjność frameworka. Jest to coś czego nienawidzę na przykład w Joomli. Różnica między zaproponowanym przez ciebie rozwiązaniem i Jomlowym jest taka, że Joomla ma statyczne gettery w swoim rejestrze. Nazywam to singleton overflow. tongue.gif
markac
Cytat(orglee @ 3.12.2008, 16:52:57 ) *
Stosowanie setterów i getterów dla poszczególnych obiektów moim zdaniem nie jest wygodnym rozwiązaniem bo kompletnie burzy intuicyjność frameworka. Jest to coś czego nienawidzę na przykład w Joomli. Różnica między zaproponowanym przez ciebie rozwiązaniem i Jomlowym jest taka, że Joomla ma statyczne gettery w swoim rejestrze. Nazywam to singleton overflow. tongue.gif


Przecież ja piszę o statycznych metodach... Co Ci burzy? Jaka intuicyjność? Podawanie ścieżek i nazw po kropce, które w twoim wypadku zajmują cały ekran jest intuicyjne? Pamiętać strukturę katalogów też jest intuicyjne? Zresztą, nikogo na siłe nie będę przekonywał smile.gif Widać, że programujesz w notatniku, wiec nie widzisz zalet uzupełniania kodu smile.gif
starach
Uhh ależ mi dopiekłeś. Programuje w notatniku na windowsie 3.11. Chyba pójdę sobie w kącik, cichutko popłakać.
edit>
Co ja gadam. Przecież ja piszę kod na glinianej tabliczce rysikiem. Potem wysyłam do przedszkola, żeby dzieci mi zrobiły kolorowanie składni.
<edit

Pisałem już to w tym temacie co najmniej 2 razy. Dajcie mi kawałek kodu. Przepiszę go po swojemu i każdy będzie mógł sobie porównać co mu jest wygodniej stosować. Cały czas szukam wygodniejszych i wydajniejszych sposobów pisania kodu. Macie okazje przekonać sceptyka. Jeśli wam na tym nie zależy to po co się wdajecie ze mną w dyskusję... Olać mnie po prostu i nie odpisywać.

Chociaż myślałem że forum.php.pl jest miejscem gdzie różne poglądy ścierają się ze sobą i nanoszą. Tworząc nowe i lepsze poglądy oraz rozwiązania.
Black-Berry
Cytat(orglee @ 3.12.2008, 16:52:57 ) *
Stosowanie setterów i getterów dla poszczególnych obiektów moim zdaniem nie jest wygodnym rozwiązaniem bo kompletnie burzy intuicyjność frameworka. Jest to coś czego nienawidzę na przykład w Joomli. Różnica między zaproponowanym przez ciebie rozwiązaniem i Jomlowym jest taka, że Joomla ma statyczne gettery w swoim rejestrze. Nazywam to singleton overflow. tongue.gif


Sory trochę zgubiłem się w temacie ale czy stosowanie getterów i setterów jest takie niezbędne do rozwiązania kontekstowego? Przecież wszystko można oprzeć o jakieś dziedziczenie. Gdzieś już tutaj pisałem o tym razem z przykładowym kodem. Każdy obiekt dziedziczący po obiekcie klasy Core_Context automatycznie może ustawiać sobie obiekty wymagane. Jeśli już chcemy wszystko zautomatyzować to poprostu każdy obiekt w naszym frameworku traktujemy jako Core_Object i po krzyku. Takie coś:

  1. <?php
  2. $ob = Instance::Get('library.template.cache.data.package.collection');
  3. ?>


Może i jest pomysłowe ale czy istnieje w jakimkolwiek poważnym oprogramowaniu? Wiem, że PHP można różnie traktować ale wydaje mi się że uniwersalne rozwiązania są najlepsze. Nawet jeśli nikt nie ma pracować w przyszłosci na Twoim kodzie tylko ty sam to trzeba dążyć do czegoś co akceptuje większość społeczności programistycznej nie tylko ta z PHP. (Sam mam jeszcze masę nietrafionych rozwiązań w swoim frameworku ale systematycznie je poprawiam. Nie piszę tutaj żeby komuś coś wytykać)

Pozdrawiam.
erix
Cytat
Może i jest pomysłowe ale czy istnieje w jakimkolwiek poważnym oprogramowaniu?

I tu sie mylisz. winksmiley.jpg Gdyż z tego, co miałem do czynienia z językami programowania, to obiekty oddzielano właśnie poprzez kropki. Takie rozwiązanie jest stosowane choćby w Pythonie. W Javie chyba jest tak samo. winksmiley.jpg A że PHP stosuje kropkę do łączenia stringów i do obiektów można się odwoływać przez "strzałki", to niektórzy programiści robią takie obejścia... :S

Osobiście nie popieram takich rozwiązań w PHP ("kropkowanie").
Black-Berry
Tak ale tam jest to rozwiązanie wbudowane a nie parser napisany przez użytkownika. To zasadnicza różnica myślę smile.gif

Zresztą chodziło mi o ideę pobierania z rejestru obiektów za pomocą stringu a nie sam sposób zapisu. Trochę to... no wiecie... nie pokazałbym tego "na salonach" smile.gif
markac
Cytat(Black-Berry @ 4.12.2008, 14:49:57 ) *
Sory trochę zgubiłem się w temacie ale czy stosowanie getterów i setterów jest takie niezbędne do rozwiązania kontekstowego? Przecież wszystko można oprzeć o jakieś dziedziczenie. Gdzieś już tutaj pisałem o tym razem z przykładowym kodem. Każdy obiekt dziedziczący po obiekcie klasy Core_Context automatycznie może ustawiać sobie obiekty wymagane. Jeśli już chcemy wszystko zautomatyzować to poprostu każdy obiekt w naszym frameworku traktujemy jako Core_Object i po krzyku. Takie coś:


Nie obrażając nikogo, ale nie masz pojęcia o programowaniu obiektowym... Co ma np. wspólnego klasa DB (np. PDO) z klasą powiedzmy Kota? Używając dziedziczenia (Kot dziedziczy po DB), dajesz do zrozumienia, że klasa kota jest klasą rozszerzającą mozliwosci klasy DB, co jest nieprawdą.
Do tego pozwalasz używać klasę Kota tak, jakby to była klasa DB... I teraz prosty przykład:

  1. <?php
  2. if ($kot instanceof $db)
  3.  echo "to jest klasa db";
  4. ?>


Trochę to dziwne? Rozumiem, że kot może być klasą pochodną klasy Zwierzak, a ten z kolei klasy Ssak, ale nie WTC na miłość boską, chociaz nikt Ci tego nie zabroni smile.gif Przepraszam za takie łopatologiczne przykłady, ale nie umiem tłumaczyć. Najlepiej zacząć rozpisywać to w UML, wtedy ujrzysz, że to nie ma sensu. Każdy początkujący programista próbuje wyprowadzać z klasy np. MySQL następne klasy tongue.gif
LBO
Klasyczny problem
Cytat
Telefonistka dziedziczy po telefonie


@Black-Berry, @markac zasadniczo ma rację. Do tego co ty opisujesz używa się interfejsów.
Black-Berry
@markac Ja nie mam pojęcia o programowaniu obiektowym?? Skoro tak to ty nie umiesz czytać bo napisałem ze jesli ktoś chce sobie zautomatyzować to dziedziczy po Core_Object a nie po DB!! I DB i twój przykładowy kot może być obiektem dziedziczącym po Core_Object i nie mów mi że to nie logiczne bo kot jest zwierzęciem a nie obiektem jądra.
markac
Cytat(Black-Berry @ 4.12.2008, 14:49:57 ) *
Sory trochę zgubiłem się w temacie ale czy stosowanie getterów i setterów jest takie niezbędne do rozwiązania kontekstowego? Przecież wszystko można oprzeć o jakieś dziedziczenie. Gdzieś już tutaj pisałem o tym razem z przykładowym kodem. Każdy obiekt dziedziczący po obiekcie klasy Core_Context automatycznie może ustawiać sobie obiekty wymagane. Jeśli już chcemy wszystko zautomatyzować to poprostu każdy obiekt w naszym frameworku traktujemy jako Core_Object i po krzyku.


Pisałeś o Core_Context, a w kontekście może znajdować się dostęp do obiektu DB. Kontekst się deleguje, nie dziedziczy po nim.
Black-Berry
Tak, sory literówka. Dalej pisałem o Core_Object. Chodzi oczywiście o Core_Object. Przyznaję źle napisałem.
dr_bonzo
@mike

Cytat
Cytat
@orgle: ZS ma, eclipse nie ma, (...)

O kurcze, to ja cały czas piszę w Eclipse i korzystam z czegoś czego on nie ma?
Eclipse również podpowiada składnię w ten sposób.

Ehhh, rzeczywiscie dziala, nie wiem kiedy to dodali, ale nigdy mi nie dzialalo.
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.