[PHP] Template parser in eeuwige loop

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Het CMS'je waar ik mee bezig ben zet ik graag zo modulair mogelijk op. Op dit moment ben ik bezig met de templates. Het idee is dat de gebruiker (met juiste rechten) in een tekstarea de template kan aanpassen. Om toegang te krijgen tot bepaalde content onderdelen (vast of variabel) heeft hij de beschikking over een aantal macro's. Elke module (bij mij is elke module een apart bestand) kan macro's ter beschikking stellen aan het systeem. Bijvoorbeeld:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module | macro          | callback       | output
-------+----------------+----------------+-------------------------
system | {bodytext}     | get_body()     | artikel uit de database
       | {trail}        | cookie_trail() | cookie > crumb > trail
       | {menu,2}       | get_menu()     | html list met menu items
-------+----------------+----------------+-------------------------
forum  | {forums}       | get_forums()   | html list met alle fora
       | {forum_last,5} | forum_last(5)  | laatste 5 forum reakties
-------+----------------+----------------+-------------------------
user   | {user_last}    | user(lastname) | achternaam van ingelogde
       |                |                | gebruiker
       | {loginbox}     | login_form()   | login form
-------+----------------+----------------+-------------------------
etc... |                |                |
       |                |                |

Ik haal de template met de {macro's} op uit de database en doorloop deze met de array welke alle gedefinieerde macro's bevat:
code:
1
$template = str_replace('{trail}', cookie_trail(), $template);

In werkelijkheid gaat het wat geavanceerder maar het komt hier wel op neer en het werkt perfect.
Het probleem hierbij was alleen dat als iemand bijvoorbeeld een artikel schreef en in dit artikel een overzicht wilde geven van de laatste 5 forum reakties, dit niet werkte. De {bodytext} macro werd in de template immers vervangen door het artikel en de {forum_last} macro in het artikel werd niet geparsed.
Dus heb ik de parse-functie recursief gemaakt, zodat eerst {bodytext} en daarna {forum_last} vervangen werd door de werkelijke inhoud. Ik zit nu alleen met een nieuw probleem waar ik mijn hoofd al een tijd over breek: als iemand een {bodytext}-macro in een artikel zet, raatk mijn parsertje in een eeuwige loop! Hetzelfde gebeurt als iemand bijvoorbeeld een menu-item aanmaakt met als titel {menu}.
Bepaalde {macro's} leveren dus problemen op als ze binnen bepaalde andere {macro's} worden gebruikt. Mijn vraag is dus hoe ik (binnen mijn PHP) aangeef welke macro's wanneer wel en wanneer niet geparsed mogen worden. En is zo'n systeem uiteindelijk wel te onderhouden als je 30 macro's ofzo hebt?

Hoe lossen jullie dit probleem op? ("Ik laat mijn klanten nooit zelf aan de templates werken" is niet de oplossing die ik zoek :) )

[off_topic]p.s - is het niet veel logischer om de textarea van GoT waar je je bericht intikt als lettertype courier mee te geven aangezien veel van ons code intikken? Makkelijker met indenten enzo...[/off_topic]

[ Voor 17% gewijzigd door Reveller op 17-05-2005 22:30 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

Verwijderd

Hoe parse je nu je template dan? Waarom zou iets als dit niet werken?:
PHP:
1
2
3
4
5
<?php
    while (preg_match_all("/\{([a-z]+)(\,[a-z0-9]+)*\}/", $template, $preg) > 0) {
        // Do magic with $preg here and update $template
    }
?>


Nvm, ik zie je punt. Je zou er natuurlijk voor kunnen zorgen dat {} tags binnen macro's alleen alle andere macro's vervangen.

[ Voor 26% gewijzigd door Verwijderd op 18-05-2005 00:10 ]


Acties:
  • 0 Henk 'm!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Nou, wat je dus eigenlijk wil (als ik het goed begrijp): bepaalde tags van type x mogen niet in tags van type y voorkomen (x en y kunnen gelijk zijn), dus maak een lijstje van tags waarbij dit niet mag, en zorg er voor dat het alleen toegestaan word als twee tags niet in dat lijstje voorkomen.

Trouwens: wat als je in een {bodytext} een {forumlast} plaatst, en in die {forumlast} een {bodytext} plaatst? Ik denk dat je toch een andere (beproefde?) manier voor je templates moet gaan zoeken, aangezien het volgens mij redelijk moeilijk word om circulaire verwijzingen er uit te halen. (Alhoewel, hier zullen vast wel goede algoritmen voor zijn, heb alleen geen idee welke).

edit:
Trouwens, je moet ook nadenken over wat je eigenlijk wil: stel je zet bewust {bodytext} binnen {bodytext}, wat wil je dat er dan gebeurt? Hoe zou je programma moeten reageren? Je zou trouwens ook nog iets van een counter kunnen meegeven, die er voor zorgt dat je een recursiedieptie van maximaal (10/15/100) krijgt.

[ Voor 20% gewijzigd door chris op 18-05-2005 01:00 ]


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Verwijderd schreef op woensdag 18 mei 2005 @ 00:07:
Nvm, ik zie je punt. Je zou er natuurlijk voor kunnen zorgen dat {} tags binnen macro's alleen alle andere macro's vervangen.
Ik snap niet wat je bedoelt?
chris schreef op woensdag 18 mei 2005 @ 00:58:
Trouwens: wat als je in een {bodytext} een {forumlast} plaatst, en in die {forumlast} een {bodytext} plaatst?
[...]
Trouwens, je moet ook nadenken over wat je eigenlijk wil: stel je zet bewust {bodytext} binnen {bodytext}, wat wil je dat er dan gebeurt?
Dat zijn opzich interessante vragen. Als je in een {bodytext} een {forumlast} plaatst, moeten beide gewoon geparsed worden, terwijl een {bodytext} in een {bodytext} niet geparsed mag worden. Je kijgt dan immers het artikel in het artikel.

Nu ik erover nadenk - wat een brei wordt dat dan eigenlijk. Je zou dan een array ofzo moeten samenstellen waarin staat welke {macro's} binnen welke {macro's} wel en niet geparsed mogen worden:
  • zijn hier geijkte manieren voor?
  • hoeveel van jullie werken eigenlijk met {macro's} in jullie cms en van welke aard zijn deze dan? Een makkelijke oplossing zou ook zijn om te zeggen dat alleen macro's geparsed worden die in de template zelf staan. Macro's die in door de gebruiker gemaakte artikelen etc. staan, worden niet geparsed. Maar dan mis je toch een hoop functionaliteit die denk ik vrij handig kan zijn, of overschat ik nu de waarde van dergelijke {forum_last} macro's voor de gebruiker?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Hm, ik vind je hele macro-systeem niet zo denderend, waarom niet een gewone template-engine gebruiken? (b.v. Smarty). Daarmee kan je ook behoorlijk krachtige dingen doen, onderschat het niet.

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Voor zover ik begrepen heb, is smarty idd een goede engine, maar eigenlijk alleen te gebruiken door programmeurs zelf. Het is mijn doel om de eindgebruiker met een aantal eenvoudige macro's toegang te geven tot php functies / dynamische content. Dat is een andere benadering dan smarty, een snelle, cachende vervang-blokken-en-tokens-door-gegenereerde-html engine...

Volgens mij zit er een duidelijk verschil in doel. En wat is er precies niet denderend aan dit macro systeem? Niet goed geimplementeerd of staat het hele idee je opzich niet aan? Waarom (niet)? Misschien heb je gelijk, maar ik hoor graag waarom :)

Voor de rest blijft de vraag uit de openingspost nog steeds open :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Het ligt natuurlijk heel erg aan de situatie, maar het is meestal zo dat je de eindgebruiker hier absoluut geen controle over wil geven. Maak het dan zo dat als ze een pagina kunnen bewerken dat ze met een vinkje aan of uit kunnen zetten of ze de laatste forum_replies willen hebben. Je wil de meeste gebruikers gewoon geen controle geven over de layout, behalve als ze precies weten waar ze mee bezig zijn OF als ze de manual goed door hebben gelezen en snappen. Dat laatste komt vrijwel niet voor, en in het eerste geval kan je ze ook wel met smarty laten werken.

Ik heb trouwens eventueel nog wel een oplossing voor je probleem: je kan een stack bijhouden met de elementen waar je in zit, als je bijvoorbeeld {body_text} doet, dan push je "body_text" op de stack, en ga je body_text parsen. Kom je dan bijvoorbeeld een {forum_topics} tegen, dan push je "forum_topics" op de stack. De stack bevat dan ["body_text", "forum_topics"]. Vervolgens ga je forum_text parsen, en kom je weer een "body_text" tegen. Je doet een array_exists("body_text", $stack).
Pagina: 1