![]() |
![]() |
![]()
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ć? |
|
|
![]() |
![]()
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:
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 |
|
|
![]()
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)
|
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 157 Pomógł: 0 Dołączył: 11.07.2009 Skąd: root Ostrzeżenie: (10%) ![]() ![]() |
To ja się podepnę: Do czego można wykorzystać konstruktor? Jak i kiedy z niego korzystać?
|
|
|
![]()
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:
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. |
|
|
![]()
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.
|
|
|
![]()
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?
|
|
|
![]()
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. |
|
|
![]()
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.
|
|
|
![]()
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 |
|
|
![]()
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. |
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 157 Pomógł: 0 Dołączył: 11.07.2009 Skąd: root Ostrzeżenie: (10%) ![]() ![]() |
Czemu strzałeczki, a nie kropki? Tak samo jak: czemu kropki a nie znak plusa?
(IMG:style_emoticons/default/winksmiley.jpg) |
|
|
![]()
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? |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 48 Pomógł: 3 Dołączył: 7.12.2007 Ostrzeżenie: (0%) ![]() ![]() |
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:
Teraz pytanie z mojej strony, raczej z czystej ciekawości bardziej niż z potrzeby odpowiedzi: Do czego najczęściej używacie destruktorów? |
|
|
![]()
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.
|
|
|
![]()
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?
|
|
|
![]()
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.
|
|
|
![]()
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.
|
|
|
![]()
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?
Ten post edytował Zagiewa 28.06.2010, 12:08:37 |
|
|
![]()
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.
|
|
|
![]()
Post
#21
|
|
Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
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. |
|
|
![]()
Post
#22
|
|
Grupa: Zarejestrowani Postów: 48 Pomógł: 3 Dołączył: 7.12.2007 Ostrzeżenie: (0%) ![]() ![]() |
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:
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 |
|
|
![]()
Post
#23
|
|
Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
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. |
|
|
![]()
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:
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 |
|
|
![]()
Post
#25
|
|
Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
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ś: 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. |
|
|
![]()
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.
|
|
|
![]()
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ę:
|
|
|
![]()
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. |
|
|
![]()
Post
#29
|
|
Grupa: Zarejestrowani Postów: 48 Pomógł: 3 Dołączył: 7.12.2007 Ostrzeżenie: (0%) ![]() ![]() |
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 |
|
|
![]()
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:
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 |
|
|
![]()
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:
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 |
|
|
![]()
Post
#32
|
|
Grupa: Zarejestrowani Postów: 898 Pomógł: 80 Dołączył: 31.05.2008 Ostrzeżenie: (20%) ![]() ![]() |
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 |
|
|
![]()
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 |
|
|
![]()
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:
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 |
|
|
![]()
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:
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. |
|
|
![]()
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.
|
|
|
![]()
Post
#37
|
|
Grupa: Zarejestrowani Postów: 898 Pomógł: 80 Dołączył: 31.05.2008 Ostrzeżenie: (20%) ![]() ![]() |
IDE jakieś sobie zainstalowałeś? Czu przesiadłeś się na ASPX?
|
|
|
![]()
Post
#38
|
|
Grupa: Zarejestrowani Postów: 95 Pomógł: 7 Dołączył: 16.07.2007 Skąd: Gorzów Wielkopolski 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 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) |
|
|
![]()
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.
|
|
|
![]()
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.
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) . |
|
|
![]()
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ść) |
|
|
![]()
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)
|
|
|
![]()
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).
|
|
|
![]()
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.
|
|
|
![]()
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). |
|
|
![]()
Post
#46
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 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. 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. @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. |
|
|
![]()
Post
#47
|
|
Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
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:
Czy wg Ciebie przekazanie 3 parametrów do metody render() jest błędne? 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. 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. |
|
|
![]()
Post
#48
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław 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? Polecam, tania i warta swej ceny, ale raczej dla średnio-zaawansowanych i zaawansowanych. |
|
|
![]()
Post
#49
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) ![]() ![]() |
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:
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. |
|
|
![]()
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. |
|
|
![]()
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).
|
|
|
![]()
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. |
|
|
![]()
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ć.
|
|
|
![]()
Post
#54
|
|
Grupa: Zarejestrowani Postów: 782 Pomógł: 153 Dołączył: 21.07.2010 Ostrzeżenie: (0%) ![]() ![]() |
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. |
|
|
![]()
Post
#55
|
|
Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
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. 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. |
|
|
![]()
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.
|
|
|
![]()
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) |
|
|
![]()
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)
|
|
|
![]()
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?).
|
|
|
![]()
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)
|
|
|
![]()
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. |
|
|
![]()
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?
A jak np robić wyświetlanie wyników w html po pobraniu danych z bazy? |
|
|
![]()
Post
#63
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław 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?
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). |
|
|
![]()
Post
#64
|
|
Grupa: Zarejestrowani Postów: 1 006 Pomógł: 111 Dołączył: 23.07.2010 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
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. |
|
|
![]()
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:
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 |
|
|
![]()
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?
|
|
|
![]()
Post
#67
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław 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. 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; ?> 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:
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 |
|
|
![]()
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:A jak rozumiem chodziło Ci o coś takiego: 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: 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ę. |
|
|
![]()
Post
#69
|
|
Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
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. 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:
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) 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:
Nie mogę niczego i nikomu zakazać, to nie dyktatura. Na szczęście żyjemy w wolnym kraju (IMG:style_emoticons/default/tongue.gif) 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. |
|
|
![]()
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: 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: 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:
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 |
|
|
![]()
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.
|
|
|
![]()
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ąć.
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 18.10.2025 - 11:51 |