Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Kilka pytań o praktyczne zastosowanie programowania obiektowego
Zagiewa
post
Post #1





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


Witam. Dopiero wchodzę w programowanie obiektowe i choć oczytałem się już trochę, wiele poradników dostępnych w internecie opisuje obiektowość w sposób teoretyczny nie pokazując jak można go wykorzystać w praktyce dlatego też mam parę pytań, które nie dają mi spokoju.

1. Tworząc klasy powinno się je trzymać w tym samym pliku co całość kodu czy najlepiej jest utworzyć nowy plik zawierający tylko klasy, a następnie je includować w plikach w których będziemy z tych klas korzystać?
2. Jeśli utworzymy klasę to tworzenie do niej obiektów za pomocą np. formularzy jest proste (przynajmniej teoretycznie) natomiast jak zapisywać obiekty do bazy danych? zapisujemy samą nazwę obiektu czy należy zapisać nazwę wraz ze wszystkimi właściwościami tego obiektu? Np. mamy klasę o nazwie prostokąt. Właściwościami będzie bok_a i bok_b. Tworzymy nowy obiekt o nazwie pierwszy_prostokat i nadajemy mu właściwości bok_a=5 i bok_b=10 jak powinien wyglądać rekord gdy zapiszemy ten obiekt do bazy? bo mi przychodzą do głowy taki zapis:

id. || nazwa || bok_a || bok_b
1 || pierwszy_prostokat || 5 || 10

3. Czy nawet w przypadku prostych skryptów warto używać obiektowości? Dajmy na to tworząc księgę gości to ilość kodu niezależnie czy użyjemy kodu strukturalnego czy obiektowego jest niemal taka sama. Jeśli chodzi o czytelność jest też podobnie bo skrypt ogólnie jest prosty. Sposób zapisywania do bazy jest identyczny zmienia się co najwyżej struktura tabeli. Więc nasuwa się pytanie - jak pisać?
Go to the top of the page
+Quote Post
4 Stron V   1 2 3 > »   
Start new topic
Odpowiedzi (1 - 71)
tmka
post
Post #2





Grupa: Zarejestrowani
Postów: 27
Pomógł: 9
Dołączył: 9.02.2009

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


Na początek dobra rada jeżeli chodzi o sam proces nauki obiektówki i, w sumie, nauki czegokolwiek (IMG:style_emoticons/default/smile.gif) - zobaczyć jak to robią inni. Poszukaj jakiś prostych CMS-ów, sklepów itp. napisanych obiektowo i zobacz jak robią to inni.

Jeżeli chodzi o pytania:
1. Najczęstszym modelem jest trzymanie każdej, nawet małej, klasy w oddzielnym pliku.
2. Użyte przez Ciebie pojęcie 'zapisu obiektu do bazy' jest troche mylące, bo zapisujesz tylko jego, i to niektóre, właściwości (w tym przypadku boki). Najlepiej zobrazuje to przykład:

  1. class Prostokat{
  2. private bokA;
  3. private bokB;
  4. private nazwa;
  5.  
  6. public function __construct(a,b,nazwa){
  7. $this->setBokA(a);
  8. $this->setBokB(b);
  9. $this->setNazwa(nazwa);
  10. }
  11.  
  12. public function setBokA(a){
  13. $this->bokA = a;
  14. }
  15.  
  16.  
  17. public function setBokB(b){
  18. $this->bokB = b;
  19. }
  20.  
  21.  
  22. public function setNazwa(nazwa){
  23. $this->nazwa = nazwa;
  24. }
  25.  
  26. public function getBokA(){
  27. return $this->bokA;
  28. }
  29.  
  30.  
  31. public function getBokB(b){
  32. return $this->bokB;;
  33. }
  34.  
  35.  
  36. public function getNazwa(){
  37. return $this->nazwa;
  38. }
  39.  
  40. //save zapisuje nam wlasciwosci do bazy
  41. public save(){
  42. //zalozmy, ze masz juz polaczenie, wiec tworzysz zapytanie ktore moze wygladac tak:
  43. $query = "INSERT INTO prostokaty ( nazwa, bok_a, bok_b ) VALUES ($this->nazwa, $this->bokA, $this->bokB)";
  44. mysql_query($query);
  45. }
  46. //load wczyta nam wlasciwosci z bazy, wystarczy podac id wpisu
  47. public load($id){
  48. //
  49. $query = "SELECT nazwa, bok_a, bok_b FROM prostokaty WHERE id=$id";
  50. $result = mysql_query($query);
  51. //itd.
  52. }
  53.  
  54. }


3. Na łatwych skryptach można łatwo przećwiczyć sobie pewne mechanizmy obiektowości jak np. dziedziczenie czy polimorfizm. Osobiście staram sie wszystko pisac obiektowo, ze wzgledu na to, że pozniej
łatwiej jest taki obiekt wykorzystać w innych projektach.

Ten post edytował tmka 24.06.2010, 14:49:31
Go to the top of the page
+Quote Post
Zagiewa
post
Post #3





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


Szukałem skryptów napisanych obiektowo ale na ogół natrafiałem na skomplikowane ogromne skrypty, których samo przeanalizowanie było gorsze niż nauka obiektowości (IMG:style_emoticons/default/tongue.gif) Najbardziej w przykładzie, który napisałeś zainteresował mnie sposób zapisu i odczytu z bazy bo zrobiłeś z tego metody o czym ja raczej bym nie pomyślał. Sposób ten jest o tyle dobry, że bardzo prosto się odczytuje obiekt z bazy. Co do praktyki używania obiektowości nawet w prostych skryptach to masz racje, jest to dobry sposób na potrenowanie tak czy inaczej dzięki wielkie, nie oczekiwałem tak konkretnej odpowiedzi (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
red9skull
post
Post #4





Grupa: Zarejestrowani
Postów: 157
Pomógł: 0
Dołączył: 11.07.2009
Skąd: root

Ostrzeżenie: (10%)
X----


To ja się podepnę: Do czego można wykorzystać konstruktor? Jak i kiedy z niego korzystać?
Go to the top of the page
+Quote Post
croc
post
Post #5





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

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


Programowanie obiektowe pojawiło się, ponieważ jest bardziej naturalnym przełożeniem rzeczywistości na kod. Dla mnie używanie kodu obiektowego jest pewnego rodzaju dojrzałością programistyczną, chociaż używanie go wszędzie też nie jest rozsądne. Trzeba samemu wiedzieć co i kiedy jest właściwe.

Ja osobiście lubię tworzyć dużo metod tak, by używanie kodu było potem jak najbardziej intuicyjne i wygodne. Przykładowo:

  1. $article = new Article(12); // w konstruktorach robię pobieranie ID i wczytywanie danych z bazy do pól obiektu
  2. echo $article->getAuthor()->getFullName();
  3. if($article->getAuthor()->isAdmin()) {
  4. echo 'Autor jest administratorem!';
  5. }
  6. while($news = $article->getAuthor()->getNews()) {
  7. echo $news->getTitle();
  8. echo '<br>';
  9. echo $news->getDate()->getYear();
  10. }


Napisałem ten kod teraz, naprawdę nigdy tego konkretnego fragmentu nie użyłem. Chodzi o to jak pisać kod, żeby było można wykonywać równie wygodne operacje. Wszystko może być obiektem (u mnie np. daty to obiekty, bo potem bardzo fajnie się na nich operuje).

Nie wyobrażam sobie pisania dużych systemów strukturalnie. OK, samo pisanie sobie wyobrażam, ale potem rozwijanie kodu to masakra.
Go to the top of the page
+Quote Post
Zagiewa
post
Post #6





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


Croc co prawda nie napisałem jeszcze żadnego praktycznego kodu z użyciem obiektowości bo tak jak pisałem dopiero staram się go dobrze zrozumieć ale zgodzę się, że rozbudowywanie kodu strukturalnego to koszmar tym bardziej, że kod strukturalny miejscami jest bardziej zawiły niż obiektowy, a przynajmniej tak mi się wydaje.
Go to the top of the page
+Quote Post
haahh
post
Post #7





Grupa: Zarejestrowani
Postów: 23
Pomógł: 9
Dołączył: 6.06.2010

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


Strukturalny faktycznie strasznie się edytuję. Sam zmieniałem ostatnio strukturę wyświetlania mojego "małego portalu" php i to była masakra. Muszę przejść na obiektowy styl pisania kodu - ktoś poleci jakieś książki traktujące o średnio-zaawansowanym php i pisanie obiektowym?
Go to the top of the page
+Quote Post
croc
post
Post #8





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

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


Lepsze są tutoriale. Zacznij od tutoriala o samej idei OOP nawet jeśli wydaje ci się, że ją znasz.

Co do zawiłości: nie uważam, by kod obiektowy był zawiły. Jest go dużo, ale dobrze napisany jest niesamowicie schludny i poukładany. Pamiętam dzień, kiedy przekonałem się do OOP w PHP - od tego czasu każdy projekt to dla mnie 90% mniej nerwów i irytacji. Pisząc kod, płyniesz. (IMG:style_emoticons/default/smile.gif) Masz ten komfort, że kod w klasach można [przeważnie] poprawić bez ingerencji w schematy użycia tych klas. A to genialne, bo cały bajzel pojawia się zwykle w strukturach. Dla mnie najlepszą nauką OOP była nauka Javy, chociaż kompilowane aplikacje OOP pisze się nieco inaczej niż interpretowane.
Go to the top of the page
+Quote Post
haahh
post
Post #9





Grupa: Zarejestrowani
Postów: 23
Pomógł: 9
Dołączył: 6.06.2010

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


Tutki? Pewnie najlepszy ten z manuala (IMG:style_emoticons/default/snitch.gif) , coś polecasz? Ale i tak jakaś książka mi się przyda, bo chciałbym ruszyć do przodu z php. Zobaczę, może uda mi się mój portal przerobić na wersję obiektową i ciekawe, czy naprawdę będzie to lepiej się prezentować niż obecna wersja. Na razie za każdym razem jak spojrzę na te strzałki "->" to padam.
Go to the top of the page
+Quote Post
croc
post
Post #10





Grupa: Zarejestrowani
Postów: 706
Pomógł: 108
Dołączył: 12.03.2010

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


Kiedyś kochałem czytać książki programistyczne, ale mam o nich coraz gorsze zdanie. Szalę goryczy przelała książka autorstwa samego ojca PHP pt. "PHP5. Programowanie". Byłem w szoku, że sam autor PHP utrwala złe nawyki (np. używanie funkcji empty dla stringów, co uważam za zły nawyk), niekonsekwencję w kodzie i bezsensowne podrozdziały kosztem takich, których brakuje w książce.

A zachwycając się dalej programowaniem obiektowym, to te strzałeczki również polubisz (IMG:style_emoticons/default/smile.gif) (chociaż Bóg jeden wie dlaczego w PHP nie są to kropki) Kod daje frajdę, bo myślisz o wielu rzeczach jak o żywych obiektach, dzięki czemu zachowujesz konsekwencję. Oczywiście, strukturalnie mógłbyś robić do wszystkiego funkcje, ale to nie to samo.

Ten post edytował croc 25.06.2010, 09:34:15
Go to the top of the page
+Quote Post
thek
post
Post #11





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Czemu strzałeczki, a nie kropki? Może są to wskaźniki na pola, a nie same pola bezpośrednio. Albo zrobiono tak by nie przeciążać już używanego operatora konkatenacji.
$obiekt.pole
$obiekt.$pole
Różnica niewielka, ale trzeba by rozpoznawać po stronie interpretera z czym mamy do czynienia. Łatwiej wprowadzić -> , który jest bardziej jednoznaczny i wiąże się w pewien sposób z obiektami jako odniesienie przez wskaźnik typowe dla choćby takich języków jak C++.

EDIT: Patrząc na zapisy oba popatrz też jak łatwo się pomylić (IMG:style_emoticons/default/winksmiley.jpg) Po prostu brak dolara w jednym miejscu.
Go to the top of the page
+Quote Post
red9skull
post
Post #12





Grupa: Zarejestrowani
Postów: 157
Pomógł: 0
Dołączył: 11.07.2009
Skąd: root

Ostrzeżenie: (10%)
X----


Cytat(thek @ 25.06.2010, 11:13:38 ) *
Czemu strzałeczki, a nie kropki?


Tak samo jak: czemu kropki a nie znak plusa?
  1. $string = "wyszukiwarka " . "google";


(IMG:style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
Zagiewa
post
Post #13





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


Mam zamiar dzisiaj napisać pierwszy skrypt za pomocą obiektowości. Żeby było łatwo ale praktycznie padło na księgę gości. Zanim jednak zacznę chciał bym zapytać was czy dobrze ją sobie zaplanowałem, a więc.

1. klasa nazywała by się ksiega
2. właściwości: data, imie, email, strona, numer gg, komentarz
3. metody: zapis(do bazy), wczytaj(z bazy), set(ustawienie wartości dla właściwości)

I tutaj mam jeszcze dwa pytanka. tmka Ty jako pierwszą metodę utworzyłem z konstruktorem dlaczego? i czy ona jest wymagana? W Twoim kodzie ustawianie wartości dla właściwości jest w nowej metodzie np:
Kod
public function setBokA(a){

$this->bokA = a;

}

Moje pytanie to czy nie lepiej było by w jednej metodzie zawrzeć wszystkie właściwości czyli coś takiego:
Kod
public function setBokA(a){

$this->data = a;
$this->imie = b;
$this->email = c;
$this->strona = d;
$this->gg = e;
$this->komentarz = f;

}

Czy jest coś jeszcze o czym powinienem pamiętać przy pisaniu tego skryptu?
Go to the top of the page
+Quote Post
Mikz
post
Post #14





Grupa: Zarejestrowani
Postów: 48
Pomógł: 3
Dołączył: 7.12.2007

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


Cytat(thek @ 25.06.2010, 11:13:38 ) *
Czemu strzałeczki, a nie kropki? Może są to wskaźniki na pola, a nie same pola bezpośrednio. Albo zrobiono tak by nie przeciążać już używanego operatora konkatenacji.
$obiekt.pole
$obiekt.$pole
Różnica niewielka, ale trzeba by rozpoznawać po stronie interpretera z czym mamy do czynienia. Łatwiej wprowadzić -> , który jest bardziej jednoznaczny i wiąże się w pewien sposób z obiektami jako odniesienie przez wskaźnik typowe dla choćby takich języków jak C++.

EDIT: Patrząc na zapisy oba popatrz też jak łatwo się pomylić (IMG:style_emoticons/default/winksmiley.jpg) Po prostu brak dolara w jednym miejscu.


No nie jest to takie proste jeśli dorzucimy do tego fakt, że można zastosować coś takiego jak metoda __toString() w obiekcie lub nazwę funkcji jako wartość zmiennej (IMG:style_emoticons/default/winksmiley.jpg) .

Red9skull, konstruktor można wykorzystać na wiele sposobów, na przykład:

  1.  
  2. class article
  3. {
  4. private $title, $content, $id;
  5.  
  6. public function __construct($id = null)
  7. {
  8. $this->id = $id;
  9.  
  10. if (!is_null($id))
  11. {
  12. $query = "SELECT * FROM articles WHERE 'id' = $id LIMIT 1";
  13.  
  14. $result = mysql_query($query);
  15. //pominę fetch etc...
  16.  
  17. $this->title = $result['title'];
  18. $this->content = $result['content'];
  19. }
  20. }
  21.  
  22. public function setTitle($title)
  23. {
  24. //parę postów wyżej było
  25. }
  26.  
  27. public function setContent($content)
  28. {
  29. //parę postów wyżej było
  30. }
  31.  
  32. public function save()
  33. {
  34. if (!is_null($this->id))
  35. $query = "UPDATE (et cetera)";
  36. else
  37. $query = "INSERT (et cetera";
  38.  
  39. //parę postów wyżej było
  40. }
  41. }
  42.  


Teraz pytanie z mojej strony, raczej z czystej ciekawości bardziej niż z potrzeby odpowiedzi:
Do czego najczęściej używacie destruktorów?
Go to the top of the page
+Quote Post
thek
post
Post #15





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Odpowiedź równe prosta - zwalniania zasobów przydzielonych konstruktorem. Dla wielu wyda się to dziwne, skoro istnieje Garbage Collector.Tu jest jednak pułapka. Wielokrotnie zachodzą sytuacje gdy pewne obiekty zawierają inne obiekty a te z kolei inne obiekty prowadzące do kolejnych. GC potrafi się w takich sytuacjach "wywalić" i zostawić w pamięci śmieci. Po prostu może czegoś nie zgarnąć do usunięcia. Taki zombie... Nie żyje, a jednak jest (IMG:style_emoticons/default/winksmiley.jpg) O ile w PHP nie jest to łatwo zauważalne, tak w językach kompilowanych potrafi napsuć krwi. Szczególnie ważne jest to w dynamicznym przydziale pamięci. Jeśli pole jest tylko wskaźnikiem (adresem elementu) na obszar pamięci, to jego skasowanie powoduje nie usunięcie całej danej z pamięci, ale tylko utratę wskaźnika, bez dotykania tych danych. Jeśli obiekt jest tymczasowym tylko w pętli, to z każdym jej przebiegiem z pamięci ucieka nam obszar równy jej długości. Kilkadziesiąt tysięcy cykli i nagle program zająć może kilkadziesiąt MB, choć używa tak naprawdę kilkuset kilobajtów. Destruktory właśnie odpowiadać mają za zwalnianie pamięci w odwrotnej kolejności niż przydzielał ją konstruktor by uniknąć wycieków. To jest jego główne zadane, ale nie tylko. Często stosuje się parę konstruktor-destruktor do działania na zmiennych statycznych. Takim banalnym przykładem jest licznik obiektów. Konstruktor inkrementuje zmienną statyczną mającą być licznikiem obiektów. Bo przecież do takiej mają dostęp wszystkie obiekty tej samej klasy. Destruktor tę zmienną dekrementuje. Dzięki temu patrząc na zmienną statyczną, wiemy w każdej chwili ile instancji danej klasy siedzi w pamięci.
Go to the top of the page
+Quote Post
Mikz
post
Post #16





Grupa: Zarejestrowani
Postów: 48
Pomógł: 3
Dołączył: 7.12.2007

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


Muszę się szczerze przyznać że nowością jest dla mnie fakt że PHP może nie radzić sobie ze zwalnianiem zasobów. Nigdy, na swoim przypadku, nie zaobserwowałem czegoś takiego i nigdy też nie stosowałem samodzielnego zwalniania zasobów w destruktorach (bo rozumiem że mówisz o samodzielnym zwalnianiu). Czy mógłbyś podrzucić jakiś przykład takiego zwalniania?
Go to the top of the page
+Quote Post
Crozin
post
Post #17





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

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


Wystarczy użyć zwykłego unset.
Go to the top of the page
+Quote Post
thek
post
Post #18





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Jak wspomniał Crozin - unset. Co do destruktora to wiele osób odpuszcza sobie pisanie go w przypadku mało skomplikowanych klas. Zazwyczaj bowiem domyślne destruktory bezproblemowo radzą sobie z usuwaniem. Jeśli struktura jest zagmatwana lub niszczenie obiektu powinno zakończyć się określonymi działaniami, to własny destruktor po prostu ratuje tyłek. Nieważne bowiem jak kończy żywot obiekt - destruktor zostanie wywołany i wykona zadaną akcję, przykładowo zapis stanu obiektu do bazy lub pliku w momencie zniszczenia.
Go to the top of the page
+Quote Post
Zagiewa
post
Post #19





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


Pisałem, pisałem, aż stanąłem w miejscu (IMG:style_emoticons/default/sad.gif) Niby bez błędu a jednak przesyłane wartości nie trafiają do bazy. Mam dwa pliki. Jeden z klasą, drugi z formularze do dodawania wpisów w prostej księdze gości. Przypominam, że to mój pierwszy skrypt z zastosowaniem obiektowości. Mógł by ktoś zerknąć na moje wypociny i sprawdzić czemu to nie działa?
  1. <?php
  2.  
  3. class ksiega {
  4.  
  5. private $_data = null;
  6. private $_godzina = null;
  7. private $_imie = null;
  8. private $_email = null;
  9. private $_strona = null;
  10. private $_gg = null;
  11. private $_wpis = null;
  12.  
  13. public function ustaw_wartosci($data, $godzina, $imie, $email, $strona, $gg, $wpis) {
  14.  
  15. $this->_data = $data;
  16. $this->_godzina = $godzina;
  17. $this->_imie = $imie;
  18. $this->_email = $email;
  19. $this->_strona = $strona;
  20. $this->_gg = $gg;
  21. $this->_wpis = $wpis;
  22. }
  23.  
  24. public function pokaz() {
  25.  
  26. return $this->_data.'\n';
  27. return $this->_godzina.'\n';
  28. return $this->_imie.'\n';
  29. return $this->_email.'\n';
  30. return $this->_strona.'\n';
  31. return $this->_gg.'\n';
  32. return $this->_wpis.'\n';
  33. }
  34.  
  35. public function save() {
  36.  
  37. include('dane.php');
  38. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  39. die("Sprawdź połączenie z serwerem! " . mysql_error());
  40.  
  41. mysql_select_db(SQL_DB, $sql) or
  42. die("Sprawdź bazę! " . mysql_error());
  43.  
  44. $insert = "INSERT INTO wpisy (data, godzina, imie, email, strona, gg, wpis)
  45. VALUES ('$this->data', '$this->godzina', '$this->imie', '$this->email', '$this->strona', '$this->gg', '$this->wpis')";
  46. $result = mysql_query($insert) or
  47. die('Dodanie wpisu nie powiodło się. ' . mysql_error());
  48. }
  49.  
  50. public function load_one($id) {
  51.  
  52. $select = "SELECT * FROM wpisy WHERE id=$id";
  53. $result = mysql_query($select) or
  54. die('Załadowanie wpisu z bazy nie powiodło się. ' . mysql_error());
  55. }
  56.  
  57. public function load_all() {
  58.  
  59. $select = "SELECT * FROM wpisy ORDER BY id DESC ";
  60. $result = mysql_query($select) or
  61. die('Załadowanie wpisów z bazy nie powiodło się. ' . mysql_error());
  62. }
  63. }
  64.  
  65. ?>

  1. <html>
  2. <head>
  3. </head>
  4. <body>
  5.  
  6. <?php
  7.  
  8. if(isset($_POST['submit'])) {
  9.  
  10. include('class/wpis.php');
  11.  
  12. $data = date("d-m-Y");
  13. $godzina = date("G:i");
  14. $imie = $_POST['imie'];
  15. $email = $_POST['email'];
  16. $strona = $_POST['strona'];
  17. $gg = $_POST['gg'];
  18. $wpis = $_POST['wpis'];
  19.  
  20. $nowy = new ksiega;
  21. $nowy->ustaw_wartosci($data, $godzina, $imie, $email, $strona, $gg, $wpis);
  22. $nowy->save();
  23.  
  24. echo 'Dziękuję za dodanie wpisu do księgi gości.';
  25. exit();
  26. }
  27.  
  28. ?>
  29.  
  30. Aby dodać wpis do księgi wypełnij formularz.
  31. <br /><br />
  32.  
  33. <form method="post">
  34. Autor: <input type="text" name="imie" size="25"><br />
  35. Email: <input type="text" name="email" size="25"><br />
  36. Strona www: <input type="text" name="strona" size="25"><br />
  37. Numer gg: <input type="text" name="gg" size="25"><br />
  38. Komentarz: <textarea style="width: 250px; height: 150px;" name="wpis"></textarea><br />
  39. <input type="submit" name="submit" value="Dodaj">
  40. </form>
  41.  
  42. </body>
  43. </html>


Ten post edytował Zagiewa 28.06.2010, 12:08:37
Go to the top of the page
+Quote Post
thek
post
Post #20





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Po pierwsze - użyj właściwego bbcode (nie wal do znacznika code, ale php i na przyszłość odpowiednio css, html czy inne). Poza tym nie wiemy jaki bład Ci sypie, a to też ważna informacja. Ja obstawiam, że funkcja save i błąd zapytania wpisującego do bazy. Ale to tylko przypuszczenie z mojej strony.
Go to the top of the page
+Quote Post
phpion
post
Post #21





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




  1. class ksiega {
  2.  
  3. private $_data = null;
  4. private $_godzina = null;
  5. private $_imie = null;
  6. private $_email = null;
  7. private $_strona = null;
  8. private $_gg = null;
  9. private $_wpis = null;
  10.  
  11. //...
  12. }

Zastanowiłbym się nad sensownością powyższego kodu. Czy obiekt klasy ksiega faktycznie posiada takie elementy jak data, godzina itd.? Moim zdaniem nie, księga gości jest kolekcją wpisów, czyli powyższe składowe powinny być raczej w klasie wpis, a klasa ksiega powinna mieć jakąś składową typu tablicowego, w której byłyby obiekty wpisów. Wydaje mi się to sensowniejsze.
Go to the top of the page
+Quote Post
Mikz
post
Post #22





Grupa: Zarejestrowani
Postów: 48
Pomógł: 3
Dołączył: 7.12.2007

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


Cytat(phpion @ 28.06.2010, 09:55:28 ) *
powyższe składowe powinny być raczej w klasie wpis, a klasa ksiega powinna mieć jakąś składową typu tablicowego, w której byłyby obiekty wpisów. Wydaje mi się to sensowniejsze.


Oczywiście pod warunkiem że zakładamy na jednej stronie więcej niż jedną księgę (IMG:style_emoticons/default/smile.gif) .
Zagiewa -> zrób następująco a potem obejrzyj zapytanie ew. wklej je do phpmyadmina:

  1. // (...)
  2. public function save() {
  3.  
  4. include('dane.php');
  5. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  6. die("Sprawdź połączenie z serwerem! " . mysql_error());
  7.  
  8. mysql_select_db(SQL_DB, $sql) or
  9. die("Sprawdź bazę! " . mysql_error());
  10.  
  11. $insert = "INSERT INTO wpisy (data, godzina, imie, email, strona, gg, wpis)
  12. VALUES ('$this->data', '$this->godzina', '$this->imie', '$this->email', '$this->strona', '$this->gg', '$this->wpis')";
  13. echo '<pre>';
  14. echo $insert;
  15. echo '</pre>';
  16. //POWYŻSZE 4 LINIE!
  17. $result = mysql_query($insert) or
  18. die('Dodanie wpisu nie powiodło się. ' . mysql_error());
  19. }
  20. // (...)


Koniecznie pamiętaj jeszcze o mysql_real_escape_string() żeby zabezpieczyć swój skrypt przed atakiem Sql Injection, inaczej każdy bardziej rozgarnięty szesnastolatek zrobi z Twoją bazą danych wszystko co będzie chciał.

Dzięki za przydatne odpowiedzi dotyczące unsetów (IMG:style_emoticons/default/smile.gif) . W sumie dawno nie robiłem w "czystym" phpie, ostatnio się babram głównie w symfony ale wracam teraz do samego phpa i piszę coś w rodzaju frameworka/silnika i to mi się z całą pewnością przyda.

Ten post edytował Mikz 28.06.2010, 11:19:21
Go to the top of the page
+Quote Post
phpion
post
Post #23





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(Mikz @ 28.06.2010, 11:23:30 ) *
Oczywiście pod warunkiem że zakładamy na jednej stronie więcej niż jedną księgę (IMG:style_emoticons/default/smile.gif) .

Chyba nie do końca wiesz o czym piszesz.
Go to the top of the page
+Quote Post
Zagiewa
post
Post #24





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


thek sorki za te bbcode - już poprawiłem.
phpion mniej więcej rozumiem o co Ci chodzi ale nie był bym w stanie czegoś takiego zrobić haha (IMG:style_emoticons/default/tongue.gif) jak sam widzisz jest to mój pierwszy taki skrypt (miał być prosty) i już są problemy (IMG:style_emoticons/default/tongue.gif) Pytasz czy obiekt posiada takie elementy jak data i czas, tworząc tą klasę uznałem, że tak bo w momencie dodawania wpisu tworzony jest obiekt, do zmiennej jest zapisywany czas i data dodania a cały obiekt z tymi dwiema wartościami trafia do bazy jak dla mnie to ma sens.
Mikz Zrobiłem tak jak mówiłeś i oto co wypluła przeglądarka:
Kod
INSERT INTO wpisy (data, godzina, imie, email, strona, gg, wpis)
VALUES ('', '', '', '', '', '', '')

ok wiem, że brak wartości ale czemu? przecież przesyłam wartości, a przynajmniej tak mi się wydaje. Co do funkcji, którą mi podałeś przed atakami SQL Injection to dzięki, później sobie ją przerobie:)
Dobra, poradziłem sobie z tym. Dzięki Mikz za naprowadzenie. Wystarczyło w metodzie save() dodać podkreślenia _ przed zmiennymi/referencjami (tak to właściwie nazwać?) a wygląda to tak:
  1. public function save() {
  2.  
  3. include('dane.php');
  4. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  5. die("Sprawdź połączenie z serwerem! " . mysql_error());
  6.  
  7. mysql_select_db(SQL_DB, $sql) or
  8. die("Sprawdź bazę! " . mysql_error());
  9.  
  10. $insert = "INSERT INTO wpisy (data, godzina, imie, email, strona, gg, wpis)
  11. VALUES ('$this->_data', '$this->_godzina', '$this->_imie', '$this->_email', '$this->_strona', '$this->_gg', '$this->_wpis')";
  12.  
  13. $result = mysql_query($insert) or
  14. die('Dodanie wpisu nie powiodło się. ' . mysql_error());
  15. }

Mam jeszcze takie pytanie. Czy w moim kodzie metoda ustaw_wartości działa poprawnie? Wydaje mi się, że tak bo gdy by metoda ta nie ustawiła wartości to metoda save nie mogła by zapisać wartości do bazy mam rację?

Ten post edytował Zagiewa 28.06.2010, 12:53:14
Go to the top of the page
+Quote Post
phpion
post
Post #25





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(Zagiewa @ 28.06.2010, 13:31:18 ) *
phpion mniej więcej rozumiem o co Ci chodzi ale nie był bym w stanie czegoś takiego zrobić haha (IMG:style_emoticons/default/tongue.gif) jak sam widzisz jest to mój pierwszy taki skrypt (miał być prosty) i już są problemy (IMG:style_emoticons/default/tongue.gif) Pytasz czy obiekt posiada takie elementy jak data i czas, tworząc tą klasę uznałem, że tak bo w momencie dodawania wpisu tworzony jest obiekt, do zmiennej jest zapisywany czas i data dodania a cały obiekt z tymi dwiema wartościami trafia do bazy jak dla mnie to ma sens.

Ok, ale odpowiedz sobie na pytanie: co dodajesz do bazy? Księgę czy wpis? Sam zresztą napisałeś:
Cytat(Zagiewa @ 28.06.2010, 13:31:18 ) *
w momencie dodawania wpisu tworzony jest obiekt, do zmiennej jest zapisywany czas i data dodania a cały obiekt z tymi dwiema wartościami trafia do bazy

Jak widzisz dodajesz obiekt wpisu, a nie księgi. Księga zawiera w sobie wpisy (obiekty wcześniej dodanych wpisów). Piszesz o umiejętnościach, że się uczysz: w takim razie od razu ucz się dobrego podejścia, a nie pseudo-obiektowego.
Go to the top of the page
+Quote Post
Zagiewa
post
Post #26





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


No tak dodaję wpis, więc według Ciebie powinna być klasa o nazwie baza a jej wartościami klasa o nazwie wpis i co jeszcze? jak poprawnie powinno to wyglądać? Tworząc moją klasę wydawało mi się, że dobrze ją zaplanowałem, a obecnie jak wspomniałeś o dwóch klasach, nie mam pojęcia jak one miały by wyglądać aby były poprawne.
Go to the top of the page
+Quote Post
phpion
post
Post #27





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




To powinno Ci nieco rozjaśnić sytuację:
  1. class Wpis {
  2. protected $data;
  3. protected $tresc;
  4.  
  5. public function dodaj() {
  6. // Zapis do bazy danych
  7. }
  8. }
  9.  
  10. class Ksiega {
  11. protected $wpisy = array();
  12.  
  13. public function pobierz_wpisy() {
  14. // Zapytanie do bazy
  15.  
  16. foreach ($wpisy_z_bazy as $wpis_jako_tablica) {
  17. $wpis = new Wpis($wpis_jako_tablica['data'], $wpis_jako_tablica['tresc']);
  18.  
  19. $this->wpisy[] = $wpis;
  20. }
  21. }
  22.  
  23. public function dodaj_wpis(Wpis $wpis) {
  24. $wpis->dodaj();
  25. }
  26. }
Go to the top of the page
+Quote Post
thek
post
Post #28





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Zagiewa... Popatrz na to tak jak phpion czy ja. Najbardziej elementarny jest wpis i to on zawiera wszystkie wymienione pola. Nazwijmy więc klasę tak, jak naprawdę ona się przedstawia - Wpis. Dopiero wpisy tworzą pewien zbiór, kolekcję, którą nazywamy księgą wpisów. Skoro tak, to klasa Ksiega_wpisow może być implementowana jako tablica obiektów typu Wpis. Jak to by wyglądało w kodzie? tak naprawdę to tylko tak, że jedyną potrzebną klasą byłby Wpis a księga to byłaby zwyczajna tablica i przez to naturalne byłoby działanie w stylu.
$ksiega_wpisow[] = new Wpis;
Można tworzyć dodatkową klasę, która by się zajmowała szerszą grupą wpisów, ale bazowo tak naprawdę potrzeba Ci:
klasa Wpis
Pola: imie, email, strona, gg, wpis, dodano (pole w bazie z ustawionym CURRENT_TIMESTAMP)
Metody: dodaj, edytuj (tak naprawdę dodaj i edytuj można ująć jedną metoda wykorzystując ON DUPLICATE UPDATE), usun, pokaz(zwraca pojedynczy wpis)

Klasa Księga tak naprawdę nie byłaby czymś innym niż:
klasa Ksiega
Pola: lista_wpisow (zwykła tablica przechowująca obiekty klasy Wpis)
Metody: pokaz(zwraca listę iluś wpisów według określonego wzorca wyszukiwania), ewentualne kombinowanie z dodaniem, edycją lub usuwaniem wielu na raz to tak naprawdę to samo co posiada klasa wpis. Duplikowalibyśmy więc metody klasy Wpis lub w skrócie moglibyśmy napisać je jako wywołanie metody obiektu Wpis wielokrotnie.
Go to the top of the page
+Quote Post
Mikz
post
Post #29





Grupa: Zarejestrowani
Postów: 48
Pomógł: 3
Dołączył: 7.12.2007

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


Cytat(phpion @ 28.06.2010, 12:20:29 ) *
Chyba nie do końca wiesz o czym piszesz.

Zrozumiałem że proponujesz żeby księga była obiektem. Ja bym raczej skłaniał się ku utworzeniu klasy z polami i metodami statycznymi. Wtedy struktura tworzy nam się całkiem sensowna, mamy zbiór metod które zarządzają wszystkimi wpisami, które, tak jak zaproponowałeś, znajdują się w tablicy. Chyba że mówiłeś o czym innym, wtedy zwracam honor.

Edit: Zresztą Twój następny post potwierdza moje przypuszczenie, przy utworzeniu klasy ze statycznymi metodami nie ma potrzeby tworzyć nowej instancji obiektu Ksiega, tylko odwołujemy się tak:

Ksiega::pobierz_wpisy();

lub

Ksiega::dodaj_wpis($wpis);

Więc jeżeli nie mamy na stronie więcej niż jednej księgi lub nie tworzymy jakiejś złożonej biblioteki, wydaje mi się że takie rozwiązanie jest lepsze.

Ten post edytował Mikz 28.06.2010, 17:37:49
Go to the top of the page
+Quote Post
tmka
post
Post #30





Grupa: Zarejestrowani
Postów: 27
Pomógł: 9
Dołączył: 9.02.2009

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


Witam,
ja jeszcze wtrącę się na temat twojego kodu Zagiewa. Pytałeś się czemu u siebie użyłem oddzielnych metod ustawiających i pobierających (setterów i getterów potocznie mówiąc) dla każdego z pól. Dzięki takiemu rozwiązaniu możesz np. zwalidować przesłane dane zanim je zapiszesz do pola obiektu. Oczywiście, możesz to również zrobić w metodzie takiej jak twoja, ale jeżeli pól będzie dużo, to metoda rozrośnie się i będzie mało elegancka. Dodatkowo, gdy zechcesz rozbudować obiekt o dodatkowe pola, bedziesz musiał modyfikować tą metodę, a w obiektówce takie działanie jest niepożądane, bo np. mogłeś już użyć tej metody w wielu miejscach i przy zmianie ilości argumentów będzie trzeba albo poustawiać je w deklaracji metody na jakieś domyślne wartości, albo poprostu modyfikować każde wywołanie. Bardziej eleganckim sposobem jest właśnie zrobienie getterów i setterów, nawet jeżeli pol jest niewiele, poprostu dobrze już mieć taki nawyk.

Jeszcze podam takie małe 'ułatwienie' w pisaniu setterow. Otóż w php można zrobić coś takiego:
  1. public setDzien($dzien)
  2. {
  3. $this->_dzien = $dzien;
  4. return $this; //zwracamy instancje do 'siebie',
  5. }
  6.  
  7. public setMiesiac($mies)
  8. {
  9. $this->_mies= $mies;
  10. return $this; //zwracamy instancje do 'siebie',
  11. }
  12.  
  13. //normalnie ustawienie wyglądałoby tak:
  14. $data = new Data();
  15. $data->setDzien(12);
  16. $data->setMiesiac(4);
  17.  
  18. //przy konstrukcji metod ustawiających które zwracaja instancje do swojego obiektu
  19. //bedzie wygladac to tak:
  20. $data->setDzien(12)->setMiesiac(4);
  21.  
  22.  


Może dodam jeszcze słowo wyjaśnienia. Gdy wywolasz któregoś z setterów, zostanie zwrócony obiekt dla którego ta metoda została wywołana, następnie możesz 'w locie' wywołać kolejną metode tego obiektu itd. wystarczy zeby metoda zwracala obiekt do ktorego należy, czyli poprostu $this.



Ten post edytował tmka 29.06.2010, 09:22:07
Go to the top of the page
+Quote Post
Zagiewa
post
Post #31





Grupa: Zarejestrowani
Postów: 84
Pomógł: 0
Dołączył: 12.08.2009

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


Wiem, że już trochę minęło od dnia kiedy założyłem ten temat ale nie miałem czasu (IMG:style_emoticons/default/sad.gif) Przerobiłem moją klasę według waszych wskazówek i na chwile obecną wygląda ona tak:
  1. <?php
  2.  
  3. class wpis {
  4.  
  5. private $_data = null;
  6. private $_godzina = null;
  7. private $_imie = null;
  8. private $_email = null;
  9. private $_strona = null;
  10. private $_gg = null;
  11. private $_wpis = null;
  12.  
  13. public function ustaw_wartosci($data, $godzina, $imie, $email, $strona, $gg, $wpis) {
  14.  
  15. $this->_data = $data;
  16. $this->_godzina = $godzina;
  17. $this->_imie = $imie;
  18. $this->_email = $email;
  19. $this->_strona = $strona;
  20. $this->_gg = $gg;
  21. $this->_wpis = $wpis;
  22. }
  23.  
  24. public function save() {
  25.  
  26. include('dane.php');
  27. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  28. die("Sprawdź połączenie z serwerem! " . mysql_error());
  29.  
  30. mysql_select_db(SQL_DB, $sql) or
  31. die("Sprawdź bazę! " . mysql_error());
  32.  
  33. $insert = "INSERT INTO wpisy (data, godzina, imie, email, strona, gg, wpis)
  34. VALUES ('$this->_data', '$this->_godzina', '$this->_imie', '$this->_email', '$this->_strona', '$this->_gg', '$this->_wpis')";
  35.  
  36. $result = mysql_query($insert) or
  37. die('Dodanie wpisu nie powiodło się. ' . mysql_error());
  38. }
  39. }
  40.  
  41. class ksiega {
  42.  
  43. protected $wpisy = array();
  44.  
  45. public function pokaz() {
  46.  
  47. return $this->_data.'\n';
  48. return $this->_godzina.'\n';
  49. return $this->_imie.'\n';
  50. return $this->_email.'\n';
  51. return $this->_strona.'\n';
  52. return $this->_gg.'\n';
  53. return $this->_wpis.'\n';
  54. }
  55.  
  56. public function load_all() {
  57.  
  58. include('dane.php');
  59. $sql = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or
  60. die("Sprawdź połączenie z serwerem! " . mysql_error());
  61.  
  62. mysql_select_db(SQL_DB, $sql) or
  63. die("Sprawdź bazę! " . mysql_error());
  64.  
  65. $select = "SELECT * FROM wpisy ORDER BY id DESC ";
  66. $result = mysql_query($select) or
  67. die('Załadowanie wpisów z bazy nie powiodło się. ' . mysql_error());
  68. }
  69. }
  70. ?>

Jestem wręcz pewien, że można to zrobić lepiej niż obecnie to wygląda więc prosił bym o dalsze wskazówki jak to polepszyć. (IMG:style_emoticons/default/smile.gif)

Ten post edytował Zagiewa 23.07.2010, 22:07:35
Go to the top of the page
+Quote Post
cojack
post
Post #32





Grupa: Zarejestrowani
Postów: 898
Pomógł: 80
Dołączył: 31.05.2008

Ostrzeżenie: (20%)
X----


Zainteresuj się wzorcem GenericObject oraz GenericObjectCollection i znajdziesz odpowiedź na swoje pytanie. Przy okazji wzorzec fabryki do wykorzystania różnych silników baz danych, słowa kluczowe to: GenericObject, GenericObjectCollection, DatabaseConnection, DatatabaseQuery, DatabaseTransaction, ExceptionFactory

Ten post edytował cojack 23.07.2010, 22:27:43
Go to the top of the page
+Quote Post
Crozin
post
Post #33





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

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


1) Metody z serii "ustawi 123123123 wartości na raz" są bez sensu.
2) Nie da się na raz zwrócić 10 wartości (ksiega::pokaz())
3) Nie uważasz za bezsensowne każdorazowe łączenie się z bazą danych w metodach save()?
4) Data/godzina - do tego nie potrzeba dwóch zmiennych - jedna jest w pełni wystarczająca
Go to the top of the page
+Quote Post
everth
post
Post #34





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Swoją drogą to najlepiej te wszystkie zawiłości opanujesz ucząc się innego języka niż PHP (np. C++). Później nauka większości języków oprogramowania jest bardziej sprawna. Co do twojej klasy to od razu da się zastosować tutaj dziedziczenie np. z ArrayObject PHP (do klasy Księga - de facto jest to kolekcja wpisów, ArrayObject fajnie nadaje się do tworzenia kolekcji) czyli łopatologicznie:
  1. <?php
  2.  
  3. // Deklaracja klas, dobrym zwyczajem jest umieszczanie każdej klasy w oddzielnym pliku,
  4. // ja robię tak że jeśli są powiązane i małe to wrzucam je do jednego (np. klasa Ksiega z klasą wpis, klasa MyPDO z klasą SqlObject itd.)
  5.  
  6. class MyPDO extends PDO { //dopisujemy parę funkcji do bazodanowej klasy PDO
  7. public function insert(SqlObject $insert) {
  8. return parent::prepare($insert->insertSqlCode());
  9. }
  10.  
  11. public function remove(SqlObject $remove) {
  12. return parent::prepare($remove->removeSqlCode());
  13. }
  14. }
  15.  
  16. abstract class SqlObject { //abstract oznacza że klasa nie może być samodzielnym obiektem, służy jako szablon po którym mogą dziedziczyć inne klasy
  17. public $table_name = get_class($this); // domyślnie nazwa klasy jest nazwą tabeli, pokraczne rozwiązanie ale nie chce mi się mysleć
  18.  
  19. public function insertSqlCode() {
  20. $data = $this->prepareData();
  21. $insert = "INSERT INTO ".$this->table_name." (".implode(',',array_keys($data)).") VALUES (".implode(',',$data).")";
  22. return $insert;
  23. }
  24.  
  25. public function removeSqlCode() {
  26. $data = $this->prepareData();
  27. $remove = "DELETE FROM ".$this->table_name." WHERE ";
  28.  
  29. // normalnie przefiltrowalibysmy rekordy do usunięcia po kluczu ale klasa Wpis takowego nie ma, filtrujemy wiec po wszystkich polach (naprawde pokraczne)
  30. $filters = array();
  31. foreach($data as $name=>$value) {
  32. $filters[] = $this->table_name.".".$name."='".$value."'";
  33. }
  34. $remove .= implode(' AND ',$filters);
  35.  
  36. return $remove;
  37. }
  38.  
  39. protected function prepareData() { //przygotuj dane z pól obiektu, wykluczając zbyteczne
  40. $data = get_vars_object($this); //pobieramy dane obiektu
  41. unset($data['table_name']); //usuwamy pole z nazwą tabeli
  42. return $data
  43. }
  44. }
  45.  
  46. class Wpis extends SqlObject {
  47.  
  48. public $table_name = "Ksiega"; // nadpisujemy domyślną nazwę tabeli
  49.  
  50. protected $_data = null;
  51. protected $_godzina = null;
  52. protected $_imie = null;
  53. protected $_email = null;
  54. protected $_strona = null;
  55. protected $_gg = null;
  56. protected $_wpis = null;
  57.  
  58. public function __construct($data, $godzina, $imie, $email, $strona, $gg, $wpis) {
  59.  
  60. $this->_data = $data;
  61. $this->_godzina = $godzina;
  62. $this->_imie = $imie;
  63. $this->_email = $email;
  64. $this->_strona = $strona;
  65. $this->_gg = $gg;
  66. $this->_wpis = $wpis;
  67. }
  68.  
  69. public function showHtmlTableRow() {
  70. $resultString = "<tr>";
  71. $data = $this->prepareData() //nieładnie zrobione ale działa ;)
  72. foreach($data as $name=>$value) {
  73. $resultString .= "<td class=".$name.">".$value."</td>";
  74. }
  75. $resultString .= "</tr>";
  76. return $resultString;
  77. }
  78.  
  79. }
  80.  
  81. class Ksiega extends ArrayObject {
  82. public $db;
  83. public $table_name = 'Ksiega'; // kolejna pokraka
  84.  
  85. public function __construct($db) {
  86. $this->db = $db; // ponieważ moja klasa PDO nie jest singletonem to przekazuję ją jako referencję
  87. }
  88.  
  89. function offsetset($index=null, Wpis $value) { //nadpisujemy domyślną metodę klasy ArrayObject
  90. $this->db->insert($value)->execute(); //dodając wpis do kontenera automatycznie dodajemy go do bazy
  91. parent::offsetset($index, $value);
  92. }
  93.  
  94. function offsetUnset($index) { //przy usuwaniu wpisu z Ksiegi usuwaj tez wpis z bazy
  95. $wpis = $this[$index];
  96. if ($wpis) $this->db->remove($wpis)->execute();
  97. $wpis = NULL; //nie wiem czy to potrzebne ale dla świętego spokoju lepiej zniszczyć obiekt który nie ma odniesienia w bazie
  98. parent::offsetUnset($index);
  99. }
  100.  
  101. public function retrieveEntriesFromDB() {
  102. $sth = $this->db->prepare("SELECT * FROM ".$this->table_name);
  103. $sth->setFetchMode(PDO::FETCH_CLASS, 'Wpis'); // zamiast pobierać rekordy jako tablice, tworzymy z nich obiekty klasy Wpis
  104. $sth->execute();
  105. foreach ($sth as $wpis) {
  106. $this[] = $wpis; //dodaje kazdy rekord jako obiekt Wpis do kontenera Ksiega
  107. }
  108. }
  109.  
  110. public function showEntriesAsHtmlTable() {
  111. $resultString = "<table>";
  112. foreach ($this as $entry) {
  113. $resultString .= $entry->showHtmlTableRow();
  114. }
  115. $resultString .= "</table>";
  116. return $resultString;
  117. }
  118. }
  119.  
  120.  
  121. // WYKONANIE SKRYPTU
  122.  
  123. $db = new MyPDO($moja_konfiguracja_bazy);
  124.  
  125. $ksiega = new Ksiega($db);
  126. $ksiega->retrieveEntriesFromDB();
  127. echo $ksiega->showEntriesAsHtmlTable();
  128.  
  129. $wpis = new Wpis(date(),time(),'Jasiu','fasola@email.com','abojawiem',32167,'Nowy wpis');
  130.  
  131. $ksiega[] = $wpis // dodajemy wpis do bazy,oraz do kontenera Ksiega, ew. trzeba zastosować "REPLACE" zamiast "INSERT" żeby uniknac dublowania rekordów
  132.  
  133. unset($ksiega[5]); // usuwamy z Ksiegi i bazy wpis numer 5
  134.  
  135.  
  136. ?>

Nie parsowałem powyższego skryptu więc nie wiem czy zadziała. W każdym razie jak zapoznasz się z OOP to zobaczysz że nie da się normalnie pisać w PHP bez niego (ja przynajmniej nie potrafię (IMG:style_emoticons/default/smile.gif) ). Ale jak naprawdę chcesz być dobry to weź inny język programowania np. C++ lub Javę i tam spróbuj coś napisać. Jak tam dojdziesz do przyzwoitego poziomu to PHP będzie bułką z masłem. Po prostu PHP uczy złych nawyków.

BTW, wcześniej ktoś wspomniał o możliwych wyciekach pamięci w skryptach PHP. Może ja czegoś nie wiem lub nie rozumiem, ale przecież to chyba niemożliwe skoro pamięć jest zwalniana po zakończeniu działania programu. A PHP kończy się wykonywać wraz z końcem skryptu - czyli tak: CGI wywołuje interpreter PHP jako proces - PHP alokuje standardowy rozmiar pamięci, parsuje skrypt i rozpoczyna jego wykonanie, wszelkie wycieki pamięci powstają w obrębie za-alokowanej pamięci (od tego mamy Garbage Collectora), skrypt kończy działanie, PHP zwraca wynik i kończy swoje działanie - pamięć przez niego zajęta jest oznaczana jako wolna. Tak więc skrypt musi być naprawdę kompleksowy i rozbudowany żeby wycieki pamięci mogły odgrywać znaczącą rolę. Dziwię się bo jeszcze nigdy się z problemem wycieku pamięci w PHP nie spotkałem (ani też nie stosowałem destruktorów bez potrzeby).

Ten post edytował everth 25.07.2010, 11:58:42
Go to the top of the page
+Quote Post
thomson89
post
Post #35





Grupa: Zarejestrowani
Postów: 1 178
Pomógł: 51
Dołączył: 7.01.2009
Skąd: Gdańsk

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


Ja piszę obiektowo już od 6 miesięcy. Zacząłem gdy zacząłem pisać sklep internetowy. Powiem, że w tej chwili bez obiektowego pisania dużo bym nie zrobił. Jak dotąd, z łatwością mi się pisało wszystkie klasy. Tworzę nie jednokrotnie pliki które mają 700 linijek kodu.

Ja dzięki obiektowemu pisaniu aplikacji, przede wszystkim ułatwiłem sobie edycję. Mam przykładowo klasę produkt i plik produkty. W klasie produkt piszę wszystko co potrzebne, czyli np. dodaj, zmien, usun, sprawdz. A w pliku produkty tylko pobieram dane z formularza i:
  1. require_once('klasy/produkt.class.php');
  2. $produkt = new produkt;
  3. $produkt -> dodaj($_POST);


I tyle. W razie jakiś dodatkowych pól, lub innych tego typu po prostu edytuję JEDEN PLIK! A nie jak w strukturalnym plik z formularzem, plik odbierający i plik umieszczający. Przy dużych projektach jest to naprawdę obowiązkowe pisanie aplikacji.
Go to the top of the page
+Quote Post
Pilsener
post
Post #36





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

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


A ja jeszcze dodam, że pisząc obiektowo dostajemy cały "arsenał" narzędzi wspomagających programowanie, od bibliotek, pluginów, dodatków i frameworków zaczynając, a kończąc na prawdziwych kombajnach, gdzie mamy pod ręką zmienne lokalne i globalne, podpowiedzi (typu np. lista dostępnych metod danego obiektu wraz z opisem), przeglądarkę obiektów - można stworzyć prostą aplikacyjkę bez pisania nawet linijki kodu.
Go to the top of the page
+Quote Post
cojack
post
Post #37





Grupa: Zarejestrowani
Postów: 898
Pomógł: 80
Dołączył: 31.05.2008

Ostrzeżenie: (20%)
X----


IDE jakieś sobie zainstalowałeś? Czu przesiadłeś się na ASPX?
Go to the top of the page
+Quote Post
Luneth
post
Post #38





Grupa: Zarejestrowani
Postów: 95
Pomógł: 7
Dołączył: 16.07.2007
Skąd: Gorzów Wielkopolski

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


Cytat(Crozin @ 23.07.2010, 23:30:50 ) *
1) Metody z serii "ustawi 123123123 wartości na raz" są bez sensu.
2) Nie da się na raz zwrócić 10 wartości (ksiega::pokaz())
3) Nie uważasz za bezsensowne każdorazowe łączenie się z bazą danych w metodach save()?
4) Data/godzina - do tego nie potrzeba dwóch zmiennych - jedna jest w pełni wystarczająca


Wszystkie wypowiedzi poza pierwszą linijką są oczywiste, ale myślę, że autor (tak samo jak i ja) chętnie dowiedziałby się co konkretnie miałeś na myśli, czy porobienie settera dla każdego pola, a może ustawienie ich jako publiczne, lub jeszcze jakieś inne rozwiązanie? (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
everth
post
Post #39





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


To zależy. Settery ułatwiają pracę gdyby trzeba zmieniać kod - wtedy metoda settera zostaje, ale sam setter może dowolnie przekształcać dane. Ale ponieważ PHP nie jest językiem kompilowanym to trzeba zachować umiar - settery do każdej głupoty (gdzie wystarcza public) mają narzut na wydajność. Po prostu musisz się zdecydować czy dana zmienna może kiedyś potrzebować dodatkowej obróbki, czy też nie.
Go to the top of the page
+Quote Post
phpion
post
Post #40





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




@everth:
Ja nigdy nie korzystam z publicznych składowych klasy. Wszystkie składowe mają swoje gettery i settery. Dlaczego? Mam wówczas pełną kontrolę nad tym, co siedzi w obiekcie. Nawet takie prozaiczne ustawianie imienia robię setterem rzutując przekazywaną wartość na string.
  1. public function set_name($name) {
  2. $this->name = (string)$name;
  3. }

Fakt - jest to czasem upierdliwe bo zanim przejdę do pisania kodu klasy to wcześniej muszę napisać wszystkie settery i gettery (wraz z phpDoc'em). Mam jednak tego pecha, że jestem strasznie pedantyczny pod kątem kodu i wszystko musi być na tip-top (IMG:style_emoticons/default/winksmiley.jpg) .
Go to the top of the page
+Quote Post
Crozin
post
Post #41





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

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


@phpion: settery/gettery można z automatu generować przez IDE (IMG:style_emoticons/default/winksmiley.jpg)

Co do bezsensowności czegoś takiego (tj. ustawiania wszystkiego przez jedną metodę).
1) Co jeżeli masz już obiekt i chcesz zmienić jedną składową?
2) Zapamiętanie kolejności 10 parametrów to zbędny wysiłek
3) Burdel w kodzie (w momencie gdy chcesz zrobić coś więcej niż tylko przypisać w metodzie wartości argumentów do składowych)
4) Utrudniona dokumentacja
5) Utrudniona rozbudowa kodu (chcąc dodać nową składową musisz w metodzie ustaw wstawić ją na końcu jako opcjonalny argument - inaczej tracisz wsteczną kompatybilność)
Go to the top of the page
+Quote Post
Luneth
post
Post #42





Grupa: Zarejestrowani
Postów: 95
Pomógł: 7
Dołączył: 16.07.2007
Skąd: Gorzów Wielkopolski

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


Crozin, chodziło mi nie tyle o uzasadnienie co zaproponowanie lepszego rozwiązania (IMG:style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
everth
post
Post #43





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Fakt - ale czasem ustawia się podstawowe właściwości obiektu poprzez konstruktor i ja nie widzę w tym nic złego (jest to nawet czytelniejsze niż 10 wywołań jedno pod drugim) - choć ja wolę przekazywać to za pomocą tablicy a nie zmiennych (gdzieś ktoś napisał że jak funkcja ma więcej niż 2 argumenty to jest do dupy).
Go to the top of the page
+Quote Post
Crozin
post
Post #44





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

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


@everth: w konstruktorze podaje się wyłącznie argument wymagane do tego by w ogóle dało się utworzyć obiekt. A ta teza, że metoda z więcej niż dwoma argumentami jest do dupy... jest do dupy.
Go to the top of the page
+Quote Post
phpion
post
Post #45





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




@Crozin:
Netbeans posiada generatory setterów/getterów, Eclipse PDT niestety nie (chyba, że nie potrafię tego znaleźć).

@everth:
Jeśli przesyłasz parametry na hura w postaci tablicy to możesz sobie darować podpowiadanie parametrów w IDE. Podpowiedź, że możesz podać tablicę niewiele da. Osobiście wolę jawnie znać nazwy, znaczenie oraz typy poszczególnych parametrów (szczególnie przy przekazywaniu obiektów).
Go to the top of the page
+Quote Post
everth
post
Post #46





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Cytat(Crozin @ 26.07.2010, 15:22:23 ) *
@everth: w konstruktorze podaje się wyłącznie argument wymagane do tego by w ogóle dało się utworzyć obiekt. A ta teza, że metoda z więcej niż dwoma argumentami jest do dupy... jest do dupy.

I tak i nie. Może przez pewne naleciałości z C++ wiem jak cholernie trudno było tropić błędy w funkcjach przyjmujących po 5 i 6 argumentów, nie tędy droga. Dla mnie metoda przyjmuje coś -> przekształca coś, ew. korzystając z właściwości obiektu -> i ew. zwraca coś. Złota zasada - jedna funkcja robi jedną rzecz, dodatkowe argumenty z reguły służą modyfikacji działania funkcji czyli zaprzeczają powyższej zasadzie.
Skoro akceptujesz sytuację z pierdyliardem setterów/getterów to powiedz mi czy dlaczego setter nie może przyjmować więcej niż jedne argument? Przecież setter może być zbudowany tak że przyjmuje argument bazowy oraz zmienne modyfikujące.

Cytat(phpion @ 26.07.2010, 16:01:36 ) *
@everth:
Jeśli przesyłasz parametry na hura w postaci tablicy to możesz sobie darować podpowiadanie parametrów w IDE. Podpowiedź, że możesz podać tablicę niewiele da. Osobiście wolę jawnie znać nazwy, znaczenie oraz typy poszczególnych parametrów (szczególnie przy przekazywaniu obiektów).

Mogę sobie na to pozwolić jeśli ograniczam się do pól które w moim obiekcie i tak są public. Czyli według zasady - nazwa pola => wartość. To i tak łatwiejsze do modyfikacji niż ciąg argumentów.
Go to the top of the page
+Quote Post
phpion
post
Post #47





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(everth @ 26.07.2010, 16:28:32 ) *
Złota zasada - jedna funkcja robi jedną rzecz, dodatkowe argumenty z reguły służą modyfikacji działania funkcji czyli zaprzeczają powyższej zasadzie.

Zgadza się - jedna funkcja robi jedną rzecz. Ale zauważ, że często przydatne są funkcje "skrótowe", które przyjmą np. 3 parametry i wywołają odpowiednie metody atomowe. Prosty przykład:
  1. class Page {
  2. public function render(Page_Header $header, Page_Body $body, Page_Footer $footer) {
  3. $this->render_header($header);
  4. $this->render_body($body);
  5. $this->render_footer($footer);
  6. }
  7.  
  8. public function render_header(Page_Header $header) {
  9. //
  10. }
  11.  
  12. public function render_body(Page_Body $body) {
  13. //
  14. }
  15.  
  16. public function render_footer(Page_Footer $footer) {
  17. //
  18. }
  19. }

Czy wg Ciebie przekazanie 3 parametrów do metody render() jest błędne?

Cytat(everth @ 26.07.2010, 16:28:32 ) *
Skoro akceptujesz sytuację z pierdyliardem setterów/getterów to powiedz mi czy dlaczego setter nie może przyjmować więcej niż jedne argument? Przecież setter może być zbudowany tak że przyjmuje argument bazowy oraz zmienne modyfikujące.

Zadaniem settera jest ustawianie wartości składowej obiektu. Skąd więc pomysł by przekazywać do niego X parametrów? Przekazujesz 1 parametr, który jest wartością, która będzie przypisana do składowej.

Cytat(everth @ 26.07.2010, 16:28:32 ) *
Mogę sobie na to pozwolić jeśli ograniczam się do pól które w moim obiekcie i tak są public. Czyli według zasady - nazwa pola => wartość. To i tak łatwiejsze do modyfikacji niż ciąg argumentów.

Już lepszym rozwiązaniem byłoby (zamiast jawnego $this->$var = $value) wywoływać call_user_func(array($this, 'set_'.$var), $value). Wtedy wszystkie ustawienia wartości lecą przez odpowiednie settery.
Go to the top of the page
+Quote Post
darko
post
Post #48





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

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


Cytat(haahh @ 24.06.2010, 21:10:54 ) *
Strukturalny faktycznie strasznie się edytuję. Sam zmieniałem ostatnio strukturę wyświetlania mojego "małego portalu" php i to była masakra. Muszę przejść na obiektowy styl pisania kodu - ktoś poleci jakieś książki traktujące o średnio-zaawansowanym php i pisanie obiektowym?

Polecam, tania i warta swej ceny, ale raczej dla średnio-zaawansowanych i zaawansowanych.
Go to the top of the page
+Quote Post
everth
post
Post #49





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Cytat(phpion @ 27.07.2010, 08:13:54 ) *
Zgadza się - jedna funkcja robi jedną rzecz. Ale zauważ, że często przydatne są funkcje "skrótowe", które przyjmą np. 3 parametry i wywołają odpowiednie metody atomowe. Prosty przykład:
  1. class Page {
  2. public function render(Page_Header $header, Page_Body $body, Page_Footer $footer) {
  3. $this->render_header($header);
  4. $this->render_body($body);
  5. $this->render_footer($footer);
  6. }
  7.  
  8. public function render_header(Page_Header $header) {
  9. //
  10. }
  11.  
  12. public function render_body(Page_Body $body) {
  13. //
  14. }
  15.  
  16. public function render_footer(Page_Footer $footer) {
  17. //
  18. }
  19. }

Czy wg Ciebie przekazanie 3 parametrów do metody render() jest błędne?


Zadaniem settera jest ustawianie wartości składowej obiektu. Skąd więc pomysł by przekazywać do niego X parametrów? Przekazujesz 1 parametr, który jest wartością, która będzie przypisana do składowej.


Już lepszym rozwiązaniem byłoby (zamiast jawnego $this->$var = $value) wywoływać call_user_func(array($this, 'set_'.$var), $value). Wtedy wszystkie ustawienia wartości lecą przez odpowiednie settery.

Moim zdaniem jest błędne bo według mnie metoda render powinna być funkcją (void). A parametry powinny być właściwościami klasy Page. Albo inaczej powinna istnieć klasa RenderEngine mająca metodę render która przyjmuje obiekty page lub body lub footer (powinny dziedziczyć po jakimś abstrakcie). Tak mi się wydaje. Ale ponieważ jestem pragmatykiem to akceptuję to jeśli pracuję na czyimś kodzie (nie będę przerabiał całego kodu).

Przykład z setterami jest naciągany. Call_user_func dla mnie ma ograniczone zastosowanie - to taka szybsza wersja eval, a to odstręcza mnie zawsze od stosowania w kodzie (bo wolna, bo trudna w debugowaniu, bo może dawać nieprzewidziane rezultaty, bo może powodować dziury w bezpieczeństwie, bo...). Tak więc to co piszesz, choćby ze względu na wydajność (pomijając czytelność) dla mnie jest wykluczone.
Go to the top of the page
+Quote Post
Crozin
post
Post #50





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

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


call_user_func i inne/zmienne zmiennych - to nie szybsza wersja evala tylko RefelctionAPI. Co do wolności ich wykonywania to się nie zgadzam - natomiast fakt, faktem debuggowanie utrudniają.

Przykład metody, która wymaga wielu parametrów: ot chociażby metoda rysująca prostopadłościan (x, y, z, width, height, depth) - oczywiście można by to zastąpić dwoma obiektami (Point3D(x, y, z), Cuboid(width, height, depth)) ale takie coś można by podciągnąć chyba pod wszystko. Nie mniej jednak przykład nie przyszedł mi od razu do głowy - bo takich metod się nie stosuje zazwyczaj. Jednak czasami się tak zdarza, że coś potrzebuje tych kilku argumentów - wtedy trzeba zadbać o to by było to maksymalnie logiczne i dobrze udokumentowane.
Go to the top of the page
+Quote Post
everth
post
Post #51





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


@Crozin - co do tego że call_user_func jest wolne to tylko powtarzam zasłyszane (IMG:style_emoticons/default/smile.gif) . Gdzieś widziałem wyniki jakiegoś bencha którym porównywano eval,call_user oraz bezpośrednie wywołania. Wyszło na to że wywołanie przez eval jest 10 razy wolniejsze niż bezpośrednie a call_user 2,3 raza wolniejsze. Możliwe że poprawili to w nowszych wersjach. Dla mnie jednak call_user_func jest przydatne tylko w określonych zastosowaniach (np. wywoływanie metod za pomocą GET-a).
Go to the top of the page
+Quote Post
phpion
post
Post #52





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




@everth:
Mój przykład faktycznie był średnio trafiony, zdecydowanie lepszy podał ~Crozin.

Co do wydajności: nie przesadzaj, lepiej skupić się na tym, co faktycznie spowalnia aplikację (np. zapytania SQL). Równie dobrze mógłbyś benchmarkować sobie echo/print czy zrezygnować z foreach().

Argumenty, które podałeś:
Cytat
bo może dawać nieprzewidziane rezultaty, bo może powodować dziury w bezpieczeństwie

można z powodzeniem podpiąć pod bezpośrednie przypisanie wartości do składowych publicznych lub generalnie z pominięciem setterów.
Go to the top of the page
+Quote Post
Crozin
post
Post #53





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

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


Przecież oczywisty jest, że wywołanie call_user_func będzie wolniejsze od zwykłego wykonania wpisanej w kod metody. Ale tej funkcji, a raczej całego zestawu w postaci: call_user_func(), ReflectionAPI, zmienne zmiennych używa się dopiero w momencie gdy są potrzebne i bez nich nie da się obejść - a zbyt często się to nie zdarza (szczególnie od wersji 5.3, gdy dostępne są funkcje anonimowe znika problem połowy callbacków). Nawet jeżeli call_user_func miałoby być 1000 razy wolniejsze niż "statyczne" wywołanie to nie miałoby to znaczenia. Skrypt spowolniłby o 0.0002 sekundy - taką cenę można bez problemu zapłacić.
Go to the top of the page
+Quote Post
everth
post
Post #54





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Cytat(phpion @ 27.07.2010, 08:13:54 ) *
Już lepszym rozwiązaniem byłoby (zamiast jawnego $this->$var = $value) wywoływać call_user_func(array($this, 'set_'.$var), $value). Wtedy wszystkie ustawienia wartości lecą przez odpowiednie settery.

Ja cały czas odnoszę się do powyższego zastosowania które dla mnie osobiście jest bez sensu. Poza tym po to są pola public i private żeby stosować je z rozmysłem. Mi osobiście brakuje jeszcze możliwości ustawienia pola readOnly (jak mają wbudowane klasy) - byłoby to wygodne i bezpieczne.
Go to the top of the page
+Quote Post
phpion
post
Post #55





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(everth @ 27.07.2010, 14:58:52 ) *
Ja cały czas odnoszę się do powyższego zastosowania które dla mnie osobiście jest bez sensu.

Dla mnie też jest to bez sensu, ale jeśli chcesz ustawiać składowe na podstawie tablicy to jest to sensowniejsze rozwiązanie niż $this->$var = $value.

Cytat(everth @ 27.07.2010, 14:58:52 ) *
Poza tym po to są pola public i private żeby stosować je z rozmysłem.

Jak już wcześniej pisałem: nie używam pól publicznych. Nie widzę takowej potrzeby. Wolę nadać polu widoczność chronioną i dopisać odpowiedni getter. Podaj może przykład, w którym lepiej byłoby zastosować składową publiczną w miejsce protected + getter.
Go to the top of the page
+Quote Post
everth
post
Post #56





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Co do tablicy, to odpuszczam, kwestia przyzwyczajenia. Co do metod publicznych - poza niewygodą dopisywania dodatkowych funkcji i być może narzutem na wydajność - również odpuszczam (w C++ też robię tak jak ty). Tak więc zgoda, obie metody mają swoje wady i zalety a dla mnie to jak dyskusja o wyższości świąt bożego narodzenia nad świętami wielkiej nocy.
Go to the top of the page
+Quote Post
phpion
post
Post #57





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Masz rację, jest to dyskusja, w której obie strony mają swoje racje. No ale zazwyczaj na tym polegają dyskusje (IMG:style_emoticons/default/smile.gif) gdybyśmy oboje uważali to samo to bez sensu byłoby się nad tym rozwodzić (IMG:style_emoticons/default/winksmiley.jpg)

Jeśli chodzi o niewygodę konieczną z dopisywanie setterów/getterów to się w pełni zgadzam (aczkolwiek np. Netbeans potrafi sobie je wygenerować), również jeśli chodzi o wydajność to też masz rację - takie metody będą zawsze ciut wolniejsze od bezpośredniego odwołania do składowej. No ale moim zdaniem są to minusy, które da się przeżyć jeśli pomyślimy o korzyściach płynących z takiego rozwiązania.

Na tym myślę, że możemy zakończyć dyskusję bo nic więcej nie wymyślimy w tej materii. Kto będzie chciał to sobie przeczyta nasze wypowiedzi i wyrobi sobie własne zdanie. Dzięki za debatę (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
everth
post
Post #58





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Zaciekawiłeś mnie z tym automatem w NetBeans, nie orientujesz się może czy w Eclipse jest dostępne coś takiego? (Aptana albo PDT)
Go to the top of the page
+Quote Post
darko
post
Post #59





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

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


Korzystam z Eclipse Helios Release Build id: 20100617-1415 i brakuje mi tej opcji w menu Source (albo jestem ślepy). Pamiętam, że w Eclipsie dla Javy taka funkcjonalność była (i jest?).
Go to the top of the page
+Quote Post
phpion
post
Post #60





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Niestety chyba nie ma (IMG:style_emoticons/default/sad.gif)
Go to the top of the page
+Quote Post
Crozin
post
Post #61





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

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


Z tego co widzę PDT niestety nie udostępnia czegoś takiego ("czyste" - dla Javy - ma).

Podstawowa zaleta getterów o której tutaj nikt nie wspomniał to:
1) Zapewnienie, że podane dane są poprawne. PHP nie jest językiem, w którym typy mają jakieś większe znaczenie, przez to w pole publiczne można wrzucić dosłownie wszystko
2) Gettery/settery to miejsce, w którym można przed przypisaniem/zwróceniem danych zrobić sporo operacji - czasami dodaje się coś dopiero "później", gdy projekt jest już gotowy. Dzięki temu zew. API obiektu się nie zmienia.
Go to the top of the page
+Quote Post
IceManSpy
post
Post #62





Grupa: Zarejestrowani
Postów: 1 006
Pomógł: 111
Dołączył: 23.07.2010
Skąd: Kraków

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


A mnie zastanawia jedna rzecz odnośnie programowania obiektowego, a konkretnie obsługa bazy danych. Jak to ogólnie wygląda? Np połączenie i wybranie wszystkich wierszy z tabeli? Co takiego?
  1. public function pobierz()
  2. {
  3. $tablica = mysql_query("SELECT * FROM `tabela`");
  4. return $tablica;
  5. }


A jak np robić wyświetlanie wyników w html po pobraniu danych z bazy?
Go to the top of the page
+Quote Post
darko
post
Post #63





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

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


Cytat(IceManSpy @ 29.07.2010, 11:39:13 ) *
A mnie zastanawia jedna rzecz odnośnie programowania obiektowego, a konkretnie obsługa bazy danych. Jak to ogólnie wygląda? Np połączenie i wybranie wszystkich wierszy z tabeli? Co takiego?
  1. public function pobierz()
  2. {
  3. $tablica = mysql_query("SELECT * FROM `tabela`");
  4. return $tablica;
  5. }


A jak np robić wyświetlanie wyników w html po pobraniu danych z bazy?

1. Funkcja mysql_query zwraca zasób, a nie tablicę.
2. Generalnie mechanizm jest prosty: w kontrolerze odwołujesz się do modelu - w odpowiedzi na żądanie użytkownika (wywołanie jakiejś akcji) - wywołujesz odpowiednie metody modelu pobierające dane z bazy, następnie przekazujesz - najczęściej tablicę (z danymi) - do widoku, w którym wyświetlasz po kolei, czy jak tam potrzebujesz pobrane dane.
3. To, co nazywasz obsługą bazy danych to odpowiednia klasa modelu, umożliwiająca - w najprostszej formie - podstawowe operacje CRUD na rekordach. Najczęściej użytym wzorcem modelu DB jest singleton (słusznie czy niesłusznie, osobiście uważam, że powinna istnieć tylko jedna instancja obiektu reprezentującego bazę danych).
Najlepiej podejrzyj jakieś rozwiązania frameworkowe Kohana, klasy z rodziny Zend_Db_XXX. Zastosowane tam rozwiązania są dość czytelne (mam na myśli Zenda, bo z Kohany nie korzystam).
Go to the top of the page
+Quote Post
IceManSpy
post
Post #64





Grupa: Zarejestrowani
Postów: 1 006
Pomógł: 111
Dołączył: 23.07.2010
Skąd: Kraków

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


Cytat(darko @ 29.07.2010, 11:50:05 ) *
1. Funkcja mysql_query zwraca zasób, a nie tablicę.


Faktycznie, zapomniałem, bo na szybko pisałem (IMG:style_emoticons/default/smile.gif) Zaraz sobie pooglądam jak to robi się w zendzie.
Go to the top of the page
+Quote Post
Crozin
post
Post #65





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

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


@Darko:

Fail #1: Model MVC w skrócie: wywołanie Kontrolera -> Kontroler określa, że potrzeba użyć tego Widoku i wrzucić mu ten a ten Model(e) -> odpalenie Widoku. Jak widzisz Kontroler nie pośredniczy w przekazywaniu danych do Widoku - on sam potrafi sobie pobrać co mu jest potrzebne.
Fail #2: Ta myśl o tym, że powinna być tylko jedna instancja obiektu obsługującego bazę danych. No to prosta sytuacja, mamy następujące modele:
  • Aktualności - pobiera aktualności do witryny z naszej lokalnej bazy danych
  • Galeria - pobiera obrazy z naszej lokalnej bazy danych
  • Użytkownik - j/w
  • Użytkownik::zasugerujListęZnajomych - metoda wykorzystuje Facebookowe API i próbuje zwrócić nam sugerowaną listę znajomych danego użytkownika
  • Płatności - nasza aplikacja to np. sklep internetowy z jednym z backendów w postaci aplikacji desktopowej, która operuje na bazie SQLite po czym udostępnia tą bazę na serwerze - tutaj Twoja teza zawodzi po raz pierwszy
  • Magazyn - skoro to sklep, to musimy mieć jakiś magazyn - ale ten znajduje się daleko od nas i musimy się połączyć z jego bazą danych - tutaj Twoja teza zawodzi kolejny raz
To, że w zdecydowanej większości przypadków mamy dokładnie jedną instancję obiektu reprezentującego bazę danych (używanego przez różne Modele) nie oznacza, że tak będzie zawsze. Aplikacji korzystających z dwóch lub więcej baz danych na raz, jako tych lokalnych jest względnie niewiele, ale ot system umożliwiający założenie sobie forum czy bloga (który jest w osobnej bazie) - i już masz konieczność wykorzystania obu baz na niektórych podstronach.

Cytat
Najlepiej podejrzyj jakieś rozwiązania frameworkowe Kohana
Jeżeli zależy Ci na tym by nauczyć się OOP - w kod Kohany v3 nawet nie zaglądaj (musisz się najpierw uodpornić (IMG:style_emoticons/default/biggrin.gif) ).

Ten post edytował Crozin 29.07.2010, 13:08:09
Go to the top of the page
+Quote Post
everth
post
Post #66





Grupa: Zarejestrowani
Postów: 782
Pomógł: 153
Dołączył: 21.07.2010

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


Wczoraj poczytałem o tym MVC i wyszło na to że cały czas stosuję MVP. Człowiek zawsze się uczy. Swoją drogą nie mogę rozgryźć implementacji czystego MVC - czy to jest tak że mamy wiele modeli (za @Crozinem) i wiele widoków (do wyświetlania danych z modelu?), a jeden Kontroler który tym wszystkim zarządza? Ja robiłem to tak że model wyrzucał dane w formie XML a za Widok robiły szablony XSL - Kontroler ograniczał się do selekcji danych z modelu i wyboru szablonu. Dla mnie to MVP, wydaje się zresztą dosyć proste. Czy czyste MVC dałoby tu jakiekolwiek korzyści?
Go to the top of the page
+Quote Post
darko
post
Post #67





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

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


Cytat(Crozin @ 29.07.2010, 14:07:01 ) *
@Darko:

Fail #1: Model MVC w skrócie: wywołanie Kontrolera -> Kontroler określa, że potrzeba użyć tego Widoku i wrzucić mu ten a ten Model(e) -> odpalenie Widoku. Jak widzisz Kontroler nie pośredniczy w przekazywaniu danych do Widoku - on sam potrafi sobie pobrać co mu jest potrzebne.

Taaaak, w idealnej implementacji, która nie istnieje powinien zostać zaimplementowany wzorzec obserwator i widoki powinny się same uaktualniać przy zmianie danych. To wiemy. Niestety praktyka, zwłaszcza frameworkowa oraz specyfika protokołu HTTP uniemożliwiają taką "najbliższą ideałowi" (którego nie ma!) implementację mvc i nie ma co udawać, że jest inaczej (IMG:style_emoticons/default/biggrin.gif) Oczywiście, że sam kontroler fizycznie nie przekazuje danych z modelu do widoku, jednak to w nim deklarujemy tę operację:
przykład a'la ZF:
// kontroler
public function xyzAction()
{
// przekazanie danych do widoku (w kontrolerze z modelu sic!)
$this->view->sth = $this->MyModel->getSth();
}
// (...)

// widok:
// xyz.phtml
<!-- (...) -->
<?php
if($this->sth):
foreach($this->sth as $test):
echo $test->x . '<br/>' . $test->y . '<br/>' . $test->z;
endforeach;
endif;
?>

Cytat(Crozin @ 29.07.2010, 14:07:01 ) *
Fail #2: Ta myśl o tym, że powinna być tylko jedna instancja obiektu obsługującego bazę danych. No to prosta sytuacja, mamy następujące modele:
  • Aktualności - pobiera aktualności do witryny z naszej lokalnej bazy danych
  • Galeria - pobiera obrazy z naszej lokalnej bazy danych
  • Użytkownik - j/w
  • Użytkownik::zasugerujListęZnajomych - metoda wykorzystuje Facebookowe API i próbuje zwrócić nam sugerowaną listę znajomych danego użytkownika
  • Płatności - nasza aplikacja to np. sklep internetowy z jednym z backendów w postaci aplikacji desktopowej, która operuje na bazie SQLite po czym udostępnia tą bazę na serwerze - tutaj Twoja teza zawodzi po raz pierwszy
  • Magazyn - skoro to sklep, to musimy mieć jakiś magazyn - ale ten znajduje się daleko od nas i musimy się połączyć z jego bazą danych - tutaj Twoja teza zawodzi kolejny raz
To, że w zdecydowanej większości przypadków mamy dokładnie jedną instancję obiektu reprezentującego bazę danych (używanego przez różne Modele) nie oznacza, że tak będzie zawsze. Aplikacji korzystających z dwóch lub więcej baz danych na raz, jako tych lokalnych jest względnie niewiele, ale ot system umożliwiający założenie sobie forum czy bloga (który jest w osobnej bazie) - i już masz konieczność wykorzystania obu baz na niektórych podstronach.

Jeżeli zależy Ci na tym by nauczyć się OOP - w kod Kohany v3 nawet nie zaglądaj (musisz się najpierw uodpornić (IMG:style_emoticons/default/biggrin.gif) ).

Albo ja czegoś nie rozumiem, albo Ty. Nie napisałem nigdzie, że zawsze musi być jedna instancja bazy danych i uparcie będę twierdził, że - nawet jeśli zdefiniujemy różne dane konfiguracyjne - to i tak powinniśmy mieć możliwość - przy zastosowaniu jednej instancji obiektu bazy danych - "przełączania się" pomiędzy bazami (patrz np. Zend_Application_Resource_Multidb). Tylko dlaczego mieszać kwestię komunikacji z zewnętrznym źródłem danych poprzez wspomniane FB API z modelem DB? Przecież w jakimś innym modelu obsłużysz sobie bez problemu dane z facebooka, z bazą danych nie ma to nic wspólnego, dopóki nie będziesz musiał na tych danych operować, gromadzić je w swojej bazie danych, ale i tu rozwiązanie jest proste - napisanie/użycie odpowiedniego modelu korzystającego z FB API i pobierającego dane. Oczywiście możesz napisać sobie własny pseudo-adapter, w którym będziesz symulować implementację np. metody pobierającej dane - select() gdzie zaimplementujesz pobieranie danych z FB. Grunt, to dostosować się do interfejsu. Dążę do tego, że w przypadku, kiedy mamy wiele źródeł z których pochodzą dane, możemy - trzymając się nadal koncepcji jednej instancji DB - implementować własne adaptery i przełączać się pomiędzy nimi, korzystając z jednolitego interfejsu. W ten sposób mamy możliwość rozróżniania źródła pochodzenia danych. Myślę, że jest to wykonalne.

// edit
można też wykorzystać factory do dynamicznego tworzenia obiektów DB dla poszczególnych źródeł pochodzenia danych.

Ten post edytował darko 29.07.2010, 14:24:55
Go to the top of the page
+Quote Post
Crozin
post
Post #68





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

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


Cytat
Taaaak, w idealnej implementacji, która nie istnieje
Istnieje, istnieje. MVC to nie jest jakaś "niepoznana prawda" tylko konkretny opis jak wykonać dane zadanie. Jednak jak słusznie zauważyłeś w środowisku HTTP nie da się jej zaimplementować (model nie może powiadomić widoku (w sensie tego co jest już wyświetlane użytkownikowi) o zmianie swojego status) - o to się czepiać nie będę (chociaż IMO to już kwalifikuje to skreślenia nazwy MVC na rzecz jakiegoś "passive-view-MVC")

Cytat
Oczywiście, że sam kontroler fizycznie nie przekazuje danych z modelu do widoku
Problem w tym, że to co pokazałeś w listingu poniżej tego cytatu to przekazanie danych do widoku przez kontroler z modelu. A kontroler powinien przekazać do widoku tylko model. Ale to jeszcze jest do przeżycia... najgorsze jest to, że uprościłeś: Widoku = szablon (czy to HTML czy PDF to bez znaczenia). A to widok jest odpowiedzialny za całą logikę widoku (sortowanie po kolumnach, paginacja itp.) by na końcu dopiero odpalić sobie jakiś szablon i go wyświetlić.

To co pokazałeś ma naprawdę niewiele wspólnego z MVC. To nie jest coś gorszego... to jest coś innego.

W jakimś innym wątku bodajże Zyx całkiem fajnie opisał to.

Cytat
Albo ja czegoś nie rozumiem, albo Ty. (...)
A tutaj widzę że doszło do małego nieporozumienia.
Cytat
Najczęściej użytym wzorcem modelu DB jest singleton (słusznie czy niesłusznie, osobiście uważam, że powinna istnieć tylko jedna instancja obiektu reprezentującego bazę danych).
Pisząc coś takiego sugerujesz zrobienie czegoś takiego:
  1. class Database {
  2. protected __construct() {
  3. $this->db = new PDO();
  4. }
  5. // implementacja Singletona
  6. }
A jak rozumiem chodziło Ci o coś takiego:
  1. class DbManager {
  2. protected $instances = array();
  3.  
  4. addInstance($name, Database $db) { $this->instances[$name] = $db; }
  5. getInstance($name) { return $this->instances[$name]; }
  6.  
  7. // TUTAJ implementacja singletona
  8. }
  9.  
  10. class Database {
  11. public function __construct() {
  12. ///..
  13. }
  14. }
W takim przypadku użycie Singletona jest może nie tyle co wskazane co dopuszczalne i przede wszystkim sensowne.

Jednak co do drugiej części to nie możesz zakazać istnienia takiego modelu:
  1. public function retrieveFriends($id) {
  2. return $this->facebookAPI->getFriendsOf($id); // FB API
  3. }
  4.  
  5. public function retrieveOne($id) {
  6. return $this->db->select()->where('id', $id); // Lokalna baza
  7. }
  8.  
  9. public function retrieveSth($id, $def) {
  10. return $this->db['remote']->select()->where('id', $id)->where('def', $def); // Jakaś baza na innym serwerze
  11. }
Zrobiłeś jeszcze chyba jeden błąd (nie mam teraz czasu czytać jeszcze raz) - uprościłeś: 1 model = 1 tabela w bazie. A to nie prawda. Model ma sobą obejmować jakieś dane, które niekoniecznie muszą obejmować jedną tabelę.
Go to the top of the page
+Quote Post
darko
post
Post #69





Grupa: Zarejestrowani
Postów: 2 885
Pomógł: 463
Dołączył: 3.10.2009
Skąd: Wrocław

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


Cytat(Crozin @ 29.07.2010, 15:38:40 ) *
Istnieje, istnieje. MVC to nie jest jakaś "niepoznana prawda" tylko konkretny opis jak wykonać dane zadanie. Jednak jak słusznie zauważyłeś w środowisku HTTP nie da się jej zaimplementować (model nie może powiadomić widoku (w sensie tego co jest już wyświetlane użytkownikowi) o zmianie swojego status) - o to się czepiać nie będę (chociaż IMO to już kwalifikuje to skreślenia nazwy MVC na rzecz jakiegoś "passive-view-MVC")


Jak sam zaznaczyłeś istnieją opisy koncepcyjne, jednak modelowej i jedynej słusznej implementacji MVC nie ma i, uważam, że nie będzie.

Cytat(Crozin @ 29.07.2010, 15:38:40 ) *
Problem w tym, że to co pokazałeś w listingu poniżej tego cytatu to przekazanie danych do widoku przez kontroler z modelu. A kontroler powinien przekazać do widoku tylko model. Ale to jeszcze jest do przeżycia...

Masz rację, powinienem przekazać cały obiekt, zamiast tego, co zwróci metoda:
  1. $this->view->sth = new MyModel();


Cytat(Crozin @ 29.07.2010, 15:38:40 ) *
najgorsze jest to, że uprościłeś: Widoku = szablon (czy to HTML czy PDF to bez znaczenia). A to widok jest odpowiedzialny za całą logikę widoku (sortowanie po kolumnach, paginacja itp.) by na końcu dopiero odpalić sobie jakiś szablon i go wyświetlić.


Gdzie? W którym miejscu tak napisałem? (IMG:style_emoticons/default/smile.gif)


Cytat(Crozin @ 29.07.2010, 15:38:40 ) *
To co pokazałeś ma naprawdę niewiele wspólnego z MVC. To nie jest coś gorszego... to jest coś innego.
(...)
Jednak co do drugiej części to nie możesz zakazać istnienia takiego modelu:
  1. public function retrieveFriends($id) {
  2. return $this->facebookAPI->getFriendsOf($id); // FB API
  3. }
  4.  
  5. public function retrieveOne($id) {
  6. return $this->db->select()->where('id', $id); // Lokalna baza
  7. }
  8.  
  9. public function retrieveSth($id, $def) {
  10. return $this->db['remote']->select()->where('id', $id)->where('def', $def); // Jakaś baza na innym serwerze
  11. }


Nie mogę niczego i nikomu zakazać, to nie dyktatura. Na szczęście żyjemy w wolnym kraju (IMG:style_emoticons/default/tongue.gif)

Cytat(Crozin @ 29.07.2010, 15:38:40 ) *
Zrobiłeś jeszcze chyba jeden błąd (nie mam teraz czasu czytać jeszcze raz) - uprościłeś: 1 model = 1 tabela w bazie. A to nie prawda. Model ma sobą obejmować jakieś dane, które niekoniecznie muszą obejmować jedną tabelę.

Spytam ponownie: gdzie? W którym miejscu tak napisałem? (IMG:style_emoticons/default/smile.gif) Miałem na myśli 1 model == 1 baza danych (+ dane konfiguracyjne) == 1 źródło pochodzenia danych, czyli osobny model dla bazy lokalnej, osobny dla zdalnej i osobny do komunikacji poprzez Facebook API.
Go to the top of the page
+Quote Post
Crozin
post
Post #70





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

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


Cytat
Jak sam zaznaczyłeś istnieją opisy koncepcyjne, jednak modelowej i jedynej słusznej implementacji MVC nie ma i, uważam, że nie będzie.
Koncepcja jest jedna i dobrze opisania. Jedynie na potrzeby WWW (ograniczenia HTTP) usuwa się z niej jeden element: komunikację model ---> widok.

I proszę, przykładowa implementacja MVC z pominięciem powyższego element:
index.php: http://ideone.com/hrPUz
list-template.php: http://ideone.com/gHrjk
table-template.php: http://ideone.com/E9LAW
pagination-partial.php: http://ideone.com/Rg82I

Cały kod kontrolera wyświetlającego tabelkę z użytkownikami, którą można sortować oraz jest ona podzielona na strony:
  1. class MembersController {
  2. public function listAction() {
  3. $view = new TableView();
  4. $view->setModel(new MembersModel());
  5.  
  6. return $view;
  7. }
  8. }
Z racji na to, że interfejs przeglądania tabeli jest rozwnięciem interfejsu przeglądania listy zamiana w powyższym kodzie TableView na ListView spowoduje, że użytkownicy wyświetlą się w formie listy, nie tabeli. Chcesz dodać możliwość wyświetlania aktualności w formie tabelki? Wystarczy dodać do modelu NewsModel implementację interfejsu BrowseTableInterface, czyli notabede:
  1. public function getColumns() {
  2. return array('id', 'title', 'content');
  3. }
I już możesz wyświetlać aktualności w formie tabelki. Chcesz by tą tabelkę dało się sortować? Wystarczy dodać interfejs SortableInterface i już.

Cytat
Gdzie? W którym miejscu tak napisałem?

O tutaj:
  1. // widok:
  2. // xyz.phtml
  3. <!-- (...) -->
  4. <?php
  5. if($this->sth):
  6. foreach($this->sth as $test):
  7. echo $test->x . '<br/>' . $test->y . '<br/>' . $test->z;
  8. endforeach;
  9. endif;
  10. ?>
Cytat
Miałem na myśli 1 model == 1 baza danych (+ dane konfiguracyjne) == 1 źródło pochodzenia danych, czyli osobny model dla bazy lokalnej, osobny dla zdalnej i osobny do komunikacji poprzez Facebook API.
No to znowu źle robisz. Interfejs modelu ma kompletnie niezwiązany z wewnętrzną pracą modelu. Ty musiałbyś zrobić dwa modele: MemberModelUsingLocalDatabase, MemberModelUsingFacebookAPI (to jakie one nazwy będą miały nie ma znaczenia).

Ten post edytował Crozin 29.07.2010, 18:37:07
Go to the top of the page
+Quote Post
phpion
post
Post #71





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Ja mam pytanko: wychodząc z założenia, że w kontrolerze przekazuję do widoku obiekt modelu, a dopiero w widoku pobieram z niego dane to co w przypadku, gdy będzie konieczna jakaś zmiana w parametrach wywoływanej metody modelu? Wówczas konieczna byłaby zmiana wywołań w każdym widoku, czy tak? Jeśli tak to przekazując dane bezpośrednio w kontrolerze zmiany nanosimy tylko w nim, a widoki dostają już konkretne dane.
Go to the top of the page
+Quote Post
Crozin
post
Post #72





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

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


Jest 9 rano, czyli od jakiś 26 godzin jestem na nogach - wybacz jeżeli niezbyt ładnie odpowiem. (IMG:style_emoticons/default/winksmiley.jpg)

Tak, jeżeli potrzebujesz zmienić z jakiś powodów argumenty wywołania danej metody, musisz poprawić interfejs, a co za tym idzie wszystkie wywołania danej metody w aplikacji, czyli np. w widokach.
Cytat
Jeśli tak to przekazując dane bezpośrednio w kontrolerze zmiany nanosimy tylko w nim, a widoki dostają już konkretne dane.
Ale cała idea polega na tym, że widok nie dostaje danych tylko je sobie sam bierze. Dzięki temu jest on w stanie samodzielnie zadecydować co chcesz wziąć.
Go to the top of the page
+Quote Post

4 Stron V   1 2 3 > » 
Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 18.10.2025 - 11:51