Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][OOP] Czy to tak może być?
Forum PHP.pl > Forum > PHP > Object-oriented programming
terabit
Witam,
właśnie zacząłem próbować pisać cos obiektowo w php...

na razie wyszło mi coś takiego:


klasa do łączenia z bazą danych
  1. <?php
  2. error_reporting( E_ALL ); 
  3.  
  4. class polacz_sql {
  5.  
  6. private $sql;
  7.  
  8. public function __construct() {
  9.  
  10. $this -> db_host = '127.0.0.1'; // Adres serwera
  11. $this -> db_name = 'oop_cms'; // Nazwa bazy danych
  12. $this -> db_user = 'root'; // Nazwa uzytkownika
  13. $this -> db_password = 'root'; // Haslo
  14.  
  15. $this -> sql = mysql_connect($this -> db_host, $this -> db_user, $this -> db_password);
  16. mysql_select_db($this -> db_name);
  17.  
  18. if (!is_resource($this -> sql)) {
  19. die('Brak polaczenia z baza danych.' . mysql_error());
  20. }
  21.  
  22. }
  23.  
  24. public function __destruct() {
  25.  
  26. if(!is_resource($this -> sql)) {
  27. mysql_close($this -> sql);
  28. }
  29.  
  30. }
  31.  
  32. }
  33. ?>


klasa do zarządzania podstronami:
  1. <?php
  2. error_reporting( E_ALL ); 
  3.  
  4. require_once 'class.polaczenie_sql.php';
  5.  
  6. class podstrona extends polacz_sql {
  7.  
  8. public function pobierz_podstrone($id) {
  9.  
  10. $this -> res = mysql_query("SELECT * FROM podstrony WHERE id = '$id' LIMIT 1");
  11. return $this -> res;
  12.  
  13. }
  14.  
  15. public function edytuj_podstrone($id, $menu, $tresc) {
  16.  
  17. mysql_query("UPDATE `oop_cms`.`podstrony` SET `menu` = '$menu', `tresc` = '$tresc' WHERE `id` = $id LIMIT 1");
  18.  
  19. }
  20.  
  21. public function lista_podstron() {
  22.  
  23. $this -> res = mysql_query("SELECT id, menu FROM podstrony");
  24. return $this -> res;
  25.  
  26. }
  27.  
  28. public function usun_podstrone($id) {
  29.  
  30. mysql_query("DELETE FROM `podstrony` WHERE `id` = $id LIMIT 1");
  31.  
  32. }
  33.  
  34. public function dodaj_podstrone($nazwa) {
  35.  
  36. INSERT INTO `oop_cms`.`podstrony` (
  37. `id` ,
  38. `menu` ,
  39. `tresc`
  40. )
  41. VALUES (
  42. NULL , '$nazwa', ''
  43. )
  44. ");
  45.  
  46. }
  47.  
  48. }
  49. ?>


oraz zastosowanie:
  1. <?php
  2. error_reporting( E_ALL ); 
  3. include("class.podstrona.php");
  4. $objPodstrona = new podstrona();
  5. ?>
  6.  
  7. <h2>Edycja podstron</h2>
  8.  
  9. <?php
  10.  
  11. if(isset($_GET['zmien'])) {
  12. $objPodstrona -> edytuj_podstrone($_GET['zmien'], $_POST['menu'], $_POST['tresc']);
  13. }
  14.  
  15. if(isset($_GET['usun'])) {
  16. $objPodstrona -> usun_podstrone($_GET['usun']);
  17. }
  18.  
  19. if(isset($_GET['dodaj'])) {
  20. $objPodstrona -> dodaj_podstrone($_POST['menu']);
  21. }
  22.  
  23. if(isset($_GET['edycja'])) {
  24.  
  25. $res = $objPodstrona -> pobierz_podstrone($_GET['edycja']);
  26. while ($rekord = mysql_fetch_array($res)) {
  27. echo '
  28. Edycja podstrony:
  29. <form method="post" action="?zmien='.$rekord['id'].'">
  30. <input type="text" name="menu" value="'.$rekord['menu'].'" /><br />
  31. <textarea name="tresc">'.$rekord['tresc'].'</textarea><br />
  32. <input type="submit" value="Edytuj" />
  33. </form>
  34. ';
  35. }
  36.  
  37. }
  38.  
  39. ?>
  40.  
  41. <hr />
  42. Lista podstron:<br /><br />
  43.  
  44. <?php
  45.  
  46. $res = $objPodstrona -> lista_podstron();
  47.  
  48. while ($rekord = mysql_fetch_array($res)) {
  49. echo $rekord['menu'].' <a href="?edycja='.$rekord['id'].'">edycja</a> | <a href="?usun='.$rekord['id'].'">usun</a> <br />';
  50. }
  51.  
  52. ?>
  53.  
  54. <br /><hr /><br />
  55.  
  56. Dodaj podstrone:
  57.  
  58. <form method="post" action="?dodaj">
  59. <input type="text" name="menu" /><br />
  60. <input type="submit" value="Dodaj" />
  61. </form>


nie pisałem narazie nic wiecej, sprawdzania poprawnosci wpisanych danych itp.
czytałem kilka tematów na tym forum, starałem się nie popełniać błędów innych... wątpie żeby mi się to udało.. ale

mam kilka pytań winksmiley.jpg
1. co jest źle? co napisalibyście inaczej?
2. jak to poprawnie napisać stosując szablony MVC?
z tego co wiem to strona widoku może mieć PHP ale tylko podstawowa skladnia typu for, if, while...
tylko jak to rozbić na kontroler i model? czy przy tak prostych klasach jest to możliwe?
3. czy dobrze wykombinowałem z łączenie z bazą danych? czy może ta klasa być dziedziczona przez inne?
4. czy na stronie widoku mogę używać normalnych zmiennych typu $jakas_zmienna ? winksmiley.jpg

zaraz pewnie ktoś napisze ze to co zrobiłem to jeszcze nie prawdziwe OOP, ale to dopiero mój początek z OOP więc proszę o wyrozumiałość oraz wskazówki co mógłbym jeszcze tutaj zastosować winksmiley.jpg
wlamywacz
Pierwsze co się rzuca to brak oddzielenia kodu od treści.

  1. <?php
  2. public function edytuj_podstrone($id, $menu, $tresc) {
  3.  
  4. mysql_query("UPDATE `oop_cms`.`podstrony` SET `menu` = '$menu', `tresc` = '$tresc' WHERE `id` = $id LIMIT 1");
  5.  
  6. }
  7. ?>

Powinieneś zastosować returny abyś wiedział co dana funkcja zwraca.

  1. <?php
  2. $this -> db_host = '127.0.0.1'; // Adres serwera
  3. $this -> db_name = 'oop_cms'; // Nazwa bazy danych
  4. $this -> db_user = 'root'; // Nazwa uzytkownika
  5. $this -> db_password = 'root'; // Haslo
  6. ?>


Takie coś jest niezbyt ciekawe. Ja robię to tak przed wywołaniem głównego systemu systemu:
  1. <?php
  2. $db = new db;
  3. $db->setParam('user', $ini_array['mysql']['user']);
  4. $db->setParam('pass', $ini_array['mysql']['pass']);
  5. $db->setParam('name', $ini_array['mysql']['name']);
  6. $db->setParam('host', $ini_array['mysql']['host']);
  7. $db->connect();
  8. ?>

Nie stosuj die a return
Filtruj zmienne
terabit
Cytat(wlamywacz @ 9.07.2008, 19:40:09 ) *
Powinieneś zastosować returny abyś wiedział co dana funkcja zwraca.


ok ale jak mam np. cos takiego:
  1. <?php
  2. if(isset($_GET['usun'])) {
  3. $objPodstrona -> usun_podstrone($_GET['usun']);
  4. }
  5. ?>


to co mam przez zmienna wrzucić echo żeby wyświetliło to co zwraca return?
wlamywacz
Masz to źle zrobione powinno być tak:
  1. <?php
  2. class jakas {
  3.  
  4. function cos() {
  5.  
  6. $this->view->panel_admin($this->zapytanie_do_bazy_z_returnem($_POST['cos']));
  7. }
  8.  
  9. }
  10.  
  11. class view {
  12.  
  13. function panel_admina($result) {
  14.  
  15. echo $result;
  16. //Lub jakiś system szablonów
  17.  
  18. }
  19.  
  20. }
  21. ?>

Musisz przekazać dane z modelu do widoku który je wyświetli
terabit
sorry wlamywacz ale nie kapuje :/
widok w osobnej klasie?
wlamywacz
Jasne że tak!
M - model - pobiera dane
C - controler - router itd.
V - view - pokazuje dane
terabit
ok,
tylko nie wiem jak to wszystko laczyc...

mam model - czyli zarzadzanie wszystkimi danymi w bazie winksmiley.jpg serce aplikacji

pozniej widok - pobiera/wysyla wszystko co mu potrzebne od/do kontrolera...

kontoroler - zarzadza danymi miedzy modelem a widokiem...


teraz tak mam widok,
chce np. usunac wpis z bazy
czyli mam jakas funkcje z kontrolera...
przekazuje mu te dane...
on je obrabia, sprawdza czy wszystko z nimi ok, jesli tak to przekazuje do modelu ktory juz sie nimi odpowiednio zajmuje? smile.gif


hmm czy dobrze to rozumiem ?

tylko jak te dane przykazywać miedzy kontrolerem a modelem? :/
wlamywacz
Nie będę Ci pisał bo na forum naprawdę wiele przykładów jest.
Sedziwoj
Cytat(wlamywacz @ 9.07.2008, 19:40:09 ) *
Nie stosuj die a return
Filtruj zmienne


A ja powiem nie stosuje return ani die() w tym przypadku tylko Exception, bo przecież nie udane połączenie właśnie jest wyjątkiem, w ten sposób masz zatrzymanie skryptu jeśli ktoś nie obsłuży, ale jak ktoś obsłuży to ma dane co się stało.
Dlaczego nie die(), bo przerywa działanie skryptu i nic nie można z tym zrobić, a jednak często chcemy np. wyświetlić odpowiedni komunikat, czy coś innego zrobić.
Dlaczego nie return, bo PHP pozwala zignorować to, więc ktoś może nawet nie wiedzieć, że wystąpił błąd a to się okaże dopiero dalej.

Dalej, kontrolerów nie dziedziczysz po klasie połączenia, bo to by przypominało jakbyś ty był potomkiem ubrania, trochę głupie co nie? Przekazujesz do kontrolera instancje obiektu bazy.


Moim zdaniem zamiast brać się za pisanie własnego MVC, mógł byś chociażby nauczyć się Symfony, przejść manual krok po kroku, nawet nie zaglądając jak to działa, byś zrozumiał jak to powinno działać.
Co do pisania w tak ostatnio popularnym skrócie OOP, to masz jeszcze braki w podstawach, więc powinieneś je poprawić, tzn. kiedy się powinno dziedziczyć a kiedy agregować obiekty, dzielenia na odpowiednią funkcjonalność (wywołanie w kontrolerze mysql_query() jest bez sensu, bo po co Ci wtedy klasa bazy danych?, do tego nie wiesz do którego połączenia się odwołujesz)
wlamywacz
Cytat(Sedziwoj @ 10.07.2008, 09:51:30 ) *
Dlaczego nie return, bo PHP pozwala zignorować to, więc ktoś może nawet nie wiedzieć, że wystąpił błąd a to się okaże dopiero dalej.

Mógłbyś to rozwinąć ? Oczywiście sam stosuje:
  1. <?
  2. function __autoload($class) {
  3. require_once './class/' . $class . '.class.php';
  4. }
  5.  
  6. try {
  7.  
  8. $ini_array = parse_ini_file("config.ini", true);
  9.  
  10. $db = new db;
  11. $db->setParam('user', $ini_array['mysql']['user']);
  12. $db->setParam('pass', $ini_array['mysql']['pass']);
  13. $db->setParam('name', $ini_array['mysql']['name']);
  14. $db->setParam('host', $ini_array['mysql']['host']);
  15. $db->connect();
  16.  
  17. $action = new action;
  18. $action->setParam('defClass', $ini_array['action']['defClass']);
  19. $action->setParam('startClass', $ini_array['action']['startClass']);
  20. $action->setParam('explode', $ini_array['action']['explode']);
  21. $action->setParam('exceptions', $ini_array['action']['exceptions']);
  22. $action->action();
  23.  
  24. } catch (Exception $e) {
  25. echo 'Wystąpił błąd systemu xxxxx.pl: <b>', $e->getMessage(), "</b>\n";
  26. }
  27. ?>
Sedziwoj
Cytat(wlamywacz @ 10.07.2008, 12:16:53 ) *
Mógłbyś to rozwinąć ?


Już pominę fakt return w __construct(), ogólnie masz kod:
  1. <?php
  2. class Something {
  3.  
  4. /**
  5.  * If returns -1 means error, other case returns null
  6.  *
  7.  * @return integer
  8.  */
  9. public function doIt(){
  10. return -1; 
  11. }
  12.  
  13. }
  14. $s = new Something();
  15. $s->doIt();
  16. //And go ahead
  17. ?>

Czyli ktoś nie sprawdza czy wystąpił błąd, i nie wie że wystąpił. Takie przypadki można często spotkać jak ludzie korzystają z wbudowanych funkcji, gdzie często informacja o błędzie jest właśnie w tym co zwraca. Najczęściej nie ma problemów, więc nawet nie wiedzą, że powinni to sprawdzać, a jak wystąpią to nie wiadomo co się dzieje. "Przecież wszystko działa"

EDIT poprawa konwencji, nie wiem czemu napisałem nazwę klasy z małej litery.
wlamywacz
Zawszę sprawdzam co zwraca funkcja więc nie widziałem tego problemu smile.gif
Sedziwoj
Cytat(wlamywacz @ 10.07.2008, 13:09:08 ) *
Zawszę sprawdzam co zwraca funkcja więc nie widziałem tego problemu smile.gif


Wiesz, można być optymistą i się na tym przejechać. Po co masz ryzykować, że zapomnisz, tak masz pewność, że tego nie zrobisz, a jak coś będzie nie tak, to się dowiesz co.
Gdyby wszystko było tak pięknie jak piszesz, nie tworzyło by się testów jednostkowych, a się robi, bo człowiek nie jest omylny.
Powinno się robić to tak dobrze, jak się potrafi, a w przyszłości zwróci się to. (pamiętaj że Ty pracujesz sam, ale jak jest zespół, to wygląda inaczej, trzeba dbać, aby zawsze było dobrze)
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.