[PHP/REGEX] Menuitems replacen & herhalen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben bezig met het maken van een CMS en ben hiermee praktisch afgerond. Ik stuit echter nog op een probleempje.

Het werkt zo: in de database zit (wat nu van toepassing is) 1) een html-template en 2) de pagina's met hun inhoud, titel, url,...

Doormiddel van regex zoek ik in de "html-templates" naar tags, bijvoorbeeld {title} word vervangen door de titel van de huidige pagina en {content} door de inhoud. Nu zou ik echter het menu moeten parsen, iets complexer. Ik dacht eraan om een tag als deze te gebruiken: {menu}{menuitemurl}{menuitemtitle}{/menu}, zodat bijvoorbeeld dit in de praktijk ingevoegd word:

<ul class="menu">
{menu}<li><a href="{menuitemurl}"><strong>{menuitemtitle}</strong></a></li>{/menu}
</ul>

Alles tussen de {menu} en {/menu} tags moet dus herhaald worden naargelang het aantal pagina's (== aantal menuitems). Heeft iemand er een idee van hoe ik dit het best kan aanpakken? Nu geraakt ik er namelijk niet echt uit.


huidige index.php (waarmee de template en content geladen worden)
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
<?php
// CMS HTML template parser
include("config.php");
$link = mysql_connect($mysql['server'], $mysql['user'], $mysql['pass']);
$db = mysql_select_db($mysql['db'], $link);

// HTML template oproepen
$template_query = "SELECT content FROM " . $mysql['template_html'] . " WHERE `site`='test.be'";
$template_result = mysql_query($template_query);
if(mysql_num_rows($template_result) <= 0) { 
    die('Fout: geen html-template gevonden');
}
$template = mysql_fetch_assoc($template_result); // template: $template['content']

// Gevraagde pagina oproepen
if($_GET['page'] && !empty($_GET['page'])) {
    $requestedpage = htmlentities($_GET['page']);
}
else {
    $requestedpage = "index";
}
$requested_query = "SELECT open, title, content FROM " . $mysql['content'] . " WHERE `site`='test.be' AND `url`='" . $requestedpage . "'";
$requested_result = mysql_query($requested_query);
$requested = mysql_fetch_assoc($requested_result);
if(mysql_num_rows($requested_result) <= 0 || $requested['open'] == 0) { 
    header('Location: 404.php');
}

// Opgevraagde pagina parsen
$finalpage = preg_replace("[{title}]", $requested['title'], $template['content']);
$finalpage = preg_replace("[{content}]", $requested['content'], $finalpage);

// Uiteindelijke pagina naar browser verzenden
echo $finalpage;
?>


Bij voorbaat dank!

Acties:
  • 0 Henk 'm!

  • BtM909
  • Registratie: Juni 2000
  • Niet online

BtM909

Watch out Guys...

Ace of Base vs Charli XCX - All That She Boom Claps (RMT) | Clean Bandit vs Galantis - I'd Rather Be You (RMT)
You've moved up on my notch-list. You have 1 notch
I have a black belt in Kung Flu.


Acties:
  • 0 Henk 'm!

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

Janoz

Moderator Devschuur®

!litemod

Verwijderd schreef op dinsdag 28 oktober 2008 @ 16:29:
Heeft iemand er een idee van hoe ik dit het best kan aanpakken?
Geen regexp gebruiken, maar gewoon een stackbased parser (waarbij je het zoeken naar relevante tokens vervolgens wel weer met reguliere expressies kunt doen).

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!

Verwijderd

Wanneer je templates valid X(HT)ML zijn zou je ook 's naar XSL kunnen kijken, die is speciaal bedoeld om XML te transformeren, en heeft handige dingetjes als foreach, etc.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Janoz schreef op dinsdag 28 oktober 2008 @ 18:51:
[...]

Geen regexp gebruiken, maar gewoon een stackbased parser (waarbij je het zoeken naar relevante tokens vervolgens wel weer met reguliere expressies kunt doen).
Je bedoelt stack based als bijvoorbeeld een UBB parser? en dan binnen de gevonden stack {menu}{/menu} regex toepassen + foreach lus totdat alle menuitems gepasseerd zijn? Ken je misschien een simpel stukje code ergens dat de werking hiervan demonstreert, want vanwege de erg beperkte toepassing van stack based parser moet dit niet al te complex/uitgebreid zijn uiteraard :)

Wat XSL(T) betreft, dit is voor mij op dit moment compleet onbekend terrein, ik ga dus eerst proberen te werken zoals Janoz voorstelt, maar ik ga hier zeker eens een blik op werpen, het lijkt me namelijk wel de moeite waard! :)

Acties:
  • 0 Henk 'm!

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

Janoz

Moderator Devschuur®

!litemod

Een UBB parser is niet per definitie een stackbased parser (alhoewel een ubb parser wel als een stackbased parser geimplementeerd kan zijn).

Een stackbased parser houd in dat je je input doorleest en een stack bijhoud van de state. Als je op een gegeven moment de {menu} tegenkomt kom je in de 'menu' state terecht en moet je het menu afhandelen totdat je {/menu} tegenkomt. Dan haal je de menuafhandel state weer van je stack af.

Als voorbeeld zou je inderdaad kunnen kijken naar wat UBB voorbeelden die niet met reguliere expressies werken.

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!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Even kijken hoe het ongeveer met regexp wordt:
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
$txt="<ul class=\"menu\">
{menu}<li><a href=\"{menuitemurl}\"><strong>{menuitemtitle}</strong></a></li>{/menu}
</ul>";

$menus = array( 'a' => 'a/', 'b' => 'b/');
$content = array();

function parsecallback($matches) {
    global $menus, $content;
    if ($matches[1] == 'menu') {
        $res = '';
        foreach ($menus as $item => $url) {
            $content['menuitemtitle'] = $item;
            $content['menuitemurl'] = $url;
            $res .= parsetemplate($matches[2]);
        }
        return $res;
    }
    return $content[$matches[1]];
}

function parsetemplate($template) {
    return preg_replace_callback(
        '#\{(title|content|menu(?:itemurl|itemtitle)?)}(?:(.*?)\{/\1})?#si',
        'parsecallback', $template);
}

echo parsetemplate($txt);

Mits het niet te gek wordt, en je niet aan comments e.d. doet, zou ik dat nog wel aandurven.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
pedorus schreef op dinsdag 28 oktober 2008 @ 21:33:
Even kijken hoe het ongeveer met regexp wordt:
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
$txt="<ul class=\"menu\">
{menu}<li><a href=\"{menuitemurl}\"><strong>{menuitemtitle}</strong></a></li>{/menu}
</ul>";

$menus = array( 'a' => 'a/', 'b' => 'b/');
$content = array();

function parsecallback($matches) {
    global $menus, $content;
    if ($matches[1] == 'menu') {
        $res = '';
        foreach ($menus as $item => $url) {
            $content['menuitemtitle'] = $item;
            $content['menuitemurl'] = $url;
            $res .= parsetemplate($matches[2]);
        }
        return $res;
    }
    return $content[$matches[1]];
}

function parsetemplate($template) {
    return preg_replace_callback(
        '#\{(title|content|menu(?:itemurl|itemtitle)?)}(?:(.*?)\{/\1})?#si',
        'parsecallback', $template);
}

echo parsetemplate($txt);

Mits het niet te gek wordt, en je niet aan comments e.d. doet, zou ik dat nog wel aandurven.
Ik was zelf aan een oplossing aan het werk maar dit lijkt me een betere methode :*)


Zelf had ik deze code, doch vermoed ik dat de jouwe efficienter is (en hij is ook véél netter _/-\o_ )
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
$pageparts = preg_split("[{menu}]", $temppage);
$pageparts2 = preg_split("[{/menu}]", $pageparts[1]);

$query_menulinks = "SELECT title, url FROM " . $mysql['content'] . " WHERE `site`='test.be' AND `open`=1";
$result_menulinks = mysql_query($query_menulinks);
while($menulinks = mysql_fetch_assoc($result_menulinks)) {
    $temp = str_replace("{menuitemurl}", $menulinks['url'], $pageparts2[0]);
    $menuitems .= str_replace("{menuitemtitle}", $menulinks['title'], $temp);
}

echo $pageparts[0];
echo $menuitems;
echo $pageparts2[1];

Die $query_menulinks haalde alle titel/url paren op.

Bedankt voor jullie hulp ! _/-\o_ :)

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Verwijderd schreef op dinsdag 28 oktober 2008 @ 21:58:
Ik was zelf aan een oplossing aan het werk maar dit lijkt me een betere methode :*)
Ai, net te vroeg ;) Nou ja, gelukkig ontbreekt er een strtolower en is er nog ander werk te doen ;)

Ik zag nog iets geks: htmlentities, ik neem aan dat dat mysql_real_escape_string moet zijn, anders kan sql injection...

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
pedorus schreef op dinsdag 28 oktober 2008 @ 23:39:
[...]

Ai, net te vroeg ;) Nou ja, gelukkig ontbreekt er een strtolower en is er nog ander werk te doen ;)

Ik zag nog iets geks: htmlentities, ik neem aan dat dat mysql_real_escape_string moet zijn, anders kan sql injection...
Inderdaad... dat komt ervan als je om 3u 's nachts nog aan het werk bent :) Dank ! _/-\o_
Pagina: 1