Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Podstawy obiektowości
Forum PHP.pl > Forum > Przedszkole
kamil_lk
Witam.
W ramach nauki obiektówki postanowiłem wykonać jakiś mały projekt, aby załapać podstawy. Po krótkim namyśle stwierdziłem, że napiszę sobie bloga.
I teraz mam do was, bardziej doświadczonych, pytanie. Czy idę w dobrą stronę podczas skrobania tego projektu? Co robię źle, a co dobrze (o ile coś tongue.gif). Może polecacie jakieś przystępne tutoriale (zadania), które odnoszą się do rzeczy praktycznych, zamiast do kwadratów, czy trójkątów?

Poniżej przedstawiam to co napisałem do tej pory. Co prawda nie ma tego wiele. Głównie chodzi mi tutaj o klasę content.php oraz wpisy.php.

index.php
  1. <?php
  2.  
  3. include_once('class/class.db.php');
  4. include_once('header.php');
  5. include_once('content.php');
  6. include_once('footer.php');
  7.  
  8. $db = new db("mysql:host=localhost;dbname=blog;", "root", "");
  9. $db->query('SET NAMES utf8');
  10.  
  11. $head = new Header('Kamil');
  12. echo $head->getHeader();
  13.  
  14. $content = new Content($db);
  15. $content->getSection();
  16.  
  17. $footer = new Footer;
  18. echo $footer->getFooter();
  19.  
  20. ?>


header.php
  1. <?php
  2.  
  3. class Header{
  4.  
  5. public function __construct($tytul){
  6. $this->tytul = $tytul;
  7. }
  8.  
  9. public function getHeader(){
  10. return '
  11. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  12. <html xmlns="http://www.w3.org/1999/xhtml">
  13. <head>
  14. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  15. <link rel="stylesheet" type="text/css" href="css/style.css" />
  16. <link rel="stylesheet" type="text/css" href="css/popup.css" />
  17. <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  18. <script src="js/jquery-impromptu.js"></script>
  19. <title>'.$this->tytul.'</title>
  20.  
  21. <script type="text/javascript">
  22. function popup(zmienna){
  23. $.prompt(zmienna,{ overlayspeed: 2, buttons: {}});
  24. }
  25. </script>
  26.  
  27. </head>
  28. <body>
  29. ';
  30. }
  31.  
  32. }
  33.  
  34. ?>


footer.php
  1. <?php
  2.  
  3. class Footer{
  4.  
  5. public function getFooter(){
  6.  
  7. return '
  8. <div id="footer">
  9. <span class="footer">Created by Kamil</span>
  10. </div>
  11. </body>
  12. </html>';
  13.  
  14. }
  15.  
  16. }
  17.  
  18. ?>


content.php
  1. <?php
  2.  
  3. include_once('class/wpisy.php');
  4.  
  5. class Content{
  6.  
  7. public $cont;
  8. private $db;
  9.  
  10. public function __construct($db){
  11. $this->db = $db;
  12. }
  13.  
  14. public function getSection(){
  15. echo '<div id="content">';
  16. if( isset($_GET['section']) ) {
  17. switch($_GET['section']) {
  18.  
  19. case 'show' : $this->cont = new Wpisy($this->db); $this->cont->show(); break;
  20.  
  21. default: $this->cont = new Wpisy($this->db); $this->cont->error404();
  22. }
  23.  
  24. if( isset($_GET['action']) )
  25. switch($_GET['action']) {
  26.  
  27. case 'add' : $this->cont = new Wpisy($this->db); $this->cont->addComent($_POST); break;
  28.  
  29. }
  30.  
  31. } else {
  32.  
  33. $this->cont = new Wpisy($this->db); $this->cont->show();
  34.  
  35. }
  36. echo '</div>';
  37.  
  38. }
  39.  
  40. }
  41. ?>


wpisy.php
  1. <?php
  2.  
  3. class Wpisy{
  4.  
  5. private $db;
  6.  
  7. public function __construct($db){
  8. $this->db = $db;
  9. }
  10.  
  11. public function show(){
  12. if(!isset($_GET['param'])){
  13. $result = $this->db->select('wpisy', '1=1 ORDER BY data_dodania desc', '', 'id, temat, tresc, DATE_FORMAT(data_dodania, \'%d.%m.%Y\') AS data_dodania');
  14. foreach($result as $record){
  15. echo '
  16. <div class="wpis">
  17.  
  18. <h6>'.$record['temat'].'</h6>
  19. <span class="data">'.$record['data_dodania'].' &raquo; Kamil</span>
  20. <div class="tresc">'.$record['tresc'].'</div>
  21. <div class="wiecej">
  22. <a href="index.php?section=show&param='.$record['id'].'" class="wiecej clear">Czytaj całość</a>
  23. </div>
  24.  
  25. </div>
  26. ';
  27. }
  28. } else {
  29. $result = $this->db->select('wpisy', 'id='.$_GET['param'], '', 'id, temat, tresc, DATE_FORMAT(data_dodania, \'%d.%m.%Y\') AS data_dodania');
  30. foreach($result as $record){
  31. echo '
  32. <div class="wpis">
  33.  
  34. <h6>'.$record['temat'].'</h6>
  35. <span class="data">'.$record['data_dodania'].' &raquo; Kamil</span>
  36. <div class="tresc">'.$record['tresc'].'</div>
  37. <div class="wiecej">
  38. <a href="index.php?section=show" class="wiecej clear">Wróć</a>
  39. </div>
  40.  
  41. </div>
  42. ';
  43. }
  44.  
  45. $result = $this->db->select('komentarze k, wpisy w', 'id_wpisu='.$_GET['param'].' and w.id=k.id_wpisu', '', 'k.id kid, nick, k.tresc ktresc, k.temat ktemat, DATE_FORMAT(k.data_dodania, \'%d.%m.%Y %h:%i:%s\') AS kdata_dodania');
  46. foreach($result as $record2){
  47. echo $record2['kid'].' - '.$record2['nick'].' - '.$record2['ktemat'].' - '.$record2['ktresc'].' - '.$record2['kdata_dodania'].'<br /><br />';
  48. }
  49.  
  50. echo '
  51. <form action="index.php?section=show&action=add&param='.$_GET['param'].'" method="post">
  52. <fieldset class="komentarze">
  53. <label for="nick">Nick<br /><input type="text" name="nick" id="nick" value="" /></label>
  54. <label for="temat">Temat <span class="wymagane">*</span><br /><input type="text" name="temat" id="temat" value="Re: '.$record['temat'].'" /></label>
  55. <label for="tresc">Treść <span class="wymagane">*</span><br /><textarea name="tresc" id="tresc"></textarea></label>
  56. <label for="dodaj"><input type="submit" name="dodaj" id="dodaj" value="Dodaj komentarz" /></label>
  57. </fieldset>
  58. </form>
  59. ';
  60. }
  61. }
  62.  
  63. public function addComent($array){
  64.  
  65. if(isset($array['dodaj'])){
  66. if( isset($array['temat']) && isset($array['tresc']) && $array['temat'] != '' & $array['tresc'] != ''){
  67. $array['id_wpisu'] = $_GET['param'];
  68. $array['data_dodania'] = date('Y-m-d h:i:s');
  69. if(empty($array['nick']) || $array['nick'] == "") $array['nick'] = 'anonim';
  70. $result = $this->db->insert('komentarze', $array);
  71.  
  72. if($result){
  73. echo '<script type="text/javascript">popup("Dodano!")</script>';
  74. } else {
  75. echo '<script type="text/javascript">popup("Nie dodano!")</script>';
  76. }
  77. } else echo '<script type="text/javascript">popup("Brak danych!")</script>';
  78.  
  79. }
  80. }
  81.  
  82. public function error404(){
  83. header('Location: 404.html');
  84. }
  85. }
  86.  
  87. ?>


Sephirus
Hmm ja ogólnie napiszę tylko, że nie podoba mi się mieszanie logiki z prezentacją. Spróbuj rozdzielić warstwę logiki (kodu php) od prezentacji (html). Możesz utworzyć dodatkowe pliki, w których będą same treści HTML i includować je w odpowiednich metodach klas. W ten sposób kod będzie bardziej przejrzysty.

Co do samej obiektowości to Twój kod wygląda tak jakby był wrzucany w obiekty na siłę - nie o to tu chodzi. Chodzi o to by obiekty do czegoś konkretnego służyły. Stwórz obiekt dostępu do bazy danych, na którym będziesz pracował, proponuje od razu przejść tu na PDO. Spróbuj też zastosować "małe MVC" to znaczy:

- Twórz klasy, których zadaniem jest przetwarzanie danych - pobieranie z bazy danych, wrzucanie do bazy, manipulacja danymi w bazie, obróbka tych danych - to są modele,
- Twórz klasy, które będą używały wyżej wspomnianych modeli przekazywały im dane oraz odbierały te dane i wyświetlały je ładując odpowiedni skrypt widoku (czyli plik pozbawiony logiki PHP, w którym jest sam HTML wraz z wyświetlaniem danych z modelu, pętlami itd.) - to są widoki,
- Na końcu stwórz klasę/klasy, które będą obsługiwały dane żądanie. To oznacza że w adresie odwołujesz się do jakiegoś skryptu PHP a on już powinien wiedzieć jaki widok załadować czy jaką metodę modelu wykonać - to kontrolery

Poczytaj odrobinkę o podstawach MVC - to dobry wzorzec wcale nie trudny a struktura aplikacji dzięki niemu jest przejrzysta

Dla sytuacji gdy coś wyświetlasz (np. z bazy danych):

Żądanie -> index.php -> (wybór odpowiedniego kontrolera aby obsłużyć żądanie) -> kontroler -> (sprawdzenie, przygotowanie parametrów, załadowanie modelu, widoku) -> odpalenie metody widoku -> widok pobiera dane z modelu i wyświetla odpowiedni skrypt z HTML uzupełniając go o te dane.

Dla sytuacji zapisu do bazy z formularza:

Żądanie -> index.php -> (wybór odpowiedniego kontrolera aby obsłużyć żądanie) -> kontroler -> (sprawdzenie, przygotowanie parametrów, załadowanie modelu) -> odpalenie metody modelu zapisujące dane
Szymciosek
Dołączę się do pytania czy konkretnie View musi pobierać dane z modelu czy mogę to zrobić już w kontrolerze i później przekazać do View?

Załóżmy, że View ma metodę, która uruchomi plik z szablonem i w pewne miejsca wstawi mi kod, więc uruchamiając view z kontrolera robię $view = new View($template, $vars), gdzie $vars to array zawierający pewne dane w formie: $vars = array ('title' => 'Tytuł', 'content' => 'Zawartość');

Wtedy w kontrolerze na podstawie danych z modelu tworzę ten array.

Tak też jest dobrze? W sumie sposobów implementacji MVC jest cała masa...
!*!
@up Obie formy są poprawne. Jednak większość preferuje kontroler który pobiera dane z modelu i przekazuje je do widoku.

Do tego co napisał Sephirus dodałbym, abyś zainteresował się autoloaderami SPL, bo pisanie za każdym razem w plikach include, jest bez sensu.
Sephirus
@up to ja dorzucę jeszcze trochę z off-topic ale do zapoznania się z OB (ob_start itd) - przydaje się przy widokach i lepszej kontroli nad wyświetlanymi treściami

Co do sposób z tym modelem i widokiem... MVC ogólnie w najbardziej STRICT wersji wymusza aby kontroler nie ruszał modelu w zasadzie w ogóle jeśli uzywa widoku.

Czyli:

Jeśli mamy akcję, która coś wyświetla to kontroler powinien przygotować parametry requestu, wywołac odpowiedni widok i ewentulanie wg niego powinien robić jakieś przekierowania itd.. sam widok powinien już wiedzieć jakie modele załadować i uzywać.

W przypadku gdy mamy jakiś zapis do bazy itp kontroler przekazuje dane do modelu ktory je zapisuje, bez pośrednictwa widoku.

Niedopuszczalne wg STRICT MVC jest skolei przeniesienie funkcjonalności widoku na kontroler - sam jednak bardzo często robię od tego małe odstępstwa - to nie zbrodnia - chodzi jedynie o to by nad tym panować smile.gif
kamil_lk
Jak na razie staram się przejść na PDO i odnośnie tego mam pytania.

Mam taką oto klasę korzystającą z PDO. Klik

Mniej więcej wiem jak z niej korzystać. Zastanawiam się jednak nad jedną rzeczą przy wykonywaniu zapytań.

  1. public function delete($table, $where, $bind="") {...


Co kryje się pod zmienną $bind?

Czy korzystając z tej klasy mogę być pewniejszy, jeżeli chodzi o kwestie bezpieczeństwa danych?
krzysiekk
hi
jesli chodzi o pdo i bindowanie polecam: http://pl.wikibooks.org/wiki/PHP/Biblioteka_PDO (nie złośliwie ) na przykladach najlepiej zobaczyć o co chodzi.

jesli chodzi o programowanie OO to też mialem klopoty by to wszystko zalapac kupilem wiec ksiażkę , ktorą polecam zawsze coś tzrba miec wiedzy niemniej jest jatwiej z dobrymi przykladami i wzorcami ZF http://zend-framework.gajdaw.pl/html/menu/moje-ksiazki.html

pozdr.K
kamil_lk
Z mojej analizy wynika, że bindowanie służy tak jakby do "filtracji" danych. Jeżeli się nie mylę to kolejne pytanie, a właściwie to samo.

Jak zastosować to w moim przykładzie z wykorzystaniem np. metody select(), która posiada 4 parametry, tj. $table, $where="", $bind="", $fields="*".

Normalnie zapytanie wykonuję w ten sposób:

  1. $pdo->select('wpisy', 'id=1', '', 'temat, tresc');


Jak wykorzystywany jest 3 parametr, kiedy się go używa i w ogóle co się do niego wprowadza?

A co do książek, to którą polecasz, aby załapać podstawy obiektówki. Co powiesz o PHP, MySQL i MVC Gajdy?
krzysiekk
  1.  
  2.  
  3.  
  4. if(isset($_GET['id']))
  5. {
  6. $stmt = $pdo -> prepare('SELECT `nazwa`, `opis`, `ilosc`, `cena`, `jakosc` FROM `produkty` WHERE `id` = :id');
  7. $stmt -> bindValue(':id', $_GET['id'], PDO::PARAM_INT);
  8. $stmt -> execute();
  9.  
  10. if($details = $stmt -> fetch())
  11. {
  12. echo '<hr/>
  13. <p><b>Nazwa:</b> '.$details['nazwa'].'</p>
  14. <p><b>Opis:</b> '.$details['opis'].'</p>
  15. <p><b>Ilosc:</b> '.$details['ilosc'].'</p>
  16. <p><b>Cena:</b> '.$details['cena'].'</p>
  17. <p><b>Jakosc:</b> '.$details['jakosc'].'</p>';
  18. }
  19. else
  20. {
  21. echo '<hr/><p>Przepraszamy, podany rekord nie istnieje!</p>';
  22. }
  23. $stmt -> closeCursor();



Opis:
Oczywiście wyświetlanie szczegółów przeprowadzamy tylko, jeśli podaliśmy ID.
Przygotowujemy szkielet zapytania SELECT.
Wykonujemy zapytanie metodą execute(). Zauważmy, że obiektem $stmt dysponujemy już od momentu wywołania metody prepare(), dlatego execute() nam już nic tu nie zwraca.
Dalej postępujemy już tradycyjnie, po prostu pobierając kolejne rekordy (w tym wypadku tylko jeden) i zamykając kursor.


mam nadzeije ze oe to Cu chodzi ? to przyklad wyciety z tego 1 linku

jasli chodzi o ksiazke ktora podales to nei czytalem moze buć Ok jak wszystkie jego ksiażki ale moge sie mylić.
zegarek84
uzupełniając to co napisał @Sephirus i MVC/MVP dodam, iż chyba lepiej byś zrobił korzystając z gotowego frameworka (obojętne i nie wymieniam z nazwy coby o nich dyskusja się nie polała tu ;]), na początek możesz robić wg. schematów i instrukcji, nie musisz wiedzieć co pod maską siedzi... no chyba, że chcesz wiedzieć wszystko co i jak to możesz trochu podłubać (jak np. mnie dawniej interesowały sockety w PHP ;])...

raz na uczelni do jednego z projektów miałem zakaz stosowania FW, a że akurat jedna miniaplikacja fajnie spasowała pod temat a była w ZF to i tak w sumie nie był problem ^^... byś miał jakiś przykład z buforowaniem z ob_... wrzucę tutaj 2 króciutkie klasy i opiszę co i jak...

pierwsza jest ogólna i wykonuje całą "magię" z ob_... oraz przy jej pomocy ustawia się zmienne do widoku oraz z jej instancji pobiera się zmienne w widoku (jakby nie zdefiniowało się zmiennej wyświetla null'a co jest dla mnie też ułatwieniem) druga ją rozszerza w aplikacji i ustawia domyślne ścieżki do plików widoku które są plikami .phtml zawierającymi kod php
  1. <?php
  2. namespace Z;
  3. class View /*extends \Z\Notice*/ { // zakomentowany fragm. nie potrzebny, część była pisana zdarzeniowo
  4. public $sPathFile='';
  5. public $aVars = array();
  6.  
  7. public function __construct() {
  8. }
  9. public function setFile($sPathFile) {
  10. $this->sPathFile = $sPathFile;
  11. }
  12. public function setVar($key, $var){
  13. $this->aVars[$key] = $var;
  14. }
  15. public function getVar($key){
  16. if(array_key_exists($key, $this->aVars))
  17. return $this->aVars[$key];
  18. return NULL;
  19. }
  20.  
  21. public function renderScript(){
  22. include $this->sPathFile;
  23. return $s;
  24. }
  25.  
  26. public function __set($name, $value) {
  27. $this->setVar($name, $value);
  28. }
  29.  
  30. public function __get($name) {
  31. return $this->getVar($name);
  32. }
  33. }

  1. <?php
  2. class View extends \Z\View {
  3.  
  4. public function set($controller = 'index', $action = 'index') {
  5. $this->setFile(
  6. implode(DIRECTORY_SEPARATOR, array(APPLICATION_PATH
  7. , 'views', 'scripts', strtolower($controller), strtolower($action))
  8. ) . '.phtml'
  9. );
  10. }
  11. }

w klasie widoku czy to w kontrolerze czy wcześniej i podajesz instancje do kontrolera ustawiasz pliki widoków... w tej funkcji założone jest, że jest zdefiniowana zmienna APPLICATION_PATH, powyższe klasy masz jako przykład i możesz z nimi zrobić co chcesz... w BOOTSTRAPIE mógłbyś też całość objąć przez ob_ w celu przechwytywania wywołań echo itd. w kontrolerach czy innych miejscach, potem można zdefiniować, czy takie rzeczy chcesz wyświetlać przed widokiem, za czy jeśli renderujesz widok na końcu to np. błędy i inne rzeczy możesz wyświetlić w ten sposób w odpowiedniej sekcji widoku... odpowiednio planując kontrolery możesz też zrobić widok wielopoziomowy...

kurcze alem się rozpisał chyba nie potrzebnie - I TAK POLECAM SKORZYSTANIE Z JAKIEGOKOLWIEK FW ]:->
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.