Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]OOP na życiowym przykładzie?
Forum PHP.pl > Forum > Przedszkole
alex19
Nadszedł najwyższy czas żeby nauczyć się programowania obiektowego. Przeczytałem wiele tutoriali w sieci, ale to niestety dla mnie za mało. Wszędzie piszą co to klasa i tak dalej, ale nigdzie nie znalazłem wykorzystania w praktyce. Nie ma co ukrywać, że na jednej klasie żadnej projekt inny niż "hello world" nie powstanie.

Czy ktoś może polecić jakiś dobry tutorial gdzie były by jakieś zaaansowane przykłady programowania obiektowego?

Czego szukam? Na przykład sposobu na rozwiązanie takiego problemu:

Dajmy na to że mamy 3 klasy. Jedną swoją i dwie gotowe.

Klasa gotowa to np mPDF, która dla uproszczenia będzie wyglądała tak:
  1. class mPDF{
  2. function WriteHTML(){
  3.  
  4. }
  5. function Output(){
  6. /*jaks magia */
  7. }
  8. }


Kolejną gotową klasą będzie PHPmailer, który w uproszczeniu będzie taki:
  1. class PHPmailer{
  2. public $Host;
  3. public $SMTPAuth;
  4. public $Username;
  5. public $Password;
  6. public $SMTPSecure;
  7. public $From;
  8. public $FromName;
  9. public $addAddress;
  10. public $addAddress;
  11. public $addReplyTo;
  12. public $WordWrap;
  13. public $Subject;
  14. public $Body;
  15.  
  16. function addAttachment($att){
  17. /* cos sie dzieje */
  18. }
  19.  
  20. function isSMTP(){
  21. }
  22.  
  23. function isHTML(true){
  24. }
  25.  
  26. function send() {
  27. /*wysylka */
  28. }
  29. }


Teraz mamy sobie naszą własną klasę, która powiedzmy odpowiada za stworzenie faktury. Coś się dzieje i w efekcie otrzymamy HTML.
  1. class faktura{
  2. function generujDokument(){
  3. /* nie ważne co i jak, ważny efekt ;) */
  4. return $html;
  5. }
  6. }


Co bym chciał zrobić? Chciałbym wygenerować html z fakturą, następnie zrobić z tego pdf'a i wysłać go mailem do klienta. Pojawia się pytanie jak?

Oczywiście możemy potworzyć po koleji obiekty i "proceduralnie" wysłać naszą fkaturę, ale przecież nie o to chodzi.
  1. $fak = new faktura;
  2. $html = $fak->generujDokument();
  3.  
  4. $mpdf = new mPDF;
  5. $mpdf->WriteHTML($html);
  6. $pdf_file = 'filename.pdf';
  7. $mpdf->Output($pdf_file, 'F');
  8.  
  9. $mail = new PHPMailer;
  10. $mail->isSMTP();
  11. $mail->Host = 'smtp1.example.com;smtp2.example.com';
  12. $mail->SMTPAuth = true;
  13. $mail->Username = 'user@example.com';
  14. $mail->Password = 'secret';
  15. $mail->SMTPSecure = 'tls';
  16. $mail->From = 'from@example.com';
  17. $mail->FromName = 'Mailer';
  18. $mail->addAddress('joe@example.net', 'Joe User');
  19. $mail->WordWrap = 50;
  20. $mail->addAttachment($file_name);
  21. $mail->isHTML(true);
  22. $mail->Subject = 'Here is the subject';
  23. $mail->Body = 'This is the HTML message body <b>in bold!</b>';
  24. $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
  25. $mail->send();


To nie jest ładne rozwiązanie i najlepiej było by dodać do naszej klasy metodę
  1. function wyslijFakture(){
  2. /*pdf*/
  3. /*wyslanie maila*/
  4. }


Tylko pojawia się pytanie jak to zrobić?
golabow
Wykorzystaj kompozycje i dziedziczenie.
Mogłbyś też wykorzystać wzorzec projektowy "metoda szablonowa". Dzięki temu możesz zmieniać kroki twojego i robić różne "szablony" zależności od potrzeb.
W kodzie wyglądało by to tak:
  1. <?php
  2. abstract class Template {
  3. protected $mailWorker;
  4. protected $pdfWorker;
  5. protected $fakturaWorker;
  6.  
  7. public function prepareWokers() {
  8. $this->mailWorker = new PHPmailer;
  9. $this->pdfWorker = new mPDF;
  10. $this->fakturaWorker = new faktura;
  11. }
  12.  
  13. public function template() {
  14. $html = $this->generateFaktura();
  15. $file = $this->generatePDF( $html );
  16. $this->sendMail();
  17. }
  18.  
  19. abstract public function generateFaktura();
  20. abstract public function generatePDF( $html );
  21. abstract public function sendMail( $file );
  22. }
  23.  
  24. class Worker extends Template {
  25.  
  26. public function generateFaktura() {
  27. // tutaj kod
  28. }
  29.  
  30. public function generatePDF( $html ) {
  31. // tutaj kod
  32. }
  33.  
  34. public function sendMail( $file ) {
  35. // tutaj kod
  36. }
  37.  
  38. }
  39.  
  40. $woker = new Worker();
  41. $worker->prepareWokers();
  42. $worker->template();
  43. ?>
Pyton_000
@up Twój kod generuje zbędne obiekty.

Alex to co zrobiłeś jest prawie dobre Zrób na zasadzie:
  1. class faktura{
  2. function generujDokument(){
  3. /* nie ważne co i jak, ważny efekt ;) */
  4. $this->dok = $html;
  5. }
  6. function wyslijFakture(PHPMailer $mailer) {
  7. $mailer-> ....
  8.  
  9. }
  10. }
  11.  
  12. $faktura = new Faktura();
  13. $faktura->geerujDokument();
  14. $faktura->wyslijFakture(new phpMailer);


To co podałem nie jest jakies super ale zawsze możesz rozdzielić zadania i część wykonać, a część nie.
golabow
Warto jednak pamiętać o zasadzie jednej odpowiedzialności...
alex19
Cytat(golabow @ 9.08.2014, 13:46:41 ) *
Wykorzystaj kompozycje i dziedziczenie.
Mogłbyś też wykorzystać wzorzec projektowy "metoda szablonowa". Dzięki temu możesz zmieniać kroki twojego i robić różne "szablony" zależności od potrzeb.
W kodzie wyglądało by to tak:

Masz na myśli dziedziczenie po klasach PHPmailer i mPDF czy coś takiego jak w kodzie?
Kod jest fajny, ale to niestety moim zdaniem kod z serii "tych magicznych", które nie wiadomo co robią a działają.

Cytat(globalow)
Warto jednak pamiętać o zasadzie jednej odpowiedzialności...

O czym??

Cytat(Pyton_000)
Alex to co zrobiłeś jest prawie dobre Zrób na zasadzie:

  1.  
  2. class faktura{
  3. function generujDokument(){
  4. /* nie ważne co i jak, ważny efekt ;) */
  5. $this->dok = $html;
  6. }
  7. function wyslijFakture(PHPMailer $mailer) {
  8. $mailer-> ....
  9.  
  10. }
  11. }
  12.  
  13. $faktura = new Faktura();
  14. $faktura->geerujDokument();
  15. $faktura->wyslijFakture(new phpMailer);
  16.  


Czyli brak tu jakiejkolwiek filozofii... po prostu w obiekcie tworzony jest kolejny i tak dalej i tak dalej?

  1. function generujDokument(){
  2. /* nie ważne co i jak, ważny efekt ;) */
  3. $this->dok = $html;
  4. }

Rozumiem, że to uproszczenie i chodzi o podstawienie $html do zmiennej klasy, która tu nie została zdefiniowana?

  1. function wyslijFakture(PHPMailer $mailer)

Dlaczego tak, skoro dalej musimy zrobić
  1. $faktura->wyslijFakture(new phpMailer);


A co z "konfiguracja", tak jak w przypadku mailera? Czy można ją zdefiniować w jakiś inny sposób niż w metodzie? Tu akurat przykład jest taki sobie, ale myślę np pod kątem bazy danych - coś na zasadzie otwarcia połączenia/uchwytu na początku skryptu i korzystania z niego aż do zakończenia, tak żeby móc już tylko wykonywać zapytania do bazy i nie robić nic innego.
  1. ...
  2. ...
  3. ...


Jak by coś takiego wyglądało obiektowo, żeby nie powielać kodu, a korzystać bez ograniczeń z bazy (tej samej) z różnych obiektów w stylu:
  1. $faktura->zapisz();
  2. $klient->pobierz();
  3. $towar->usun();
  4. $dostawca->aktualizuj();
Wazniak96
Zobacz co kolega @pyton_000 dał jako argument metody wyslijFakture. Znajduje się tam taka fraza jak "PHPmailer". Jest to rzutowanie danych. To znaczy, że metoda ta przyjmie jako argument tylko obiekt klasy PHPMailer.

Ogólnie poczytaj o takim wzorce jak wstrzykiwanie zależności (Dependency Injection) wink.gif
alex19
Cytat(Wazniak96 @ 9.08.2014, 19:41:14 ) *
Zobacz co kolega @pyton_000 dał jako argument metody wyslijFakture. Znajduje się tam taka fraza jak "PHPmailer". Jest to rzutowanie danych. To znaczy, że metoda ta przyjmie jako argument tylko obiekt klasy PHPMailer.

Ogólnie poczytaj o takim wzorce jak wstrzykiwanie zależności (Dependency Injection) wink.gif


Poczytam, ale zanim to zrobię to zapytam wink.gif

Czy to jest obowiązkowe czy też jako "zabezpieczenie"i dobra praktyka, czy można by było dać jako argument metody tylko $mail.
Wazniak96
Jest to po prostu wymuszenie przekazania tego właśnie obiektu do metody. Dlaczego nie tworzyć bezpośrednio obiektu w metodzie? Bo zakładamy, że w skrypcie używasz już mailera to po co kolejny raz pobierać konfigurację skoro możesz przekazać ten sam obiekt, którego używałeś już do czegoś innego? wink.gif

PS: Jest to moje rozumowanie. Sam dopiero uczś się OOP. Jeśli wprowadzam w błąd proszę bardziej zaawansowanych o poprawę. smile.gif
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.