Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]trudny do opisania problem: markdown i kod php
Forum PHP.pl > Forum > Przedszkole
nowy_pehapowiec
Problem jest tego typu, że treść strony (zawartość jednego DIV) jest pobierana z bazy. I wszystko fajnie, ale dla jednej strony z "mapą strony" ma być generowana dynamicznie. Wszędzie używam markdowna i treść strony obrabiam ta funkcją.
Co poza dodaniem wyjątku dla tej jednej strony mogę zrobić? Jedyne co mi przyszło do głowy to wstawić warunek sprawdzający czy aktualna strona to "mapa strony" i jeśli tak to nie pobieram treści z bazy tylko generuje "mapę strony".
Tylko, że to bardzo nieefektywne i brzydkie rozwiązanie. Jak to inaczej, sprytniej zrobić?

pozdro
vokiel
Rozumiem, że to jakiś CMS jest, tak? Możesz dla każdej strony dodać parametr czy występuje edytor HTML, następnie na podstronie wyświetlać checkbox'a z wyborem. Dodatkowo możesz dodać pole z adresem do skryptu, który wygeneruje treść. Jeśli skrypt zostanie zdefiniowany, to automatycznie wyłączasz pole edycji. Przyda się do innych podstron, które będą generowane automatycznie, lub będą wymagały ręcznego pisania treści (czysty html, css).
Oczywiście te strony inaczej już obrabiasz po zapisaniu takiej strony, bo treści nie przepuszczasz przez parser markdown.
nowy_pehapowiec
Nie chodzi o cms, tylko o zwykłą stronkę. Menu i stopka się nie zmienia. treść jest pobierana z bazy dla każdej podstrony. Tylko, że dla kilku podstron np "mapy strony" to nie jest statyczna treść. I mam problem jak to połączyć. nie chce robić kilku warunków if i sprawdzać czy aktualny adres to "mapa strony" albo jakaś inna dynamiczna treść. Bo wtedy w silniku strony będę miał tez jej treść a to chce mieć rozdzielone. I nie bardzo wiem jak. Masz jakiś pomysł? Ja wymyśliłem tylko, że mógłbym do bazy w kolumnie "treść" dodawać również kod php i jednym warunkiem sprawdzać , czy dane pole zawiera '<?php' i jeśli tak to wykonać ten kod a jeśli nie to przepuścić markdownem. Tylko nie udaje mi się tego kodu wykonać. Potrzebuje zrobić coś w stylu incliude dla plików. Wiesz jak to osiągnąć? A może widzisz jakiś inny, lepszy sposób?

pozdro
Pilsener
Cytat
że dla kilku podstron np "mapy strony" to nie jest statyczna treść
- znam ten problem, jest częsty na amatorskich stronach. Ogólnie postępuje się tak:
- treść statyczna w bazie
- kod php (skryptu) w pliku .php

Jak to zaimplementować? Na wiele sposobów:
- można dodać do bazy kategorii (zakładam że strona zbudowana jest na drzewie kategorii) informację o rodzaju treści i wtedy silnik np. includuje plik zamiast wczytywać treść
- jeśli strona ma budowę typu strona.pl/kategoria/podkategoria to można sprawdzać, czy pod tą lokalizacją nie ma treści dynamicznej (np. pliku treść.php)
- można przemycać nawę pliku w adresie i sprawdzać czy istnieje, np. jak adres jest strona.pl/cos;tam.html to szukamy pliku cos;tam.php (kwestia zakodowania odpowiedniej nazwy pliku) i jeśli istnieje, to go includujemy zamiast treści z bazy
- inny sposób? Na pewno istnieje

Profesjonalnie postępuje się tak, że przechowuje się w cache/bazie informację o zainstalowanych dla danej kategorii skryptach/modułach etc i ścieżkach do ich kodu źródłowego, w PA tych skryptów lub ręcznie określa się nazwy zmiennych, które są dodawane do widoku (najczęściej po prostu są dodawane do już istniejącej tablicy), następnie pozostaje ich użyć w szablonach.
nowy_pehapowiec
Dzięki za cenną odpowiedź!

Nie jestem profesjonalista ale hobbystą, mimo to wolałbym korzystać z lepszych rozwiązań. Na pewno nie chce korzystać z plików. Przy kilku stronach to nie problem ale przy większej ilości to chyba nie może być wygodne? Czy mógłbyś nieco rozwinąć swą myśl o profesjonalnych sposobach? Bo nie do końca zrozumiałem a bardzo mnie to interesuje.

pozdro
Pilsener
Kod PHP trzyma się w plikach, a nie w bazie. Sposoby profesjonalne są w sumie proste:
- dodajesz moduł/rozszerzenie/skrypt poprzez PA, gdzie go opisujesz, wskazujesz ścieżkę do pliku w kodzie źródłowym etc, wtedy pojawia się on w tabeli "moduły" i na listach dodatków, których można użyć
- dla wybranej kategorii/strony dodajesz wybrany moduł (wykonywanie kodu modułu zawsze jest nieoptymalne)
- pozostaje wyedytować szablon, z którego dana strona korzysta i dodać do niego odpowiednią zmienną/zmienne, nazwę zmiennej można ustawić w PA, w module powinno to wyglądać jakoś tak:
  1. $widok[$zmienna] = $tresc;
- do tabeli "widok", która przechowuje treść strony dodawane są nowe elementy o nazwie zdefiniowanej przez użytkownika. Potem wystarczy tylko w templacie dać:
  1. <div id="prawa_kol">
  2. <p>
  3. {PROGNOZA_POGODY}
  4. </p>
  5. </div>
- jeśli np. nasz skrypt/moduł to prognoza pogody
nowy_pehapowiec
Bardzo Ci dziękuję. Choć niewiele z tego zrozumiałem. Chyba tylko tyle, że jednak kod php mam mieć w plikach smile.gif Może mógłbyś mi wskazać jakąś książkę albo stronę gdzie jest to opisane, szczególnie te templaty?

Mam bazę danych a w niej jest główną tabela( z między innym) kolumnami: id, adres, widok, treść. W przeglądarce wywołana jest strona o danym adresie. Pobieram odpowiedni rekord z bazy. I co dalej? Zgaduje, że ten "widok" to właśnie ma być skrypt php w osobnym pliku. Nie jednak nic nie zrozumiałem ...

pozdrawiam

questionmark.gif
Pilsener
Dla podanego adresu, np. strona.pl/filmy/sensacyjne/zabili;go;i;uciekl.html musi zostać pobrany:
1. Szablon, który będzie użyty
2. Elementy strony, czyli:
- meta dane
- pliki css
- treść, która może pochodzić z wielu modułów

W szablonie "spotykają" się wszystkie zmienne tworząc gotową stronę. Oczywiście jeśli w szablonie mamy:
  1. <div>
  2. {pogoda}
  3. </div>
- to zmienna "pogoda" może korzystać z własnych szablonów (i tak prawdopodobnie jest w panelu konfiguracyjnym modułu "pogoda"), podobnie będzie u Ciebie, musisz:
- pobrać treść z bazy
- połączyć ją z kodem html
- użyć w szablonie strony
nowy_pehapowiec
Już trochę zaczynam rozumieć! index.php to tylko taki sterownik, który w zależności od adresu ma pobrać coś z bazy i z plików i wywołać jakąś funkcje która to poskłada, ale sam ma tego nie robić. Tak? Nie rozumiem jednak tej treści pochodzącej z wielu modułów. Myślałem, że dla danej strony mam jakieś pole w bazie z jej treścią i to jest cała treść. Czy ten moduły to są powtarzające się na kilku stronach treści np menu?

Napisze co na razie zrobiłem i co działa. Mam w tabeli głównej powiedzmy takie kolumny: tytul-meta ,opis-meta,slowa-meta, plik-css, tresc. W pliku index.php pobieram plik z szablonem. W tym szablonie podmieniam podmieniam {$tresc} i {$tytul-meta}, {$opis-meta}, {$slowa-meta}, {$plik-css} na dane jakie pobrałem z bazy. Te podmiany są robione przez funkcje wywoływaną w pliku index.php - czy to może tak być? Dla wszystkich strona gdzie treść nie jest jakoś złożona (tylko jest wprost zapisana w bazie) mam ten jeden szablon. Ale nadal mam problem z "mapą strony". Sprawdzam IP i zamiast treści z bazy do szablony dodaje wynik z funkcji generującej mapę strony(generuje listę html z odpowiednimi elementami - może tak być?). Czyli coś musiałem źle zrobić, bo efekt jest taki sam jak bez użycia szablonu - też trzeba IF sprawdzić, a kodu jest dużo więcej i na pewno działa wolniej. O co chodzi z tymi modułami? Bo to chyba jest w tym najważniejsze. I czy ten cały system szablonów może być robiony bez programowania obiektowego? Bo ja właśnie tak zrobiłem.


pozdro
Pilsener
Cytat
Czy ten moduły to są powtarzające się na kilku stronach treści np menu?
- tak, są to skrypty, generujące różne zmienne, które mamy potem dostępne w widoku i możemy ich użyć w szablonie, np. do szablonu dodajemy tablicę "widok":
  1. $widok['menu'] = 'kod html menu';
  2. $widok['pogoda'] = 'kod html prognozy pogody'
- zmiennych tych możemy mieć dowolną ilość i mogą one pochodzić z dowolnych modułów. W każdej chwili możemy dodać do widoku nową zmienną lub tablicę zmiennych (metoda np. add obsługująca szablon powinna obsługiwać array_merge)

Cytat
I czy ten cały system szablonów może być robiony bez programowania obiektowego?
- może, zamiast klas używamy sekcji a zamiast metod funkcji winksmiley.jpg

Skup się na wygenerowaniu odpowiednich zmiennych stanowiących stronę, każda zmienna i grupa zmiennych to oddzielny proces:
- zmienne systemowe (takie jak np. nazwa strony, adres główny, rodzaj protokołu)
- zmienne meta
- menu strony
- szablon strony
- pliki css
- zmienne z poszczególnych modułów

Do utworzenia każdej z tych zmiennych/grup zmiennych wydziel kod, podziel to jakoś wg funkcji a nie będziesz miał problemów.
nowy_pehapowiec
W ogóle to wcześniej pisałem strony w taki sposób:
http://www.kess.snug.pl/?sid=10&pid=23
i dla prostych stron dużo lepiej mi się to sprawdzało. Ale przy większych ilość warunków i wynikające stąd ograniczenia są już duże
Pilsener
Ten sposób odrzuć czym prędzej, bo jest przestarzały i ma liczne ograniczenia, przede wszystkim strona to CAŁOŚĆ i logiczna zasada jest taka:
- najpierw przygotuj stronę, dopiero potem wysyłaj ją do przeglądarki
Echowanie po kawałku nie ma sensu (choćby ze względu na wydajność), bo co, gdy np. w stopce będzie jakiś błąd? Każesz przeglądarce "zwrócić" to, co wyechowałeś? Zauważ, że kolejność tworzenia elementów strony nie powinna mieć znaczenia, w każdej chwili możesz dodać:
  1. $zmienna['footer'] = 'kod htrml stopki';
  2. dodaj_zmienna_do_widoku($zmienna);
- a i tak zmienna ta będzie w szablonie strony dokładnie na tym samym miejscu, możesz równie dobrze zacząć od nagłówka, co od stopki czy menu. I co z obsługą błędów? Gdy podczas generowania stron wystąpi błąd na dowolnym etapie to po prostu zastępujesz szablon strony szablonem błędu a komunikat błędu dodajesz do widoku smile.gif W najprostszej postaci wszystkie błędy wrzucasz do tablicy $error i przed wykonaniem czegokolwiek sprawdzasz, czy tablica błędów nie jest pusta.
nowy_pehapowiec
dzięki Pilsener

No wiem, że ten sposób co podałem jest zły i ograniczony. Ale w sieci jest on dobrze opisany od początku do końca i działa. A to o czym piszesz to taska czarna magia dla mnie. Szczególnie ta obsługa błędów, wszystko fajnie, ale bardzo chciałbym zobaczyć po kolei jak to się robi. Trudno się w tym połapać jeśli się nigdy tego na oczy nie widziało.

pozdro

Czas czas nie mogę przejść jednej rzeczy. Mam w pliku szablon, zaczytuję go do zmiennej. W tej zmiennej podmieniam wszystkie fragmenty treści {$tytul}, {$meta} i inne. Później robię jedno echo i wyświetlam stronę. I faktycznie tak jest dużo fajniej i bardzo się ciesze, że mi to działa. Ale nadal nei wiem co zrobić z tymi treściami które nie są statyczne, np menu generowane z bazy. Poczytałem o smarty, żeby zobaczyć jak to tam jest zrobione. No i tam http://pl.wikibooks.org/wiki/PHP/Smarty zobaczyłem, że zamiast pętli i warunków w języku php są pętle i warunki w języku smarty. Czyli elementy prezentacyjne html są poprzeplatane ze skryptem. A przecież chodziło o to żeby tego uniknąćquestionmark.gif?

Jeszcze mam takie techniczne pytanie, jak działa w smarty
$tpl -> assign('tresc', $tresc);
$tpl -> display('szablon.tpl');
questionmark.gifquestionmark.gif

W pierwszej linijce jest przypisanie treści np z bazy do zmiennej w szablonie. A co w drugiej? czy ten display to po prostu dodanie zmiennych i eval??

Pilsener czy mógłbyś wkleić tutaj kawałki swoich kodów jak Ty to robisz z tymi swoimi szablonami i modułami? Nie tylko mi by to pewnie bardzo pomogło. Pomożesz, bardzo Cię o to proszę?

pozdro

Pilsener
Cytat
Czyli elementy prezentacyjne html są poprzeplatane ze skryptem
- bo system szablonów to pseudo-język, ma to swoje zarówno wady (trzeba się go nauczyć), jak i zalety (można w jednym pliku zawrzeć dość skomplikowany kod HTML).

Ja się w 90% opieram na tym:
http://www.programuj.com/artykuly/www/template.php
Mniej tu chodzi o mechanizm, bardziej o zdroworozsądkowe zasady i czystą wygodę.
Cytat
co zrobić z tymi treściami które nie są statyczne, np menu generowane z bazy
:
1. Generator menu pobiera drzewo z bazy
2. Dodajemy kod HTML korzystając z systemu szablonów
3. Przygotowane menu dodajemy do widoku strony

Oczywiście menu ma panel administracyjny, gdzie możemy decydować o tym, czy element menu to:
  1. <td><tr>{element}</tr></td>

czy:
  1. <li>{element}</li>
nowy_pehapowiec
Jeszcze raz dziękuję za pomoc.

Ten link co podałeś jest świetny! Czy Ty używasz własnego systemu szablonów czy gotowego jednak gotowego?

Nie można nie zauważyć, że zamiast mieszania html z php mieszamy inny język. Czy to nie jest trochę tak jak zamiana siekierki na kijek? Czy zamiast dodawać znaczniki html w szablonie nie lepiej dodać je w osobnej funkcji?

Powiedz mi jeszcze jak według Ciebie lepiej stworzyć taki mały system szablonów, obiektowo czy funkcyjnie? W tym linku co podałeś jest obiektowo i jest fajnie to zrobione, ale czy funkcyjnie dałoby się to zrobić równie prosto a może i prościej, jak myślisz?



pozdro

Pilsener
Najlepiej obiektowo, bo jest to zrozumiałe dla 90% programistów nawet innych języków, obiekt + interfejs jest przyjaźniejszy do implementacji i daje większe możliwości. Ja korzystam z tego systemu, który podałem w linku (w każdym bądź razie bardzo podobnego) lub ze smarty, jeśli prosty system nie wystarcza. Smarty ma wiele wad ale dużo osób go zna i umie używać, ale to ostateczność dla mnie, w zdecydowanej większości przypadków prosty system wystarcza w zupełności.
nowy_pehapowiec
Jednak nie przekonałem się do szablonów. Chyba czegoś nie zrozumiałem, ale bardziej pasuje mi include i eval i okazało się, że nie jestem sam: http://wortal.php.pl/wortal/artykuly/php/b...ajac_do_if_else

pozdro
Pilsener
Po co eval? Dziś wraca się do szablonów opartych o PHP, oto jak to robi Zend Framework:
  1. <h1>Test</h1>
  2. <hr />
  3. <ul>
  4. <?php foreach($this->users as $a):?>
  5. <li>
  6. <?php echo $a->login;?>
  7. </li>
  8. <?php endforeach ?>
  9. </ul>
- jest to fragment pliku z widokiem, zaleta szablonu pozostaje (czyli czytelny kod HTML w jednym miejscu oddzielony od PHP), wadą jest, że trzeba znać PHP i ciężko oprzeć się pokusie, by wsadzić do widoku coś z logiki aplikacji smile.gif Jest to pewnie też szybsze od parsowania różnych templatów.
nowy_pehapowiec
Masz racje eval nie jest potrzebny (kiedyś go używałem ale porzuciłem)
Ja wymyśliłem sobie na własny użytek nieco inny sposób. Mam kilka funkcji dodających kod html do treści, np _table(), _ul() i w kodzie strony tylko jie wywołuje z odpowiednimi argumentami.
np
<?php
echo '...<h1>abc</h1>'.
_ul( $dane_pobrane wcześniej z bazy).
'<p>aaaaa</p>'.
_table( $dane_pobrane wcześniej z bazy2);
?>

Oczywiście dane staram się pobierac w jednym miejscu na samym początku skryptu, ale czasem pobieram je tuż przed wyświetleniem i też jest czytelnie. A napisanie sobie funkcji dodających znaczniki bardzo ułatwia prace i przyśpiesza. Trzeba się troszkę zastanwoić nad różnymi przypadkami, dodać odpowiednie argumenty (zwykle opcjonalne) i jest wygodnie i szybko smile.gif

Nie bardzo wiem jak dodac do takiego "systemu szablonów" obsługę błedów. Np chciałbym, żeby w przypadku błedu wyświetlić na stronei komunikat, że sorry ale wytstapił błąd i nie wszystko przebiegło pomyślnie. Jak to zrobić? Nie hcodzi o błędy php ale o błędy powodowane przez dane. Np tworze liste w oparciu o baze ale w bazie nic nie ma.

Jeszcze jedna rzecz mnie irytuje w takim podejściu. Mam dwa rodzaje stron i powiedzmy, że różnią się tylko stopką i niczym więcej. Czy jest inne wyjście niż napisanie dwóch niemalże identycznych szablonów? Bo if lepiej nie stosowac bo potem łatwo się pogubić jak sie tak miesza. Niby można wspólną cześć wrzucić do pliku i include zrobić w dwóch szablonach i nie będzie fizycznie dwóch prawie identycznych plików. Odpadnie też koniecznosć pamiętania o modyfikacji obu plików. Ale nie jest to zbyt eleganckie. Co zatem zrobić?

Proszę wyjaśnij mi co to jest $a->login chodzi o ten login który nie jest ani funkcją ani zmienna?
Czy wszystkie konstrukcje można kończyć w sposób endkonstrukcja czy tylko foreach, zamias {} używać słów?

pozdro

questionmark.gif?
Pilsener
Błędy kierujesz po prostu do innego szablonu i modyfikujesz lekko widok, tak jak to robię:
  1. if(empty($error)){
  2. $tmpl_id = $cache['tmpl']; //id szablonu pobrany z cache'u strony
  3. }else{ //tu obsługa błędu
  4. unset($tresc); //czyścimy widok
  5. $tmpl_id = 2; //id szablonu z błędem (może być inny np. dla 404)
  6. $tresc['error'] = '<li>'.join("</li><li>",$error).'</li>'; //dodajemy do widoku listę błędów
  7. }


Oczywiście są to błędy typu: brak pliku .cfg, brak bazy, brak strony etc. Błędy poszczególnych modułów (np. brak artykułu) należy wyświetlać na podobnej zasadzie korzystając z szablonu tego modułu.

A co do tego:
Cytat
Czy jest inne wyjście niż napisanie dwóch niemalże identycznych szablonów?
- jest - ja wykorzystuje dziedziczenie, można teraz pójść dwutorowo:
1. Szablon defaultowy jest dziedziczony i dostępny wszędzie, natomiast dla wybranej kategorii typu 1/1.1/1.1.5 ustawiasz szablon x z inną stopką, który może być dziedziczony np. dla kategorii 1/1.1/1.1.5/1.1.5.2 lub nie, zależy jak ustawisz settings tego szablonu - jednak nie jest to optymalne (dublowanie kodu html, gdy zmienisz np. doctype to musisz zmieniać dwa szablony)
2. Lepiej stopkę zaimplementować jako coś, co ja nazywam "panelem" - panele tym się różnią od modułów, że ich treść jest generowana statycznie (są to po prostu fragmenty kodu html). Definiujesz nowy panel, nazywasz go "stopka default", włączasz mu dziedziczenie i includujesz w szablonie głównym jako {stopka}, natomiast dla kategorii x przypisujesz inny panel o tej samej nazwie zmiennej (każdy panel może mieć inną nazwę zmiennej wykorzystywaną w szablonie, w którym jest implementowany) - silnik strony jest tak pomyślany, że ważniejsze są zmienne przypisane bezpośrednio niż odziedziczone, w ten sposób stopka przypisana bezpośrednio nadpisze tą defaultową smile.gif

Cytat
Czy wszystkie konstrukcje można kończyć w sposób endkonstrukcja czy tylko foreach, zamias {} używać słów?
- chodzi tylko o czytelność kodu i wyraźne oddzielenie PHP od HTML tak, aby laik edytujący tylko HTML nie wysypał nam strony smile.gif
nowy_pehapowiec
dzięki za odp!
Pilsener a czy mógłbyś napisać taki przykładowy fragment szablonu z obsługa błędów? Ale tak od początku? Bo zupełnie nie wiem jak to zrobić.

Teraz mam plik index.php i w nim na podstawie adresu pobieram dane z bazy. Potem używam include, żeby dołączyć szablon.php. W uproszczeniu index.php wygląda tak:
Kod
$tresc1 =//tutaj pobieram dane z bazy
$tresc2 =//tutaj pobieram dane z bazy
$tresc3 =//tutaj pobieram dane z bazy
$arkuszcss =//tutaj pobieram dane z bazy
$nazwaszablonu =//tutaj pobieram dane z bazy
include('$nazwaszablonu');

i teraz szablon:
Kod
echo '
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
<head>
    <meta http-equiv="Content-type" content="application/xhtml+xml; charset=utf-8" />
    
    <title>' . $tresc1 . '</title>

    <link rel="stylesheet" href="'.$arkuszcss.'" type="text/css" />
</head>
<body>
    <div id="a">
            <?php
            echo wyswietlmenu( $tresc2, $lacznikbazdy, $zm1, $zm2 ); //wyświetlam menu na podstawie danych z bazy, łącznika do bazy i kilku zmiennych sterujących
            ?>
    </div>

        <div id="b"><ul>
            <?php foreach( $tresc3 as $t3){
            echo "<li>$t3</li>";} ?>
        </ul></div>
</body>
';


Czy to jest ok? Czy zupełnie źle?

A co do tego dziedziczenia stopek, to czy to co napisałeś nie sprowadza się do zrobienia domyślnej stopki i przypisaniu jej do wszystkich adr4esów w bazie danych. A dla tych kilku wybranych trzeba przypisać inną stopkę? Czy dobrze mi się wydaje, że to powinno być zrobione w bazie danych, tak, że pobierając z bazy pole $stopka w zależności od strony pobiera się inną nazwę pliku ze stopką? A w samym szablonie robi się cały czas include($stopka);?

Jeśli tak to jak wyświetlić taką stronę do zmiennej, żeby się upewnić czy nie ma błędów i dopiero potem na ekran przeglądarki ?
Przepraszam, że tak cięgle pytam ale nie mogę tego do końca zrozumieć. Może mógłbyś wkleić kawałek jakiegoś swojego szablonu i pliku index.php, do którego go dołączasz? Wiesz, tak, żeby dało sie zobaczyć dokładnie mechanizm jak to ma działać.
pozdrawiam
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.