Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> opakowowywanie klas (wymuszanie wzorca dla klasy) ?
xajart
post
Post #1





Grupa: Zarejestrowani
Postów: 141
Pomógł: 1
Dołączył: 2.12.2008

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


Witam, ostatnio zasnatawia mnie czy w PHP można w jakiś sposób opakowąć klasę w swego rodzaju taki szablon (nie mam na myśli interfejsu). Może jest na to jakiś wzrorzec.

Załużmy że mam klasę (pisane z palca):

  1. class Model_Read extends Model_Data_Abstract
  2. {
  3. public $msg_no_params = 'string'
  4. public $msg_db_error = 'jakis string'
  5. public $msg_success = 'jakis string
  6.  
  7. public $params1= null
  8. public $params2 = null
  9.  
  10. public function test ()
  11. {...}
  12. .....
  13. }


i teraz chciałbym aby klasa Read korzystała z jakiegoś szablonu w którym wymuszone by miała ustawione parametry $msg_*

W ten sposób poprostu kolejne modele pisał bym w stylu

  1. class Model_Read extends Model_Data_Abstract
  2. {
  3. public $params= null
  4. public $params2 = null
  5.  
  6. public function test ()
  7. {...}
  8. .....
  9. }


A odwołując się do modelu móglbym ustawiac parametry dla np komunikatów:
  1. $dbModel = new Model_Read();
  2. $dbModel->msg_db_error = 'odpowiedni lang';
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 11)
toffiak
post
Post #2





Grupa: Zarejestrowani
Postów: 395
Pomógł: 80
Dołączył: 24.08.2009

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


Jeżeli dobrze rozumiem to chcesz aby obiekty miały dostęp do właściwości $msg_*, jeśli tak to wystarczy przenieść te właściwości do klasy abstrakcyjnej, uczynić je dziedziczonymi i dodać odpowiednie gettery i settery.


--------------------
Go to the top of the page
+Quote Post
xajart
post
Post #3





Grupa: Zarejestrowani
Postów: 141
Pomógł: 1
Dołączył: 2.12.2008

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


tak ale jak utworzę klasę abstrakcyjną dziedziczoną,
to Model_Read już dziedziczy po czymś, nie można dziedziczyć po dwóch rzeczach, musiało by to wyglądać tak

np
Model_Read extends Klasa_Abstrakcyjna
Klasa Abstrakcyjna extends Model_Data_Abstract

Pytanie tylko czy w Model_Read dam radę odwoływać się bezkonfliktowo do metod Model_Data_Abstract ?
Jeżeli zawiera on np właściwosći publiczne to czy z poziomu Model_Read uzyskam do nich dostęp (musiałbym chyba w Klasa_Abstract definiować, opakowywanie metod lub iplementowac interfejs, który mi to umożliwią).
Go to the top of the page
+Quote Post
CuteOne
post
Post #4





Grupa: Zarejestrowani
Postów: 2 958
Pomógł: 574
Dołączył: 23.09.2008
Skąd: wiesz, że tu jestem?

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


Raczej:

Model_Read extends Model_Data_Abstract
Model_Data_Abstract extends Klasa_Abstrakcyjna implements YYY_Interface
Klasa_Abstrakcyjna implements XYZ_Interface, ZXY_Interface

Ten post edytował CuteOne 26.09.2012, 09:55:42
Go to the top of the page
+Quote Post
viking
post
Post #5





Grupa: Zarejestrowani
Postów: 6 380
Pomógł: 1116
Dołączył: 30.08.2006

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


Mogą cię też zainteresować http://php.net/manual/en/language.oop5.traits.php


--------------------
Go to the top of the page
+Quote Post
xajart
post
Post #6





Grupa: Zarejestrowani
Postów: 141
Pomógł: 1
Dołączył: 2.12.2008

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


Cytat(CuteOne @ 26.09.2012, 10:54:23 ) *
Raczej:

Model_Read extends Model_Data_Abstract
Model_Data_Abstract extends Klasa_Abstrakcyjna implements YYY_Interface
Klasa_Abstrakcyjna implements XYZ_Interface, ZXY_Interface


Tak to by mi rozwiązało problem, tylko Mode_Data_Abstract dziedziczy po czymś tam znowu (nie wspominając że należy do bibliotek finalnych których nie mogę ruszyć).
Wiec zostaje w punkcie wyjścia wink.gif


Cytat(viking @ 26.09.2012, 11:03:01 ) *


To rozwiązanie od 5.4 (niestety nie zastosuje tego).
Go to the top of the page
+Quote Post
Crozin
post
Post #7





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Napisz jakie będzie przeznaczenie tego kodu, dlaczego tak chciałbyś to zrealizować, bo wygląda na to, że próbujesz rozwiązać jakiś problem w niewłaściwy sposób.
Go to the top of the page
+Quote Post
xajart
post
Post #8





Grupa: Zarejestrowani
Postów: 141
Pomógł: 1
Dołączył: 2.12.2008

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


Ogólnie wygląda to tak że buduję sobie listę modeli opartych na Zend_Db_Table i każdy model muszę opakowywać (wewnątrz) w listę właściwości typu:

public $msg_...

Zawierają one domyślny komunikat, są publiczne aby można było samodzielnie np przekazać treść komunikatów, np
standardowy komunikat dla akcji usuwania byłby np "pomyślnie usunięto pozycję", ale np dla konkretnego zdarzenia lepiej wygląda komunikat, który go bezpośrednio dotyczy, np dla listy produktu, informacje o tym że produkt został usunięty.

Niestety Zend_Db_Table sobie nie rozszerzę o takie właściwości.

Problem opakowywania nie jest jakimś dyskomfortem bo z IDE łatwo się to rozwiązuje, ale zastanawia mnie czy nie można tego rozwiązać inaczej aby zgodnie z DRY elementy które się powtarzają ulokować w jednym miejscu i w jakiś sposób implementować je tam gdzie są potrzebne.


Inny problem który napotykam podczas realizacji modeli jest taki że integrując go z zewnętrzna bazą która nie była projektowana pod kątem wymogów jakie narzuca Zend_Db_Table, muszę pisać obok metody do obsługi Danych (by uniemożliwić przkazanie innych wartości niż warunki jakie dostarcza baza). Niestety to rozwiązuję tworząc nowy obiekt Np dla Model_Products, tworzę object Model_Data_Products, do którego przekazuję listę parametrów (a on mi je parsuje). Choć wolałbym to inaczej rozwiązać (właśnie poprzez jakieś dziedziczenie, by wewnątrz klasy tylko się odwoływać do metod z Model_Data_Products). Ale obecnie moja wiedza chyba w tych tematach jest ograniczona, bo nie mam innego pomysłu jak to rozwiązać, bo nie da się dwa razy podziedziczyć po innej klasie, nie tworząc przy tym dwóch klass.

Skoro Model_Products dziedziczy po Zend_Db_Table_Abstract to nie podziedzice już po Model_Data_Products, owszem są interfejsy, ale przy nich nadal pojawia się problem z właściwościami.
Z tym że Model_Data_Products dziedziczy po Model_Data_Abstract i jak bym chciał to rozwiązać tak aby mieć dostęp do metod innej klawy w obecnej klasie musiało by wyglądać to tak:

1) Model_Products extends Model_Data_Products
2) Model_Data_Products extends Model_Data_Abstract
3) Model_Data_Abstract extends Zend_Db_Table_Abstract

Z tym że w pkt 1 chyba nie będę miał dostępu do metod z punktu 3 przez $this-> ?
A jeszcze jak bym chciał tu wprowadzić szablon dla tych komunikatów to musiałbym wpleść kolejne zależności, albo wklepać je do Model_Data_Abstract

Trochę chyba za bardzo przekombinowane by to było.
Go to the top of the page
+Quote Post
Crozin
post
Post #9





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Przede wszystkim, zacznij korzystać z normalnych przestrzeni nazw. PHP 5.3.0 ma już ponad 3 lata!

Problem tkwi zupełnie gdzie indziej - tak jak podejrzewałem źle zabrałeś się do swojego prawdziwego problemu, tj. wyświetlania użytkownikowi komunikatów. Model jest częścią aplikacji, która w ogóle nie powinna interesować się takimi pierdołami. Model ma za zadanie jedynie zwrócić informację o poprawnym wykonaniu operacji, tj. jakaś metoda z publicznego interfejsu powinna zwrócić true. Natomiast w przypadku niepowodzenia rzucenie wyjątku jest niemal zawsze odpowiednim rozwiązaniem. Wyjątek to również miejsce na zamieszczenie dokładniej informacji o błędzie. Oczywiście, takie dane nie powinny być prezentowane użytkownikowi.

Ustawienie odpowiedniego komunikatu będzie raczej leżało w gestii obiektu korzystającego z modelu, często będzie to kontroler, bądź inny model. Samo ustawienie czy też zwrócenie treści komunikatu powinno być oddelegowane do osobnego obiektu. Obiekt ten mógłby mieć prosty interfejs:
  1. public function getMessage($key, $object = null);
Gdzie $key to klucz komunikatu, np. entity.remove.success, entity.create.failure czy notification.entity_created.success. Opcjonalny argument $object to obiekt, którego dotyczy komunikat - umożliwiłby on spersonalizowanie komunikatu, np. Wiadomość "Hej xajart" została wysłana pomyślnie!.
Go to the top of the page
+Quote Post
xajart
post
Post #10





Grupa: Zarejestrowani
Postów: 141
Pomógł: 1
Dołączył: 2.12.2008

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


Okej, tylko nie rozumie do końca jak w Zendzie obsługiwać te błędy.

Jeżeli zrobię w metodzie:
  1. $data = array()
  2.  
  3. try
  4. {
  5. $sql = '...'
  6. $data = $this->fetchAll($sql)
  7. }
  8. catch (Zend_Db_Exception $e)
  9. {
  10. ...?
  11. }
  12.  
  13. return $data


To nie wie co powinienem zawrzeć w "catch", jeżeli wywali się zapytanie to fajnie by było mi to zapisać do logów (tutaj pewnie jakaś metodę opartą o Zend_Log musiał bym sobie napisać), ale muszę również użytkownika jakoś o tym poinformować w przyzwoity sposób, tylko jak w kontrolerze mam złapać ten wyjątek?

Nie wstawię przecież:
  1. echo $e->getMessage()


W necie nie mogą jakiegoś sensownego przykładu znaleźć.
Go to the top of the page
+Quote Post
Crozin
post
Post #11





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


1. Raczej nie powinieneś przy każdym zapytani stosować bloku try-catch, o ile rzeczywiście nie chcesz sensownie obsłużyć błędu. Logi? Oczywiście, tak! Ale przecież nie będziesz kodu odpowiedzialnego za zapis tych logów powtarzał za każdym razem. Gdzieś w jakimś "wyższym" miejscu aplikacji, utwórz blok try-catch, który wyłapie Ci wszystkie wyjątki typu Zend_Db_Exception wygenerowane przez aplikację (zapewne Zend już takie coś ma), tam wykonaj zapis logów, a użytkownika przekieruj do statycznej strony z informacją o wewnętrznym błędzie serwera (kod odpowiedzi: 500 Internal Server Error). Żadnych dodatkowych informacji poza sugestią odświeżenia strony nie powinno tam być - bo i po co?
Go to the top of the page
+Quote Post
viking
post
Post #12





Grupa: Zarejestrowani
Postów: 6 380
Pomógł: 1116
Dołączył: 30.08.2006

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


Zawsze możesz rozszerzyć Zend_Db_Exception o jakąś własną klasę i w niej dorobić ogólne logowanie. Ewentualnie jakiś singleton kolejkujący wszystkie wyjątki Logger::addLog($e->getMessage);


--------------------
Go to the top of the page
+Quote Post

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 Aktualny czas: 20.08.2025 - 14:57