Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Programowanie obiektowe - początki
Forum PHP.pl > Forum > PHP
Damiankossek
Witam, chciałbym nauczyć się programować obiektowo. Strukturalnie już jako tako umiem, potrafie napisać jakiegoś małego CMS ... smile.gif
Czytałem dziś pół dnia na temat obiektówki ale jakoś i tak mało zrozumiałem... Teoretycznie chyba rozumiem, ale praktycznie nie potrafie tego zastosować.
Więc po całym dniu czytania spróbowałem coś napisać i napisałem skrypty wyświetlający wiadomości z funkcją ograniczania wyników. No i udało się, pełni swoją funkcje ...
Lecz naprawde nie wiem czy On jest poprawnie napisany obiektowo, może wy sprawdzicie i mnie `nasterujecie` na prawidłową droge smile.gif A oto kod:

  1. <?php
  2.  
  3. class Show
  4. {
  5. function __construct($where, $number)
  6. {
  7. $this -> where = $where;
  8. $this -> number = $number;
  9. if(!isset($_GET['page'])) { $this -> page = 0; }
  10. if(isset($_GET['page'])) { $this -> page = $_GET['page']; }
  11. $this -> result = $this -> number * $this -> page;
  12. }
  13.  
  14. function show()
  15. {
  16. $pdo = new PDO('mysql:host=localhost;dbname=BAZA', 'LOGIN', '');
  17. $request = $pdo -> query('SELECT * FROM '.$this -> where.' ORDER BY id DESC LIMIT '.$this -> result.','.$this -> number.'');
  18.  
  19. while($result = $request -> fetch())
  20. {
  21. print $result['subject']."<br/>";
  22. }
  23.  
  24. unset($request);
  25. }
  26.  
  27. function pages()
  28. {
  29. $pdo = new PDO('mysql:host=localhost;dbname=BAZA', 'LOGIN', '');
  30. $request = $pdo -> query('SELECT * FROM '.$this -> where.'');
  31.  
  32. $number_of_rows = $request -> rowCount();
  33. $number_of_pages = ceil($number_of_rows/$this -> number);
  34.  
  35. for ($i = 0; $i < $number_of_pages; $i++)
  36. {
  37. echo '<a style="margin: 5px;" href="?page='.$i.'">'.$i.'</a>';
  38. }
  39.  
  40. unset($request);
  41. }
  42. }
  43.  
  44. ?>


Mam właściwie jeszcze jedno pytanie, jak zaopatrzyć to w `skórki` ? Strukturalnie napisałem sobie skrypt który do tablicy pobiera plik i funkcją str_replace podmieniam treść. Sprawdza się to dobrze, ale obiektowo to raczej nie jest poprawnie. Pozdrawiam
marcio
Cytat
Mam właściwie jeszcze jedno pytanie, jak zaopatrzyć to w `skórki` ? Strukturalnie napisałem sobie skrypt który do tablicy pobiera plik i funkcją str_replace podmieniam treść. Sprawdza się to dobrze, ale obiektowo to raczej nie jest poprawnie. Pozdrawiam


Poczytaj o mvc, zreszta prosty szablon moze byc i parsowany, tzn masz pole %Autor% podpinasz pod nie autora.

Kod pisany chyba pod php4 bo nie wiedze zadnych zdefiniowanych dostepow do metod.

Po 2 masz pola where i number ale nigdzie ich nie deklarujesz.

skowron-line
A po co w każdej metodzie tworzysz obiekt PDO questionmark.gif Można to w konstruktorze zrobić i odwoływać się w każdej innej metodzie. Nie obawiaj się konstrukcji typu
  1. $this->pdo->query( 'SELECT ... LIMIT 1' );

Raz masz print raz echo questionmark.gif zdecyduj się na jedno.
W klasie nic nie powinno być wyświetlane metody powinny coś zwracać przez return.
  1. if(![url="http://www.php.net/isset"]isset[/url]($_GET['page'])) { $this -> page = 0; } if([url="http://www.php.net/isset"]isset[/url]($_GET['page'])) { $this -> page = $_GET['page']; }

To też możesz wogóle poza klasę wyrzucić i odwołując się do konkretnej metody podać jako parametr numer strony.
No i jak kolega wcześniej napisał poziomy dostępu do metod i zmiennych ( zmiennych nie ma więc w tym przypadku tylko metod ).
Damiankossek
No juz konstruktor wczoraj rozgryzłem i zrobiłem tak jak mówisz smile.gif W każdej metodzie odwołuje się do konstruktora i dodałem jeszcze destruktor który niby ma mnie rozłączać z bazą danych.
Tylko nie rozumiem tych `poziomów dostępu do metod i zmiennych`. Ide teraz do pracy, jezeli komus bedzie sie chcialo moze wyjasnic:)
Ale to tylko za odrobiną chęci, jeżeli nie to poczytam sobie póżniej jakieś `kursy` smile.gif

A jeszcze mam jedno pytanie bo w konstruktorze i destruktorze dałem tak:

  1. function __construct()
  2. {
  3. $this -> pdo = $pdo = new PDO(DANE);
  4. }
  5. function __destruct()
  6. {
  7. $this -> pdo = $pdo -> null;
  8. }


Czy to jest prawidłowe rozwiązanie ? Wyciągnałem to z jakiś kursów smile.gif Wszystko działa, tylko nie mam pewności co do funkcji destruct ... Pozdrawiam
marcio
Poczytaj o public,protected i private.

PDO nie znam wiec nie wiem ale ogolnie destruktor do rozlaczenia nie jest potrzebny bo baza sama powinna konczyc sesje polaczenia.




mike
Cytat(marcio @ 10.12.2009, 11:47:59 ) *
PDO nie znam wiec nie wiem ale ogolnie destruktor do rozlaczenia nie jest potrzebny bo baza sama powinna konczyc sesje polaczenia.
Dobrym nawykiem świadczącym o wiedzy jest kończenie połączenia samemu.
marcio
Cytat(mike @ 10.12.2009, 11:51:16 ) *
Dobrym nawykiem świadczącym o wiedzy jest kończenie połączenia samemu.


Ja tak robie,robilem i bede robic jednak nie raz na forum gdy podawalem kod powiedziano mi ze jest to niepotrzebne smile.gif


zzeus
Cytat(marcio @ 10.12.2009, 13:05:25 ) *
Ja tak robie,robilem i bede robic jednak nie raz na forum gdy podawalem kod powiedziano mi ze jest to niepotrzebne smile.gif


Zawsze znajdzie się ktoś, kto w danej kwestii będzie miał odmienne zdanie winksmiley.jpg
thek
Ja osobiście uważam, że jeśli tworzysz konstruktor, to powinieneś od razu stworzyć destruktor. Jakoś nie mam zaufania do wbudowanych rozwiązań określonych języków, które są podobne do działaniu do Garbage Collectorów w Javie. Ktoś, kto pracował w C++ i przydzielał dynamicznie pamięć wie o czym mówię. Pamięć może szybko "wycieknąć". To nie jest kwestia "może, ale nie musi być", tylko swego rodzaju niechlujstwa, choć może bardziej by pasowało "nadmiernego zaufania do języka". Większość dobrych nawyków programowania C++ potrafił mnie nauczyć, bo jest pod tym względem niezbyt litościwy winksmiley.jpg Po przejściu "podstaw szkoły C++" człowiek zaczyna nawet w bardzo przyjaznych językach zwracać uwagę na drobiazgi, które inne języki, takie jak PHP akceptują i wyręczają nas w tym częściowo. Choćby w PHP używanie mysql_close() czy mysql_free_result() są takimi "archaizmami", które wiele osób odpuszcza, bo wie, że i tak zasoby będą zwrócone po wykonaniu skryptu. Szkoda tylko, że część osób nie wie, że owe rozwiązania też mają czasem problemy i pamiętam jak na studiach się dziwiłem błędami pisząc w Javie, gdy po zakończeniu miałem błędy. GC Javowski po prostu miał problem ze zwróceniem do systemu dynamicznie przydzielonej pamięci. Od tamtego czasu jego (GC) kod poprawili i coraz rzadziej to się ludziom zdarza, ale zapewne wciąż nie jest rozwiązane idealnie. Stąd to programista powinien dbać o pamięć i nie zdawać się na wbudowane narzędzia.

Osoby tworzące kod bez dbania o destruktory same proszą się o problemy w przyszłości. Nie po to owe metody powstały by były sztuką dla sztuki. Są w określonym celu i należy o nich pamiętać. Oczywiście zwracanie do systemu pamięci rezerwowanej przez typy proste jest już przegięciem w drugą stronę. Wszystko z głową należy robić.

Jednym zdaniem: "Jeśli gdzieś definiujesz w programowaniu obiektowym konstruktor, destruktor też od razu napisz, a unikniesz problemow na przyszłość."

@bottom: (To Mike): Bo kilka lat w poprawianiu kodu GC w Javie zrobiło swoje winksmiley.jpg Gdy na studiach pisałem w nim kod to gubił z pamięci nie kB, ale MB pamięci bardzo szybko, a soft był odpalany nie przez minutę ale chodził nieraz godzinami odpalając się w wielu wątkach smile.gif Pamięc tak dostawała w czapę, że trochę pochodził i się wysypywał bez ostrzeżeń winksmiley.jpg GC tylko częściowo sobie z tym problemem radził bo usuwał zmienne obiektu dla niego widoczne, ale "gubił", tę część pamięci którą gdzieś mu dynamicznie przydzielałem smile.gif Czasem ją przechwycił, czasem nie i stąd trudno się z początku było połapać co jest nie tak. Stąd teraz byle pierdółkami się przejmuję, by takiego szukania w pozornie bezbłędnym kodzie unikać. Bo przecież pod względem języka jest on poprawny, co tylko bardziej irytuje przy ego wyłapywaniu. Wiesz, że coś nie działa, ale nie można ściśle określić miejsca problemu na pierwszy rzut oka.

@bottom: (To darko): Postaram się takie zwięzłe streszczenia pisać, choć nie zawsze jest to możliwe z racji opisywanego zagadnienia czy problemu.
mike
Cytat(thek @ 10.12.2009, 23:10:31 ) *
Jednym zdaniem: "Jeśli gdzieś definiujesz w programowaniu obiektowym konstruktor, destruktor też od razu napisz, a unikniesz problemow na przyszłość."
Ja tam w Javie nie mam destruktorów. I jakoś specjalnie mnie to nie martwi.
darko
OT, sorry
@thek: ja chyba będę czytał tylko to Twoje
Cytat
Jednym zdaniem:
, niech to będzie standardem, że na końcu będzie takie podsumowanie całego posta w jednym zdaniu smile.gif
Damiankossek
Witam, dzis wieczorem posiedzialem, poczytalem i postaralem sie zlepic skrypt do wyciagania danych z bazy a nastepnie ich parsowania do `motywu` smile.gif
Lecz nie wiem czy zrobilem to dobrze. Przyjzyjcie sie zwracaniu wynikow smile.gif Jezeli macie inne pomysly, linki co kolwiek co moze mi z tym pomoc to chetnie bym prosil.
Czy ten skrypt jest mniej-wiecej napisany obiektowo ? (To moj pierwszy skrypt w obiektowce, troche ciezko mi sie przestawic z kodu strukturalnego ale z tym walcze:) )
Pozdrawiam

  1. class Show
  2. {
  3. public $select;
  4. private $select_from;
  5. private $template;
  6.  
  7. public function __construct($select_from, $template)
  8. {
  9. try
  10. {
  11. $this -> pdo = $pdo = new PDO('mysql:host=localhost;dbname=, , '');
  12. }
  13. catch(PDOException $e)
  14. {
  15. echo Blad Polaczenia: ' . $e->getMessage();
  16. }
  17.  
  18. $this -> from = $select_from;
  19. $this -> template = $template;
  20. $this -> select = $select;
  21. }
  22.  
  23. public function __destruct()
  24. {
  25. $this -> pdo -> null;
  26. }
  27.  
  28. public function getcontent()
  29. {
  30. $pq = count($this->select);
  31.  
  32. for($i = 0; $i < $pq; $i++)
  33. {
  34. if($i != $pq-1)
  35. {
  36. $query .= $this->select[$i].",";
  37. }
  38. if($i == $pq-1)
  39. {
  40. $query .= $this->select[$i];
  41. }
  42. }
  43.  
  44. $request = $this -> pdo -> query("SELECT $query FROM $this->from");
  45. $number_of_rows = $request -> rowCount();
  46.  
  47. for ($i = 0; $i < $number_of_rows; $i++)
  48. {
  49. $result = $request -> fetch(PDO::FETCH_ASSOC);
  50. for($x = 0; $x < $pq; $x++)
  51. {
  52. $after[$x] = $result[$this->select[$x]];
  53. $before[$x] = strtoupper('['.$this->select[$x].']');
  54. }
  55.  
  56. $return .= show::tpl_parse($before, $after, $this -> template);
  57. }
  58. unset($request);
  59. return $return;
  60.  
  61. }
  62.  
  63. static function tpl_parse($before, $after, $tpl)
  64. {
  65. $file = file("templates/".$tpl);
  66. $count = count($file);
  67. for($i = 0; $i < $count; $i++)
  68. {
  69. for($x = 0; $x < count($before); $x++)
  70. {
  71. $file[$i] = str_replace($before[$x], $after[$x], $file[$i]);
  72. }
  73. $return .= $file[$i];
  74. }
  75. return $return;
  76. }
  77. }
  78.  
  79. $news = new Show("news", "news.tpl.html");
  80. $news -> select = array("subject", "content");
  81. print $news -> getcontent();
  82.  
  83.  
marcio
Nie jest zle ale jak dla mnie na twoim miejscu zmienilbym 3 rzeczy wedlug mojego punktu widzenia.

-Dodal setter na pole select

-Zmienilbym dostepy do wszystkich pol na protected

-Fukcji tpl_parse() dal dostep protected, bo jak narazie jest public.

dr4ko
Przepraszam za OT ale cała ta dyskusja o "poprawności manualnego wywoływania destruktora" mnie zmusza do zajęcia stanowiska winksmiley.jpg

Otóż proszę Państwa każdy obiekt w PHP ma destruktor, nawet jeśli go nie zadeklarujemy. I jest on automatycznie wywoływany przez parser PHP na końcu skryptu. Więc o ile nie chcemy zrobić czegoś dodatkowego, np zapisać finalnej struktury obiektu w pliku, przed zniszczeniem instancji to jego używanie jest nieuzasadnione. Wręcz kiedyś widziałem test który wykazywał spowolnienie działania aplikacji przy użyciu manualnych destruktorów.

Co do zamykania połączenia z bazą danych to robiąc to manualnie możemy co najwyżej spowolnić działanie aplikacji. Dopuszczalne to jest w momencie gdy korzystamy na stronie z bazy sporadycznie ale w normalnej sytuacji, gdzie każdy element strony wyciąga dane z bazy jest to wręcz niedopuszczalne.

Temat by można wydzielić do dyskusji bo jest w miarę ciekawy;) Jeszcze raz sorry za OT.
thek
To i ja znów zajmę stanowisko... Nie pisano tu o "manualnym wywołaniu destruktora" (a przynajmniej nie ja o tym pisałem) tylko o jego zdefiniowaniu w kodzie obiektu smile.gif To, że destruktor jest wywoływany zawsze przy niszczeniu obiektu jest wiadome i nawet jeśli obiekt nie posiada destruktora to pamięć związana z polami obiektu jest zwalniana automatycznie. Tyle że jeśli majstrujesz coś z dynamicznym przydziałem to można się przejechać na cieknięciu pamięci.
dr4ko
Dlatego napisałem w " " winksmiley.jpg Chodziło mi o właśnie definiowaniu destruktora w klasie. Sęk w tym że w PHP już w momencie tworzenia instancji obiektu parser PHP tworzy automatycznie metody konstruktora i destruktora. Więc one tam fizycznie są mimo że nie są zdefiniowane. Leak może powstać w dużych pętlach ale normalnie nie ma na to szans smile.gif
thek
Jeśli konstruktor polega jedynie na kombinowaniu z typami wbudowanymi czy prostymi obiektami to rzeczywiście jest to bezsensowne i mija się z celem tworzenie destruktorów. Jeśli jednak zaczyna się porządnie grzebać to przy większym obciążeniu czy choćby dużej ilości działań na obiektach, wielu odwiedzających, te "zgubione" skrawki pamięci się szybko namnażają i w efekcie wyczerpują zasoby dostępne dla strony na hostingu. Na szczęście "zarżynaczami" bawię się tylko na lokalu, ale niczym niezwykłym dla mnie jest choćby to, że wygenerowany plik ma ponad 1MB jako czysty html i potrafi kompowi zeżreć 1.5GB pamięci będąc pisany najbardziej optymalnie jak się tylko da.
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.