Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wywołanie obiektu w obiekcie.. z zewnątrz - problem
Forum PHP.pl > Forum > PHP > Object-oriented programming
japolak
Witam.. mam taki kod:

fragment pliku strona.php:
  1.  
  2.  
  3. class strona {
  4. public $tytul;
  5. public $zawartosc;
  6.  
  7. public function __set($nazwa,$wartosc)
  8. {
  9. $this->$nazwa=$wartosc;
  10. }
  11.  
  12. public function wzor_obranowania(){?>
  13. echo$this->tytul;
  14. echo $this->zawartosc;
  15.  
  16. }
  17.  
  18. public function wyswietl_dodaj_karte()
  19. {
  20.  
  21. .... costam....
  22. }
  23.  
  24. }
  25.  



nastepny plik wywolujacy obiekty z klasy (fragment):

  1.  
  2. $wyswietl= new strona();
  3.  
  4. $wyswietl->wyswietl();
  5. echo"<br>";
  6. $wyswietl->tytul="Rejestracja nowego klienta";
  7. $wyswietl->zawartosc=wyswietl_dodaj_karte();
  8. $wyswietl->wzor_obranowania();
  9.  
  10.  
  11.  
  12. $wyswietl->wyswietl_stopke();
  13.  
  14.  



i wyskakuje mi error:
Fatal error: Call to undefined function wyswietl_dodaj_karte() in C:\xampp\htdocs\praca_inz\test.php on line 7

co jest nie tak?? jak zrobic aby funkcja wzor_obranowania byla elastyczna i mogla w sobie wyswietlac tez inne fukcje..
thek
Podstawy obiektówki. Zauważ, że funkcja jaka wywala błąd jest wewnątrz definicji klasy strona, przez co musi być wywoływana poprzez obiekt tejże klasy. A skoro tak jest to wywołuj ją prawidłowo, czyli
  1. $wyswietl->wyswietl_dodaj_karte();

Bo chyba nie chodzi Ci o wariacje w stylu:
  1. $wyswietl->zawartosc = $wyswietl->wyswietl_dodaj_karte();

EDIT: oczywiście to są moje domysły bo kompletnie nie wiem co metoda wyswietl_dodaj_kartę() robi. Dla mnie jest zapewne widokiem jakimś, ale to tylko moje przypuszczenia...
japolak
Cytat(thek @ 5.11.2009, 22:54:13 ) *
Podstawy obiektówki. Zauważ, że funkcja jaka wywala błąd jest wewnątrz definicji klasy strona, przez co musi być wywoływana poprzez obiekt tejże klasy. A skoro tak jest to wywołuj ją prawidłowo, czyli
  1. $wyswietl->wyswietl_dodaj_karte();

Bo chyba nie chodzi Ci o wariacje w stylu:
  1. $wyswietl->zawartosc = $wyswietl->wyswietl_dodaj_karte();

EDIT: oczywiście to są moje domysły bo kompletnie nie wiem co metoda wyswietl_dodaj_kartę() robi. Dla mnie jest zapewne widokiem jakimś, ale to tylko moje przypuszczenia...


codzi mi konkretnie o to ze w metodzie wzor_obranowania znajduje sie tabela
a ja chce jeszcze w wybrane komórki tabeli umiescic inne obiekty.. inne metody..


Cytat
1.
$wyswietl->zawartosc = $wyswietl->wyswietl_dodaj_karte();


to sprawia iż obiekt wyswietl_dodaj_karte wyswietla mi sie calkowicie nad obiektem wzor obramowania.. a chce aby znajdowal sie wewnatrz tabeli ktora obiekt wzor oprogramowania tworzy..
thek
Twoim problemem jest to, że wszystko masz w jednej klasie i nie widzisz co jest czym. Gubisz się między modelem, kontrolerem i widokiem. Widok to wzor_obranowania() i jego nawet nie tykaj. To co masz zrobić z zawartością definiujesz wewnątrz metody wyswietl_dodaj_karte() i wywołujesz ją z odpowiednimi parametrami lub używasz $this jeśli tylko zapisujesz do zmiennej $zawartość poprzez $wyswietl->wyswietl_dodaj_karte($parametry), ale broń boże nie wyświetlasz tego co robi! Od tego masz metodę widoku wzor_obranowania() bo to ona wyświetla całość tabelki. Podziel sobie kod na logiczniejsze działy jeśli chcesz mieć całość w jednej i zrób bloki kodu, które funkcjonalnie będą równe modelowi, kontrolerowi oraz widokowi/-om. Teraz masz bowiem coś, co jest jednocześnie metodą modelu (kontrolera? ki czort wie co robisz tak naprawdę wewnątrz więc nie mam pojęcia gdzie to wcisnąć), ale jednocześnie ma być widokiem bo wyświetla dane. Tak się nie robi i dlatego masz problem z wciśnięciem tego. Możesz dopisać do zmiennej zawartość efekt tej metody lub nadpisać ją, ale nie tak jak Ty to robisz tylko jak Ci pokazałem w drugim przypadku. Po drodze jednak pewnie zamiast nadpisywać Ci dane - dopisuje je, przez co kod się wewnątrz wydłuża.
japolak

hmm
no dałeś mi teraz do myslenia ..

widać nie dokońca rozumiem reguł obiektowości..

moze zdradze troche wiksza część mojej jednej klasy..>

teoretycznie podzielilem sobie klasy .. na te ktore wyswietlaja jakis teoretycznie statyczny kod.. oraz te ktore pobieraja dane z bazy..

zerknij i oceń.. czy to jest wszystko do kitu.. questionmark.gif

chcialem we wzorze_obramowania . umieszczac sobie w zaleznosci co dana strona ma zawierac odpowiednie "funkcje / obiekty"

moze wiec inaczej zapytam .. jak zrobic aby nie trzeba bylo pisac po sto razy do każdej funkcji w klasie tabelek tylko raz zrobic wzór i wszystko w niego pakować questionmark.gif





  1.  
  2.  
  3.  
  4. class recepcja extends strona
  5.  
  6. {
  7.  
  8. public $naglowek;
  9. public $obiekt;
  10.  
  11.  
  12. protected $przyciski = array ('Recepcja'=>'panel_recepcji.php',
  13. 'Rejestracja karty'=>'dodaj_karte.php',
  14. 'Karnety'=>'pokaz_karnety.php',
  15. 'Formularz dzienny'=>'formularz_dzienny.php',
  16. 'Szukaj'=>'form_szukaj.php',
  17. 'Trenerzy'=>'dyz_trenerow.php',
  18. 'Wyloguj'=>'wyloguj.php' );
  19.  
  20.  
  21. public function wyswietl (){
  22. $this->doctype();
  23. echo "<html>\n<head>\n";
  24. $this->wyswietl_metaznaczki();
  25. $this->wyswietl_tytul();
  26. $this->wyswietl_style();
  27.  
  28. echo"</head>\n<body>\n";
  29. $this->wyswietl_naglowek();
  30.  
  31. $this->wyswietl_menu($this->przyciski);
  32. $sprawdzenie=new logowania();
  33. $sprawdzenie->sprawdz_prawid_uzyt();
  34. echo $this->spawdzenie;
  35. echo $this->zawartosc;
  36.  
  37.  
  38.  
  39. }
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46. protected function wyswietl_menu($przyciski){
  47. echo "<table width = '100%' rules='none' class='all' frame='above' border='1' bgcolor = 'white' cellpadding = '1' cellspacing = '1' >\n";
  48. echo " <tr >\n";
  49.  
  50. //obliczenie wielkości przycisku
  51. $szerokosc = 100/count($przyciski);
  52.  
  53. foreach ($przyciski as $nazwa=>$url)
  54. {
  55. $this->wyswietl_przycisk($szerokosc, $nazwa, $url,
  56. !$this->czy_to_aktualny_url($url));
  57. }
  58. echo " </tr>\n";
  59. echo "</table>\n";
  60. }
  61.  
  62. protected function czy_to_aktualny_url($url){
  63. if(strpos($_SERVER['PHP_SELF'], $url)==false)
  64. {
  65. return false;
  66. }
  67. else
  68. {
  69. return true;
  70. }
  71. }
  72.  
  73. protected function wyswietl_przycisk($szerokosc, $nazwa, $url, $active = true){
  74. if($active)
  75. {
  76. echo "<td width = '".htmlentities($szerokosc)."%'align='center' >
  77.  
  78. <a href = '".htmlentities($url)."' class='nav' ><span class='menu'>$nazwa</span></a></td>";
  79. }
  80. else
  81. {
  82. echo "<td width = '".htmlentities($szerokosc)."%' align='center' style='border-bottom-style: double;'>
  83.  
  84. <span class='menu' >$nazwa</span></td>";
  85. }
  86. }
  87. public function wzor_obranowania(){?>
  88. <table width=100% border =0 cellpadding=0 cellspacing=0><tr><td valign="top" align="left"><img src = "r1.gif" /></td>
  89. <td ><?php echo$this->naglowek;?></td><td valign="top" align="right"><img src = "r2.gif" /></td></tr>
  90. <tr><td></td><td>
  91. <?php
  92. echo$this->obiekt;
  93.  
  94. ?>
  95.  
  96. </td><td ></td></tr>
  97. <tr valign="bottom" align="left" ><td><img src = "r4.gif" /></td><td></td><td valign="bottom" align="right"><img src = "r3.gif" /></td></tr>
  98. </table><?php
  99. }
  100.  
  101. public function wyswietl_dodaj_karte()
  102. {
  103. $sprawdz=new prawid_dane();
  104. $sprawdz->sprawdz_dodaj_karte_onkeyup();
  105. $sprawdz->sprawdz_dodaj_karte_onsubmit();
  106.  
  107.  
  108.  
  109.  
  110. ?>
  111.  
  112.  
  113.  
  114.  
  115.  
  116. <center><h3>Formularz rejestracji nowej karty klienckiej w systemie</h3></center>
  117.  
  118.  
  119. <form
  120. method="post" action="tworz_karte.php"
  121. name="dodaj_karte"
  122. id="basicform"
  123. onSubmit="return sprawdz_form_dodaj_karte(this);" >
  124.  
  125.  
  126. <fieldset>
  127. <label for="nr_karty">Nr karty:</label>
  128. <?php
  129. $nr=new dane();
  130. $nr->nastepny_numer_karty();
  131.  
  132. ?>
  133. </fieldset>
  134.  
  135.  
  136.  
  137.  
  138. <fieldset>
  139. <label for="imie">Imie:</label>
  140. <input
  141. type="text"
  142. name="imie"
  143. id="imie"
  144. onkeyup="sprawdz_imie(this);" />
  145. <span class="hint"> Imie może zawierać tylko znaki polskiego alfabetu, musi być bez spacji oraz składać sie od 3 do 20 liter</span>
  146. </fieldset>
  147.  
  148. <fieldset>
  149. <label for="nazwisko">Nazwisko:</label>
  150. <input
  151. type="text"
  152. name="nazwisko"
  153. id="nazwisko"
  154. onkeyup="sprawdz_nazwisko(this);" />
  155. <span class="hint">Nazwisko musi zaczynać sie i konczyć znakiem polskiego alfabetu, może składac sie z kilku członów oddzielonych "-" lub " " oraz składać sie od 3 do 40 liter</span>
  156. </fieldset>
  157. .......
  158.  
  159.  
  160. ......
  161.  
  162. <input type="submit" name="submit" value="Zapisz" />
  163.  
  164. </form>
  165.  
  166.  
  167. <?php
  168.  
  169. }
  170.  
  171.  
  172.  
  173.  
  174.  
  175. function wyswietl_formularz_dzienny()
  176. {
  177. ?>
  178.  
  179.  
  180. <?php
  181. $pokaz=new dane();
  182. $godzina=date(G);
  183. $id_dnia=date(w);
  184. ....
  185.  
  186. bla bla bla
  187. ......
  188.  
  189. }
  190. }
  191.  
  192. function wyswietl_historia_dzienny_form(){
  193. $sprawdz= new prawid_dane();
  194. $sprawdz->sprawdz_hist();
  195.  
  196. ?>Wyświetl formularz z dnia:
  197. <form
  198. onSubmit="return sprawdz_hist1(this);"
  199. action="formularz_dzienny.php" method="get">
  200. <input name="dzien" type="text" maxlength="2" size="2" /> - <input name="miesiac" type="text" maxlength="2" size="2" /> - <input name="rok" type="text" maxlength="4" size="4" />
  201. <input type="submit" name='submit' value='wyslij'/>
  202. </form>
  203. <?php
  204.  
  205.  
  206. }
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215. function wyswietl_szukaj_karte()
  216. {
  217. ?>
  218. <br />
  219. <table width=100% border =0 cellpadding=0 cellspacing=0><tr><td valign="top" align="left"><img src = "r1.gif" /></td><td >
  220. <center><h3>Wyszukiwarka</h3></center>
  221. </td><td valign="top" align="right"><img src = "r2.gif" /></td></tr>
  222. <tr><td></td><td>
  223. <center><form method="post" action='szukaj.php'>
  224. <table>
  225. <tr>
  226. <td><input type="text" name="wyrazenie"></input> </td>
  227. <td>
  228. <select name="metoda_szukania">
  229. <option value="id_karty">Nr. karty</option>
  230. <option value="imie">Imie</option>
  231. <option value="nazwisko">Nazwisko</option>
  232. <option value="adres">Adres(ulica)</option>
  233. <option value="miasto">Miasto</option>
  234. <option value="kod_pocztowy">Kod pocztowy</option>
  235. <option value="telefon">Telefon</option>
  236.  
  237. </select>
  238.  
  239. </td>
  240. <td><input type="submit" value="szukaj" name="szukaj" /></td>
  241. </tr>
  242.  
  243. </table>
  244. </form></center>
  245. </td><td ></td></tr>
  246. <tr valign="bottom" align="left" ><td><img src = "r4.gif" /></td><td></td><td valign="bottom" align="right"><img src = "r3.gif" /></td></tr>
  247. </table>
  248.  
  249.  
  250.  
  251.  
  252. <?php
  253.  
  254. }
  255.  
  256. function sprawdzanie_nr_karnetu(){
  257. ?>
  258.  
  259.  
  260.  
  261. <script type="text/javascript"><!--
  262.  
  263.  
  264.  
  265. var minlength = '3'; // minimalna ilość znaków
  266. var delay = '1000';// czas do aktywacji sprawdzania. w milisekundach (1 sec = 1000 milisec.)
  267. var divid = 'sprawdz'; // ID of the DIV where response will be shown
  268.  
  269. // czekaj az użytkownik przestanie pisać
  270.  
  271. function czekaj(){
  272. if(window.mytimeout) window.clearTimeout(window.mytimeout);
  273. window.mytimeout = window.setTimeout("sprawdz2()", delay);
  274. return true;
  275. }
  276.  
  277. //sprawdz dostepność przegladarki
  278.  
  279. function sprawdz2() {
  280.  
  281. if (window.XMLHttpRequest) {
  282. http = new XMLHttpRequest();
  283. } else if (window.ActiveXObject) {
  284. http = new ActiveXObject("Microsoft.XMLHTTP");
  285. }
  286.  
  287. handle = document.getElementById('nazwisko');
  288. var url = 'ajax2.php?';
  289. if(handle.value.length > minlength) {
  290.  
  291. // czas dla IE
  292.  
  293. fetch_unix_timestamp = function()
  294. {
  295. return parseInt(new Date().getTime().toString().substring(0, 10))
  296. }
  297.  
  298. var timestamp = fetch_unix_timestamp();
  299.  
  300. var fullurl = url + 'do=sprawdz_nazwisko&nazwisko=' + encodeURIComponent(handle.value) + '&timestamp=' + timestamp;
  301.  
  302. http.open("GET", fullurl, true);
  303. http.send(null);
  304. http.onreadystatechange = zmiana_stanu_nazwiska;
  305. }else{
  306. document.getElementById(divid).innerHTML = '';
  307. }
  308. }
  309.  
  310. // sprawdź nazwisko
  311.  
  312. function zmiana_stanu_nazwiska() {
  313. if (http.readyState == 4) {
  314.  
  315. var html = http.responseText;
  316.  
  317. document.getElementById(divid).innerHTML = html;
  318. }
  319. }
  320. // -->
  321. </script>
  322.  
  323. Szukaj nr. karnetu:
  324. <table width = "300"><tr><td>
  325. <div id="sprawdzanie">
  326.  
  327. <form>
  328. Wpisz nazwisko:
  329.  
  330.  
  331. <input id="nazwisko" onkeyup="czekaj()" name="nazwisko" size="20" type="text" />
  332. </form></div>
  333. <br/>
  334. <div id="sprawdz"></div>
  335.  
  336. </td></tr></table>
  337. <?php
  338.  
  339. }
  340.  
  341.  
[/php]
thek
Jak dla mnie to za bardzo chcesz upychać wszystko do wszystkiego. Zauważ, że większość Twoich metod uparcie chce coś wyświetlać, choć wcale nie jest to konieczne. Niech będzie sobie co chcesz w podziale, ale ustawiaj to osobnymi metodami. Osobna do doctype, osobna do meta, osobna do dodawania css i js, osobna do body. Dopiero w metodzie wyświetlającej całość strony składaj to do kupy. Poza tym uważam, że pisanie wszystkiego w jednej klasie wprowadzi chaos do twojego projektu w pewnym momencie będziesz miał tyle metod, że pogubisz się w ich wywołaniach. Zauważ, że przykładowo zdefiniujesz sobie metodę display() i będzie miała ona gotowy szablon strony. wystarczy, że w jej zmienne "wstrzykniesz" kawałki kodu i wszystko zagra. Jak go podzielisz? Twój wybór. Ale tylko ona jedna ma wpływać na całość. Nie zaś tak, że dostaje wszystko na gotowe. Weź sobie przykładowo sytuację, że obiekt ma do zmiany head i body. To zrób obiektowi funkcje je ustawiające, ale oczekuj określonego formatu i typu, byś mógł je do zmiennej wpisać. Gdy już masz wszystko ustawione, wywołaj metodę display() a wyświetli ci całość. Tymczasem Ty upychasz metodę wyświetlającą mikroskopijną część wyniku po innej metodzie, która też to robi, by ta druga robiła to samo w trzeciej. To nie ma sensu. Metodami ustawiaj tylko zmienne wewnątrz klasy, a tylko jedna powinna wyświetlać. Da ci to coś w stylu:
  1. class Strona {
  2. private $head;
  3. public $title;
  4. private $body;
  5.  
  6. public function setHead($dane) {
  7. $this->head = $dane;
  8. }
  9.  
  10. public function setBody($dane) {
  11. $this->body = $dane;
  12. }
  13.  
  14. public function display() {
  15. echo '<doctype ble...>
  16. <html>
  17. <head>'.$this->head.
  18. '<title>'.$this->title.'</title>
  19. <head>
  20. <body>'.$this->body.'</body>
  21. </html>';
  22. }
  23. }
Oczywiście to baaaaaaaaaardzo okrojona wersja, ponieważ head powinno mieć podział na zmienną title (często zmieniana zmienna), tablicę znaczników meta, tablicę dołączanych arkuszy stylów, tablicę dołączanych skryptów itp, wraz z odpowiednimi metodami. Takie podejście mocno upraszcza nawet późniejsze dziedziczenie.
Bo ostatecznie kończy się to poprzez wywołanie
  1. $wyswietl = new Strona();
  2. $wyswietl -> setHead( $sekcjaHead );
  3. $wyswietl ->title = "Rejestracja nowego klienta";
  4. $wyswietl -> setBody( $co_w_body );
  5. $wyswietl -> display();
Zauważ, że to, co będzie w head i body jest dla mnie obojętne dopóki będzie miało odpowiedni format. Mogę tam wrzucić tablicę, którą mi funkcja display() sama wstawi odpowiednio do szablonu (tak jak zrobiłem z title), albo jako ciąg znakowy jak teraz to mam. Bez mieszania, kombinowania. a jeśli zechcę coś zmienić z wyświetlaniem to po prostu inny display mogę napisać bez modyfikacji czegokolwiek innego. Czyli przechodząc na terminologię MVC -> napisałbym inny widok dla tej klasy smile.gif U Ciebie skończyło by się to poprawianiem kilku metod zapewne.
Co istotniejsze. Dopóki nie wywołam funkcji display, mogę zmieniać nawet setki razy title czy inną część bez wpływu na całość tego co Ci zostanie pokazane. Bo i też jest to cały czas na serwerze tylko. Sekcję body możesz nawet składać. Wystarczy, że przerobisz funkę by zamiast podmiany mogła dodawać dodatkowo. A więc choćby coś w stylu:
  1. public function setBody($dane, $dodanie = FALSE) {
  2. if($dodanie)
  3. $this -> body .= $dane;
  4. else
  5. $this -> body = $dane;
  6. }

EDIT: czemu wspomniałem o trybie dodawania? Bo to świetna baza wyjściowa dla tworzenia modułów. Zrobisz tylko pierwszy w trybie normalnym, a resztę w trybie dodawania i masz budowanie sekcji body z klocków wedle uznania. Najlepiej zaś jeszcze display domyślnie ustalić na jakiś wzorzec i go wypełniać. innymi słowy znacznie bardziej rozbudowany niż mój. Z większą ilością kod html, pomiędzy którymi tylko zmienne wkładamy.
japolak
ok..

Wielkie dzięki za udzielenie wskazówek.
niezmiernie mi sie przydadzą .. teraz troche inaczej na to wszystko patrze;) ...

wiesz ten kod co ci przedstawiłem.. to część mojej pracy inz.

Program mam juz gotowy.. akceptacje promotora tez mam.. ale chcialem sobie kod poukładać jakoś ładniej, zanim oddam do końcowej analizy.. smile.gif bo jak sam zauważyłeś teraz jest zmiksowany bałagan..

tak sie zastanawiam. skorzystać z jakiejś literatury??

myślalem poczytać troche : Php object - oriented solutions. .ale nie wiem czy to dobra pozycja aby zaczynac??
bo to co aktualnie mam wykonane bylo zalążkiem .. z książki : PHP i MySQL. Tworzenie stron WWW. Vademecum profesjonalisty

moze ty znasz jakaś pozycje wartą uwagi??

thek
Szczerze mówiąc, to do PHP nie czytałem żadnych książek drukowanych smile.gif Moja wiedza wynika głównie ze znajomości inżynierii oprogramowania, C++, który jest bardzo podobny, późniejszego wertowania manuala, googlania oraz masy czasu poświęconego na siedzenie w kodzie. Dobry projekt + chęci = 70% sukcesu. Stąd nie mogę polecić konkretnego wydawnictwa. Zwyczajnie szukam rozwiązań na bieżąco gdy mi problem wykoczy. A raczej wyskakują rzadko bo trochę już połamałem zębów na różnych problemach. Podstawą jest i tak dobry algorytm. Nietóre mają już gotowe implementacje, ale większość musisz sam napisać i przemyśleć. Z czasem zaczniesz widzieć rozwiązania dopiero co przedstawionego Ci problemu od razu. To już kwestia doświadczenia i otrzaskania z problemami. Najwyższe stadium "zboczenia programistycznego" to widzieć algorytmy w zdarzeniach codziennych i próbować je zapisać winksmiley.jpg
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.