[PHP/ALG] Hoe "volgorde problemen" voorkomen bij templates?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Met de bouw van mijn eigen cms stuit ik op een probleem. In de basis werkt mijn (zeer eenvoudige) template systeempje als volgt:
HTML:
1
2
3
4
5
6
7
8
9
10
11
<html>
  <head>
    <title>[title]</title>
    [css]
  </head>
  <body>
    [admin_toolbar]
    [bodytext]
    [sideboxes]
  </body>
</html>

De pagina wordt van boven naar beneden ingelezen, en bij elke [token] wordt een callback functie aangeroepen. Zo pakt token_css() alle relevante stylesheets bij elkaar, maakt er een goede html-string van en retourneert deze naar de template:
HTML:
1
2
<link rel="stylesheet" href="files/style.css" type="text/css" media="screen">
<link rel="stylesheet" href="files/jquery.lightbox.css" type="text/css" media="screen">

Dit gaat goed zolang er geen afhankelijkheid tussen de [tokens] is. Bij [admin_toolbar] komt er een probleem: de token_admin_toolbar() functie retourneert een fixed div bovenaan het scherm met daarin alle administratieve functies die op die pagina van belang zijn, bijvoorbeeld:
code:
1
2
3
+-----------------------------------------------------------+
| edit page | edit sidecontent | edit css | change template |
+-----------------------------------------------------------+

Welke knoppen er allemaal in de toolbar moeten komen, gebeurt door de global $buttons te imploderen, zie het volgende vereenvoudigde voorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
10
function token_css($page_id) {
  global $buttons;
  $css = invoke_all_content('css', $page_id) // grab all css for this page
  $buttons[] = (isset($css)) ? 'edit css' : 'add css';
}

function token_toolbar() {
  global $buttons;
  return implode($buttons);
}


En zie hier het probleem. "Sidecontent" zijn extra stukjes informatie in de zijkolom van de pagina, zoals de productreviews en jobs op deze tweakers pagina.
  1. Op sommige pagina's is nog geen sidecontent ingevuld. De functie token_sidecontent() zal dan null retourneren. In dat geval moet $buttons worden uitgebreid met een knop 'add sidecontent'
  2. In het geval er wel sidecontent is gedefinieerd voor deze pagina (bijvoorbeeld: <div>kijk voor meer info op <a href="nu.nl">nu.nl</a></div>), wordt dit geretourneerd. In dat geval moet $buttons worden uitgebreid met een knop 'edit sidecontent'
Het probleem is nu dat ik pas weet welke sidecontent knop ik moet toevoegen, nadat token_toolbar() al heeft gedraaid. Met andere woorden, op het moment dat token_toolbar() wordt aangeroepen (en dus de toolbar div construeert), bevat $buttons nog niet een 'add sidecontent' of 'edit sidecontent' knop. Ik zou dus token_toolbar() pas helemaal op het laatst moeten runnen.

Dit probleem openbaart zich op veel meer plekken in mijn code. Naarmate ik het aantal [tokens] uitbreid, komt het vaker voor dat er afhankelijkheden tussen de tokens bestaan. Ik zou dus eigenlijk moeten kunnen definieren dat token_toolbar() pas als laatste gaat lopen, of in ieder geval pas na token_sidecontent(). Ik ben bang dat ik het hele systeem van [tokens] van boven naar beneden uitlezen zal moeten omgooien, maar ik snap niet goed hoe.

Mijn vraag aan jullie is dus: hoe worden dit soort "volgorde problemen" van uitvoeren van callback functies in zijn algemeenheid opgelost? En is dat ueberhaupt op te lossen? Want ik kan wel leuk definieren dat token_toolbar() pas na token_sidecontent() moet worden uitgevoerd, maar wat als er een pagina is die NA token_sidecontent() nog een andere token heeft staan die van belang is (bijvoorbeeld [footer])? Want dan wordt de knop 'add/edit footer' weer niet op tijd aan $buttons toegevoegd.

Ik hoop dat ik mijn probleem duidelijk heb uitgelegd.

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Simpel : code en layout scheiden...

Eerst alle code uitvoeren en aan de hand daarvan een variabele sidecontent vullen ( desnoods met niks ) en daarna in je template de html produceren...

Als alle code uitgevoerd is dan weet je blijkbaar pas wat er in de sidecontent moet, doe er dan ook niets mee van te voren...

Acties:
  • 0 Henk 'm!

  • Peedy
  • Registratie: Februari 2002
  • Laatst online: 06-11-2024
Kijk eens naar het MVC concept. Dat is dé oplossing voor jouw probleem.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Gomez12 schreef op zondag 21 februari 2010 @ 14:08:
Simpel : code en layout scheiden...
Ik dacht dat ik dat had gedaan (hieronder zeer vereenvoudigd, maar geeft wel goed aan hoe het nu in mijn systeempje werkt). De layout staat in main.tpl, de code / logica in index.php?
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// main.tpl
"<html>[title] [css] [admin_toolbar] [sidecontent]</html>"

// index.php
$template = file_fetch(TEMPLATE_PATH .'main.tpl');
echo token_process($template); // html output naar client...

function token_process($text) {
  // ...find [tokens] in $text
  foreach ($token in $tokens) {
    $funtion = 'token'. _$token;
    return $function();
  }
}

function token_title() {
  global $buttons;
  $buttons[] = 'edit title';
  return get_page_title_from_db();
}

function token_css() {
  global $buttons;
  $buttons[] = 'edit css';
  return '<link rel="stylesheet" ...>';
}

/**
 * Oeps! De button "edit sidecontent" ontbreekt in de output 
 * ("edit title | edit css") omdat token_sidecontent() pas hierna
 * aangeroepen wordt :-(
 */
function token_admin_toolbar() {
  global $buttons;
  return '<div>'. implode(" | ", $buttons) .'</div>';
}

function token_sidecontent() {
  global $buttons;
  $buttons[] = 'edit sidecontent';
  return get_sidecontent_from_db();
}
Eerst alle code uitvoeren en aan de hand daarvan een variabele sidecontent vullen ( desnoods met niks ) en daarna in je template de html produceren...Als alle code uitgevoerd is dan weet je blijkbaar pas wat er in de sidecontent moet, doe er dan ook niets mee van te voren...
Ik vind dit moeilijk voor te stellen. Mijn code wordt uitgevoerd terwijl er van boven naar beneden door main.tpl (de template file) gelezen wordt. Zou je mijn voorbeeld van hierboven kunnen aanpassen, zodat mij duidelijk wordt hoe ik eerst alles kan uitvoeren VOORDAT ik de template variabelen ga vullen? Ik heb namelijk echt geen idee hoe ik eerst alle $buttons kan verzamelen, en daarna terug kan gaan naar token_admin_toolbar() om de toolbar samen te stellen :?
Peedy schreef op zondag 21 februari 2010 @ 17:51:
Kijk eens naar het MVC concept. Dat is dé oplossing voor jouw probleem.
Ik ben me nu wat aan het orienteren, maar loop wel tegen een probleem op. Ik ben een hobbyist (geen informatica opleiding) en mijn systeempje is niet rond classes gebouwd (maar, zoals ik net mbv van Google uitvond, 'procedural' :)). Alle MVC voorbeelden zijn OO, dus ik zou eerst in die materie moeten duiken om die concepten te snappen. Ik zag ook dat alle "PHP template engines" (Google) OO zijn geschreven. Mijn eerste vraag is dan ook: is mijn probleem alleen met OO programmeren op te lossen? Niet dat ik dat niet zou willen uitvinden, maar dan moet ik dit probleem een aantal weken laten liggen (terwijl ik iemand een site heb beloofd). Is er misschien een 'quick and dirty' voorlopige oplossing anders? En welk open source project is bij jouw weten netjes OO geprogrammeerd maar niet te groot in omvang, zodat ik daarvan kan gaan leren?

[ Voor 23% gewijzigd door Verwijderd op 22-02-2010 02:43 ]


Acties:
  • 0 Henk 'm!

  • Peedy
  • Registratie: Februari 2002
  • Laatst online: 06-11-2024
Verwijderd schreef op maandag 22 februari 2010 @ 00:54:
[...]

Ik dacht dat ik dat had gedaan (hieronder zeer vereenvoudigd, maar geeft wel goed aan hoe het nu in mijn systeempje werkt). De layout staat in main.tpl, de code / logica in index.php?
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// main.tpl
"<html>[title] [css] [admin_toolbar] [sidecontent]</html>"

// index.php
$template = file_fetch(TEMPLATE_PATH .'main.tpl');
echo token_process($template); // html output naar client...

function token_process($text) {
  // ...find [tokens] in $text
  foreach ($token in $tokens) {
    $funtion = 'token'. _$token;
    return $function();
  }
}

function token_title() {
  global $buttons;
  $buttons[] = 'edit title';
  return get_page_title_from_db();
}

function token_css() {
  global $buttons;
  $buttons[] = 'edit css';
  return '<link rel="stylesheet" ...>';
}

/**
 * Oeps! De button "edit sidecontent" ontbreekt in de output 
 * ("edit title | edit css") omdat token_sidecontent() pas hierna
 * aangeroepen wordt :-(
 */
function token_admin_toolbar() {
  global $buttons;
  return '<div>'. implode(" | ", $buttons) .'</div>';
}

function token_sidecontent() {
  global $buttons;
  $buttons[] = 'edit sidecontent';
  return get_sidecontent_from_db();
}


[...]

Ik vind dit moeilijk voor te stellen. Mijn code wordt uitgevoerd terwijl er van boven naar beneden door main.tpl (de template file) gelezen wordt. Zou je mijn voorbeeld van hierboven kunnen aanpassen, zodat mij duidelijk wordt hoe ik eerst alles kan uitvoeren VOORDAT ik de template variabelen ga vullen? Ik heb namelijk echt geen idee hoe ik eerst alle $buttons kan verzamelen, en daarna terug kan gaan naar token_admin_toolbar() om de toolbar samen te stellen :?

[...]

Ik ben me nu wat aan het orienteren, maar loop wel tegen een probleem op. Ik ben een hobbyist (geen informatica opleiding) en mijn systeempje is niet rond classes gebouwd (maar, zoals ik net mbv van Google uitvond, 'procedural' :)). Alle MVC voorbeelden zijn OO, dus ik zou eerst in die materie moeten duiken om die concepten te snappen. Ik zag ook dat alle "PHP template engines" (Google) OO zijn geschreven. Mijn eerste vraag is dan ook: is mijn probleem alleen met OO programmeren op te lossen? Niet dat ik dat niet zou willen uitvinden, maar dan moet ik dit probleem een aantal weken laten liggen (terwijl ik iemand een site heb beloofd). Is er misschien een 'quick and dirty' voorlopige oplossing anders? En welk open source project is bij jouw weten netjes OO geprogrammeerd maar niet te groot in omvang, zodat ik daarvan kan gaan leren?
Antwoord; nee. Hoewel OO wel the way to go is (en echt niet zo moeilijk als het lijkt, dus ook jij als hobbyist kan er mee aan de slag) kan het ook procedural. Ik zie in jouw code echter dat jij de template in het begin aanroept en dan er mee aan de haal gaat. Je moet het proces omdraaien; eerst je tokens definen en beslissen waarmee je ze wilt replacen (en dat in arrays zetten) en dan op het eind bijv een str_replace draaien waarin je daadwerkelijk alles aanpast. Zo kan je de afhankelijkheden dus ook instellen.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Hm. Je gebruikte structuur heeft een bepaalde naam (het is een design pattern), dat vergelijkbaar is met het MVC pattern (alleen dan niet op basis van OO). In plaats van dat je controller bepaald welke content je krijgt, wordt dit echter aangeroepen vanuit je presentatie.

Dit is op zich geen vreemde aanpak, en het heeft ook een voordeel ten opzichte van MVC - flexibiliteit en efficientie, dwz, je kunt vanuit je templates bepalen welke content er opgehaald wordt, in plaats van dat je dat vast moet stellen in je controller. In ieder geval, genoeg theorie, weet niet of je bekend bent met dit soort concepten.

De oplossing voor jouw probleem (voor zover ik die kan zien) is om niet 'live' te gaan renderen, maar eerst een tussenstap te doen. Laat je software eerst een keer door de template heen gaan om te kijken welke tokens er zijn, ofwel welke gegevens opgevraagd worden.

Van daaruit kun je elke token apart behandelen. Elk token kan dan (indien nodig) iets aan het menu-token toevoegen, of de andere 'global' tokens waarvan de inhoud afhankelijk is van andere tokens.

Tenslotte, zodra je alle tokens vervangen heb, laat je de presentatie renderen.

Acties:
  • 0 Henk 'm!

  • flashin
  • Registratie: Augustus 2002
  • Laatst online: 17-12-2023
Ik vind het maar vrij ernstige crap om MVC altijd maar de oplossing van alles te benoemen. Terwijl 99% van de 'programmeurs' het concept niet eens volledig begrijpt en er een dikke kans in zit dat de TS dit binnen korte termijn ook niet zal doen (NOFI)..

Als je het lekker procedureel wilt houden, je bent namelijk lekker aan het hobby'en, zonder dat het al te theoretisch wordt kun je met een simpel template parsertje ook al genoeg doen. Ook al is PHP in feite zelf al een template parser, en kun je hier ook eindeloos over discussieren, het maakt dit probleem wel een stuk eenvoudiger.
TemplatePower is bijv. een relatief simpele parser die doet wat je nodig hebt.

[ Voor 5% gewijzigd door flashin op 22-02-2010 10:48 ]


Acties:
  • 0 Henk 'm!

  • Peedy
  • Registratie: Februari 2002
  • Laatst online: 06-11-2024
flashin schreef op maandag 22 februari 2010 @ 10:46:
Ik vind het maar vrij ernstige crap om MVC altijd maar de oplossing van alles te benoemen. Terwijl 99% van de 'programmeurs' het concept niet eens volledig begrijpt en er een dikke kans in zit dat de TS dit binnen korte termijn ook niet zal doen (NOFI)..

Als je het lekker procedureel wilt houden, je bent namelijk lekker aan het hobby'en, zonder dat het al te theoretisch wordt kun je met een simpel template parsertje ook al genoeg doen. Ook al is PHP in feite zelf al een template parser, en kun je hier ook eindeloos over discussieren, het maakt dit probleem wel een stuk eenvoudiger.
TemplatePower is bijv. een relatief simpele parser die doet wat je nodig hebt.
99% van de programmeurs kent het concept niet? Ik neem geen programmeur aan die het MVC concept niet kent hoor. Dat is toch echt wel basiskennis.

Dat terzijde, als je aan de slag gaat met template engines (inderdaad geen gek idee in dit geval) dan zou ik kijken naar TemplateLite, een afgeslankte versie van Smarty.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

Peedy schreef op maandag 22 februari 2010 @ 11:26:
[...]

99% van de programmeurs kent het concept niet? Ik neem geen programmeur aan die het MVC concept niet kent hoor. Dat is toch echt wel basiskennis.
99% is misschien wat overdreven, maar ik moet Flashin wel gelijk geven dat het vaak nogal een hoog cargo cult gehalte heeft. Ik zie nog best veel opmerkingen voorbijkomen van mensen die van zichzelf wel vinden dat ze MVC volledig begrijpen, maar het vervolgens verwarren met 3 tier oplossingen of zelfs als oplossing aanbieden voor een datalaag probleem. MVC werkt erg goed, maar is zeker niet de heilige graal. Zeker wanneer je met een meer een tot request scope beperkte omgeving hebt als PHP gaan veel voordelen van het MVC pattern verloren (Aangezien jij het naadje van de MVC kous weet zul je dat zelf ook wel begrijpen ;) ). Ik verbaas me er dan ook vaak over dat het in die wereld zo ontiegelijk veel gebruikt wordt, zonder die problemen te adresseren.

In het geval van de topicstarter zou ik eerder voor de door YopY voorgestelde oplossing gaan.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • jip_86
  • Registratie: Juli 2004
  • Laatst online: 20-09 16:33
OO zou hier zeker wel iets toevoegen. Je zou dan eerst alle tokens in kunnen lezen en omzetten naar klasses. Daarna zou bijvoorbeeld de admintoolbar klasse aan de sidecontent klasse kunnen vragen via een methode benjeleeg() of er ook een knop 'add sidecontent' getoond moet worden. Procedureel kan het vast ook wel, maar maakt het wel heel erg complex. Zeker bij veel tokens en afhankelijkheden.

Acties:
  • 0 Henk 'm!

  • cfern
  • Registratie: Oktober 2009
  • Laatst online: 19-09 10:09
Peedy schreef op maandag 22 februari 2010 @ 11:26:
99% van de programmeurs kent het concept niet? Ik neem geen programmeur aan die het MVC concept niet kent hoor. Dat is toch echt wel basiskennis.
:'( Niet iedere programmeur bemoeit zich dagelijks met webdingesen hoor.

"I'd rather have a full bottle in front of me, than a full frontal lobotomy." (Tom Waits) | PoE


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor jullie antwoorden, ik ben vooral blij te horen dat mijn probleem in principe ook zonder OO opgelost kan worden, en dat ik niet de hele structuur van mijn systeempje hoef om te gooien :)

De oplossing van YopY klinkt goed, en ik doe mijn best om het te begrijpen maar ik loop dat tegen hetzelfde probleem op. Pseudo en zeer verkort hieronder weergegeven. Ook hier loop ik in de array van [tokens] eerst tegen [admin_toolbar] aan en pas daarna tegen [sidecontent], dus de knop 'edit sidecontent' ontbreekt ook in deze output.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// main.tpl
"<html>[title] [css] [admin_toolbar] [sidecontent]</html>"

// index.php
$template = file_fetch(TEMPLATE_PATH .'main.tpl');
$tokens = template_preprocess($template); // geeft als resultaat:
$tokens = array('[title]', '[css]', '[admin_toolbar]', '[sidecontent]')

$content[] = token_process($tokens); // geeft als resultaat:
$content = array(
  titel => 'leuke titel', 
  css => '<link rel="stylesheet" ...>', 
  admin_toolbar => 'edit title | edit css', 
  sidecontent => 'marginale info'
); 

echo template_fill($template, $content); // output naar client

function token_process($array) {
  foreach ($token in $tokens) {
    $funtion = 'token'. _$token;
    return $function();
  }
}

function token_title() {
  global $buttons;
  $buttons[] = 'edit title';
  return get_page_title_from_db(); // stel output = "leuke titel!"
}

function token_css() {
  global $buttons;
  $buttons[] = 'edit css';
  return '<link rel="stylesheet" ...>';
}

function token_admin_toolbar() {
  global $buttons;
  return '<div>'. implode(" | ", $buttons) .'</div>';
}

function token_sidecontent() {
  global $buttons;
  $buttons[] = 'edit sidecontent';
  return get_sidecontent_from_db(); // stel output = "marginale info" 
} 

function template_fill($template, $content) {
  // vervang [tokens] door content in template
  return $output;
}

Mijn vraag is dus: HOE kan ik de output van token_admin_toolbar() manipuleren, nadat deze al is aangeroepen en dus $buttons al geimplode heeft? Een eenvoudige oplossing is natuurlijk door de [admin_toolbar] token achteraan in de array te zetten, maar dat is geen blijvende oplossing volgens mij omdat er altijd token-afhankelijkheid zal zijn. Misschien wil token_admin_toolbar() wel iets toevoegen aan de output van token_title(), bijvoorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Stel $tokens als volgt waarbij [admin_toolbar] NA [title] volgt
$tokens = array('[title]', '[css]', '[admin_toolbar]')

function token_title() {
  global $title;
  $title = 'leuke titel!';
  return $title;
}

function token_admin_toolbar() {
  // ...
  global $title;
  $title.= '(admin ingelogd)';
}

Hier tracht token_admin_toolbar() de titel van de pagina ($title) te manipuleren naar 'leuke titel! (admin ingelogd)', maar dit zal in de output naar de client niet worden weergegeven, omdat token_admin_toolbar() $title pas aanvult NADAT deze al door token_title() naar de $content-array is teruggestuurd!

Ik blijf maar in ditzelfde kringetje draaien. Waar ga ik verkeerd? Kan iemand, bv. met een aanvulling / verandering in mijn pseudo-code hierboven, aangeven hoe ik hier omheen werk?

Overigens heb ik gekeken naar de voorgestelde templating systemen. Misschien ben ik eigenwijs als ik zeg dat ik liever een klein 'parsertje' zelf bouw. De genoemde alternatieven zijn allen overkill: ik zie geen noodzaak voor control structures in templates, alswel het includen van PHP-code. Ik wil dat de eindgebruiker niet meer (of minder) kan dan een aantal voorgedefinieerde [tokens] in een eenvoudig html-template zetten. Bovendien heb ik liever iets wat veel minder krachtig is, maar wat ik wel zelf heb geschreven (en dus begrijp), dan dat ik een library include die voor mij een black box is. Ik wil met dit projectje ook PHP leren :) Als ik iets mis, hoor ik het graag :)

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

cfern schreef op maandag 22 februari 2010 @ 12:41:
[...]

:'( Niet iedere programmeur bemoeit zich dagelijks met webdingesen hoor.
De grootste grap is juist dat het MVC pattern lastig toepasbaar is in een stateless webomgeving ;). Het werkt veel beter in een native GUI applicatie.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Ten eerste moeten je functies niet gelijk de output teruggeven, maar de output ofwel de gegevens juist eerst opslaan, of in ieder geval dat admin menu van je. Haal het admin blok uit de array van blokken die hij verwerkt / waar hij naar zoekt, en roep die apart aan nadat de andere blokken klaar zijn met verwerken en het toevoegen van hun menuopties aan het menu. Pseudo:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// index.php 
$template = file_fetch(TEMPLATE_PATH .'main.tpl'); 
$tokens = template_preprocess($template); // geeft als resultaat: 
$tokens = array('[title]', '[css]', '[sidecontent]') 

$content[] = token_process($tokens); // geeft als resultaat: 
$content = array( 
  titel => 'leuke titel',  
  css => '<link rel="stylesheet" ...>',  
  sidecontent => 'marginale info' 
);

// doe altijd admin_toolbar pas als laatste
// $content bevat nu ook admin toolbar
$content[] = token_process(array('[admin_toolbar]'));

echo template_fill($template, $content); // output naar client 


Natuurlijk is dat alleen toepasbaar op je admin_toolbar. Je zou dit verder kunnen toepassen als je verschillende tokens altijd 'hierarchisch' opgebouwd zijn (dwz, de ene is afhankelijk van de andere, maar niet vice-versa en omgekeerd). Het lijkt me echter beter om de HTML en de data gescheiden te houden. In plaats van dat token_css een string met CSS teruggeeft, zou het alleen de CSS bestandsnamen in een array moeten zetten. Deze worden dan pas nadat alle gegevens verzameld zijn doorgegeven aan een functie die er HTML omheen zet, danwel een zogeheten 'partial', een kleiner template waarin data omgezet wordt naar stukken HTML. In gewoon standaard niks-aan-de-hand PHP:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$css = array('files/main.css', 'print.css');
// functies die iets toevoegen (eventueel) aan $css

// tenslotte:

$css_output = render('css.tpl', $css);

// waar css.tpl zoiets is als:
foreach ($css as $file) :
?>
    <link rel="stylesheet" href="<?= $file ?>" type="text/css" media="screen"> 
<?php
endforeach;
// noot: syntax zal wel niet kloppen of optimaal zijn.
?>


Je grote probleem op dit moment is dat je token_ functies direct HTML teruggeven, en dat ze 'in-order' uitgevoerd worden. Zorg ervoor dat je token_ functies op willekeurige tijdstippen ('out-of-order') aangeroepen kunnen worden, en dat er maar één moment in je code is waarop de data omgezet wordt naar HTML.

Niet dat ik een expert ben overigens.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
YopY schreef op maandag 22 februari 2010 @ 13:37:
[...]
Ten eerste moeten je functies niet gelijk de output teruggeven, maar de output ofwel de gegevens juist eerst opslaan [...] Deze worden dan pas nadat alle gegevens verzameld zijn doorgegeven aan een functie die er HTML omheen zet, danwel een zogeheten 'partial', een kleiner template waarin data omgezet wordt naar stukken HTML. [...] Zorg ervoor dat je token_ functies op willekeurige tijdstippen ('out-of-order') aangeroepen kunnen worden, en dat er maar één moment in je code is waarop de data omgezet wordt naar HTML. [...] Niet dat ik een expert ben overigens.
Maar wat je zegt snijdt wel hout :) Maar nu begin ik de rest van de code van mijn cms'je ook wel te overdenken. Neem bijvoorbeed de functie waarmee ik een geneste unordered list voor de navigatie maak:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function menu_tree($parent = '') {
  global $menu;
  global $theme;

  $output = '';
  if (isset($menu[$parent]) && $menu[$parent]['children']) {
    usort($menu[$parent]['children'], 'menu_sort');
    foreach ($menu[$parent]['children'] as $item) {
      $visible = has_visible_children($item);
      if (($menu[$item]['access'] == 1 && ($menu[$item]['callback'] || $visible))) {
        $style  = ($visible) ? (in_active_trail($item) ? 'expanded' : 'collapsed') : 'leaf';
        $title = str_replace("'", '&lsquo;', $menu[$item]['title']);
        $output.= '<li class="'. $style .'">'. l($title, $item);
        $output.= menu_tree($item);
        $output.= '</li>';
      }
      else if ($menu[$item]['children']) {
        $output.= menu_tree($item, 1);
      }
    }
    if ($output != '' && $type != MENU_HIDE) {
      if ($parent == '') {
        $output = sprintf('<ul id="toolbar-menu">%s</ul>', $output);
      }
      else {
        $output = sprintf('<ul>%s</ul>', $output);
      }
    }
  }
  return $output;
}

Ik dacht altijd "als ik dan toch al door alle menu items heen loop, kan ik er net zo goed meteen html tags omheen zetten en in een keer de output genereren". Maar volgens het idee van YopY, zou menu_tree() een multidimensionale array moeten retourneren, die in een template in een unordered list wordt gegooid?

En een ander extreem voorbeeld. Stel dat ik een functie heb om de gebruikers van de website op te sommen. In die lijst wil ik de naam van de admins, vet weergeven. Dan zou ik dat normaal zo hebben gedaan:
PHP:
1
2
3
4
5
6
function list_users() {
  $result = db_query("SELECT name, role FROM users");
  while ($user = db_fetch_object($result)) {
    $output.= ($user->role == 'admin') ? '<b>'. $user->name .'</b>' : $user->name;
  }
}

Maar als ik het goed begrijp, zou ik ook in dit geval een array moeten retourneren, die in een template functie weer wordt doorlopen en waar dan pas de bold-tags worden toegevoegd? Het klinkt zo als performance verlies? Waar trekken jullie de grens; een enkele html tag mag wel of gewoon helemaal geen html in je logica?

* leert veel vandaag *

Acties:
  • 0 Henk 'm!

  • flashin
  • Registratie: Augustus 2002
  • Laatst online: 17-12-2023
Scheiden is scheiden. Dus dan betekent het geen enkele html in je logica..Hoe onpraktisch dat in het begin ook lijkt. Theoretisch gezien kun je een nieuwe presentatielaag aanmaken die een andere output verzorgt dan HTML.

Dit is echter precies een van de punten waar discussies altijd over gevoerd worden. Wanneer je op deze manier al bezig bent ga je al gauw met het veel complexere smarty aan de gang 'om je code maar duidelijk te houden'. In feite ga je door het extreem te scheiden, het alleen maar onduidelijker maken. Dwz je presentatielaag zelf wordt crap..
(ik ben niet pro-smarty, deze kerel is helemaal anti-smarty, maar heeft wel een aantal goede punten: http://nosmarty.net/)

Wat ik vind, is dat je een goede balans moet vinden tussen scheiding van logica en code en efficientie van ontwikkelen en van je applicatie. Ik bedoel daarmee dat je niet compleet moet verzuipen in theoretisch perfectionisme, wat ik helaas relatief vaak zie gebeuren bij programmeurs, maar gewoon implementeren.

Acties:
  • 0 Henk 'm!

  • ZpAz
  • Registratie: September 2005
  • Laatst online: 19-09 22:44
cfern schreef op maandag 22 februari 2010 @ 12:41:
[...]

:'( Niet iedere programmeur bemoeit zich dagelijks met webdingesen hoor.
MVC is dan ook niet gelimiteerd tot enkel het web, en is in applicaties ook prima te gebruiken.

Tweakers Time Machine Browser Extension | Chrome : Firefox


Acties:
  • 0 Henk 'm!

  • Peedy
  • Registratie: Februari 2002
  • Laatst online: 06-11-2024
cfern schreef op maandag 22 februari 2010 @ 12:41:
[...]

:'( Niet iedere programmeur bemoeit zich dagelijks met webdingesen hoor.
Sorry, ik doelde zelf op webdevelopers :) Point taken.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
flashin schreef op maandag 22 februari 2010 @ 16:47:
Scheiden is scheiden. Dus dan betekent het geen enkele html in je logica..Hoe onpraktisch dat in het begin ook lijkt.
Onpraktisch, daar kan ik overheen stappen. Het zal vervelend zijn om alle html uit mijn logica te slopen en via templates in te vullen, maar dat is dan maar even zo. Waar ik eerder een probleem mee heb, is de inefficiency ervan: eerst bouw ik (in de logica) een recursieve functie die een multi-array met menu items retourneert, daarna bouw ik een template die recursief door die array gaat om de html te genereren. Het lijkt zo dubbelop en dus negatief qua performance...of overdrijf ik dat nu?

Acties:
  • 0 Henk 'm!

  • jip_86
  • Registratie: Juli 2004
  • Laatst online: 20-09 16:33
Opmaak is opmaak. Als je graag templates wilt gebruiken moet je ook alles in je templates zetten. Als je later je site nog eens wilt redesignen moet je op tig plaatsen nog eens aanpassingen doen om je layout te verbouwen.

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Verwijderd schreef op maandag 22 februari 2010 @ 17:16:
[...]

Onpraktisch, daar kan ik overheen stappen. Het zal vervelend zijn om alle html uit mijn logica te slopen en via templates in te vullen, maar dat is dan maar even zo. Waar ik eerder een probleem mee heb, is de inefficiency ervan: eerst bouw ik (in de logica) een recursieve functie die een multi-array met menu items retourneert, daarna bouw ik een template die recursief door die array gaat om de html te genereren. Het lijkt zo dubbelop en dus negatief qua performance...of overdrijf ik dat nu?
Qua performance ga je er niets van merken.

Je moet het ook weer niet overdrijven natuurlijk, maar een keer extra door een array met 1000 items heenlopen in een template kost je echt geen secondes ofzo...

Zolang je je logica maar buiten je templates houdt ( die kosten inclusief dbase calls namelijk veelal 99,99% van de tijd ) en je niet array's met miljoenen records gaat opbouwen dan merk je er niets negatiefs van als het al niet positief wordt ( je kunt blokken logica gaan cachen waardoor als je bijv een rss-template ernaast zet of je rss je cache vult of je pageview vult de cache, maar alletwee kunnen ze putten uit dezelfde cache )
Pagina: 1