Door
j opla
op 06-02-2016 20:23
gewijzigd op 06-02-2016 20:24
2.397 views
Beste mensen,
Ik heb een probleempje, misschien weten jullie een oplossing.
Met een hulpmiddel pas is de html code van een stuk tekst aan. Ik gebruik hiervoor de tool simple_html_dom
De bijgewerkte html code roep ik vervolgens met "echo $html" op. Echter, in de html code staat ook een stuk php. Maar die php code wordt nu niet geëvalueerd. Eigenlijk logisch. Maar hoe zou ik het dan wel kunnen doen? Kan ik de php code die in een variabele staat evalueren?
Ja, dan zet je dat tabelletje onder de tekst. Dat is een losse verwerking. Of je maakt gebruik van andere placeholders, die je bijvoorbeeld met preg_replace/preg_replace_callback verwerkt. Dat is vele malen logischer dan met PHP code en eval() te gaan zitten prutsen.
@Ben
Ik begrijp je vraag niet. Soms staat er wel een tabel, soms niet. Er wordt verder niets met preg_replace gedaan, behalve dan hetgeen dat eventueel in simple_html_dom zit. Maar dat heb ik niet uitgeplozen.
@Ivo
Dat gaat mijn pet te boven ... Volgens mij moet ik de $html file opsplitsen in stuk voor een "<¿php". Dat echo-en. Dan het stuk tussen de <¿php en ¿> dat ik met eval() kan uitvoeren, etc. Maar ik zie de link niet met preg_match_all behalve dan dat je een array krijgt -denk ik- met de verschillende php codes. Maar hoe krijg ik de voor-, tussen- en achterliggende html code die gewoon ge-echoed mag worden?
Een menu op te bouwen?
Een HTML tekst (met code) aan te passen?
Wat ben je aan het doen?
Schrijf alsjeblieft een backend om datgene wat je probeert te bereiken structureel aan te pakken, bijvoorbeeld, schrijf een of meer formulieren waarbij elk formulier-veld een element is van de data die je wilt wijzigen, zodat je na afloop de HTML kunt genereren met behulp van gestructureerd opgeslagen data in plaats van dit te ontleden en je te beroepen op de validatie van PHP-code.
Of edit (enkel) de HTML en gebruik wat placeholders voor PHP-code. Maar edit nooit rechtstreeks code van een framework in het framework zelf. Dat is een recipe for disaster. Hier zijn editors en versioning systemen voor, textareas zijn daar een arm substituut voor.
@ Thomas
In mijn pagina zit een stukje content. Dat stukje content is een apart bestandje dat ik inlees. In dat stukje content maak ik uit de html-code van de content een sub-menuutje met simple_html_dom op basis van de in de content gebruikte <h2> codes en als ik aangeef in de content dat ik graag een submenu wil hebben (als <div id=inhoudlinks> in de content staat). In de content staat soms ook nog wat php code om bijvoorbeeld een tabel met dichtstbijzijnde andere monumenten toe te voegen: require extratabel.php.
Een en ander heeft niets met formulieren te maken, ook niet met input van buiten.
Probleem is een beetje dat ik in de loop van de tijd steeds iets toe voeg met de op dat moment aanwezige kennis en ideeën. Nu ben ik wat aan het herstructureren en loop ik tegen zaken aan die kennelijk tegenstrijdig werken. Maar toen windows 10 gemaakt werd, werd ook niet van nul af aan begonnen met een geheel nieuw besturingssysteem te schrijven...
Helaas moet ik het dus doen met wat ik al heb en probeer ik met zo min mogelijk moeite het toch weer netjes werkend te krijgen. Al ben ik me er terdege van bewust dat het soms geen mooie oplossingen zijn als ik opnieuw zou beginnen het anders zou aanpakken.
@ allen:
Misschien kan iemand me iets meer toelichting geven hoe ik met preg_match_all (o.g.) voor elkaar kan krijgen wat ik wil? Zie mijn vorige bijdrage/vraag aan Ivo.
Wat je dus wilt, als ik het goed begrijp, is het genereren van een table-of-contents (ToC) bij een soort van artikel.
Dit artikel staat in een apart bestand. Waarom? Stop deze artikelen in een database. Dit is je "rauwe" tekst.
Gebruik eventueel een WYSIWYG-editor (of in eerste instantie een textarea, dat is om het even) om deze rauwe teksten te beheren.
Vervolgens verzin je een of andere pseudo-code als "placeholder" voor je ToC, bijvoorbeeld [[toc]].
Deze klop je in in je rauwe tekst. Of je zet een vinkje bij je artikel die aangeeft dat er een table-of-contents gegenereerd moet worden, whatever floats your boat.
Als je vervolgens deze tekst opslaat verwerk je deze rauwe tekst, waarbij deze -en mogelijk andere- pseudo-codes/opties worden opgepikt en verwerkt tot een tekst -die je apart opslaat- die wordt gebruikt om weer te geven. Het zou nogal onzinnig zijn om al het rekenwerk elke keer opnieuw uit te voeren als je deze tekst weergeeft. Je hebt dan dus meteen een vorm van "caching" van je weer te geven tekst. De ToC kun je apart bij, of in de verwerkte tekst zelf, opslaan; en met CSS kun je deze toch positioneren waar je wilt.
Rest dus nog de code die acteert op [[toc]] (of een optie die je aanvinkt) voor het invoegen/apart opslaan van een ToC. Liefst wil je ook de bijbehorende id's in de headers genereren, zodat je daar geen omkijken naar hebt. Maar in eerste instantie ga ik er vanuit dat deze al aanwezig zijn, voor een wat simpelere implementatie.
Code volgt, misschien. Hangt er vanaf of dit zo snel lukt...
Toevoeging op 07/02/2016 14:21:49:
Zoiets dus:
<?php
header('Content-Type: text/html; charset=UTF-8');
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>table of contents</title>
</head>
<body><?php
// Je HTML tekst (input)
ob_start(); // output buffering :D
?><h1 id="1-introductie">1. Introductie</h1>
<h2 id="1.1-inleiding">1.1 Inleiding</h2>
<p>Blablabla</p>
<h3 id="1.1.1-subparagraaf">1.1.1 Subparagraaf</h3>
<p>Blablabla</p>
<h2 id="1.2-nogwat">1.2 Nog wat</h2>
<p>Lalalalal</p>
<h1 id="2-meer">2. Meer</h1>
<h2 id="2-1-vervolg">2.1 Vervolg</h2>
<p>Lalalalal</p>
<h3 id="2-1-1-enzo">2.1.1 Enzo</h3>
<p>Lalalalal</p>
<h4 id="2-1-1-1-edoch">2.1.1.1 Edoch</h4>
<p>Lalalalal</p>
<h3 id="2-1-2-maar">2.1.2 Maar</h3>
<p>Lalalalal</p>
<h2 id="2-2-en-ook">2.2 En ook</h2>
<p>Lalalalal</p>
<h1 id="3-dus">3. Dus</h1>
<p>Lalalalal</p><?php
$html = ob_get_clean();
// Regexp voor het vangen van alle headers.
preg_match_all('#<h([1-9])([^>]*)>([^<]*)<\/h\1>#', $html, $matches);
// Verzamel gegevens.
$toc = array();
// $matches[0][x] bevat totale header matches
// $matches[1][x] bevat de header nummers
// $matches[2][x] bevat alle overige data van de openingstag van een header, waaronder het id
// $matches[3][x] bevat de tekst tussen de header tags (de header titels)
foreach ($matches[1] as $k => $h) {
// abstraheer het id
$id = 'not found !';
if (preg_match('#id="([^"]*)"#', $matches[2][$k], $match) === 1) {
$id = $match[1];
} else {
// kon id niet uit de header tag vissen - doe iets?
}
$toc[] = array(
'header' => $h,
'title' => $matches[3][$k],
'bookmark' => $id,
);
}
// Bouw de ToC.
$currentDepth = 0;
ob_start(); //vang de HTML op
// Zet er een wrapper omheen
?><div class="toc"><?php
foreach ($toc as $i => $data) {
if ($i > 0 && $currentDepth == $data['header']) {
// item op zelfde niveau, sluit eerst vorige tag
?></li><?php
}
if ($data['header'] > $currentDepth) {
// we gaan altijd 1 niveau omhoog als je een hoger header nummer hebt, anders klopt je structuur niet
?><ul><?php
$currentDepth++; // altijd 1 niveau hoger
}
if ($data['header'] < $currentDepth) {
// we gaan weer een of meer niveaus omhoog, sluit deze tags
while ($currentDepth > $data['header']) {
?></li></ul><?php
$currentDepth--;
}
?></li><?php
}
?><li><a href="#<?php echo $data['bookmark'] ?>"><?php echo $data['title'] ?></a><?php
}
// sluit het restant
while ($currentDepth > 0) {
?></li></ul><?php
$currentDepth--;
}
// sluit de wrapper
?></div><?php
$tocHtml = ob_get_clean();
// $tocHtml bevat nu de ToC.
echo $tocHtml;
?></body>
</html>
Disclaimer: het genereren van de bulleted list is mogelijk niet syntactisch correct, maar in eerste opzicht ziet dit er goed uit, heb niet uitgebreid getest.
Dank je voor de uitgebreide code met toelichting. Ik moet het nog even goed bestuderen, maar het lijkt me dat dit doet wat ik met simple_html_doc ook doe, maar ik loop juist vast met de php die in de content staat. Of zie ik het verkeerd?
Of zou ik het volgende moeten doen:
<?
ob_start();
require 'mycontent.php'; //evalueert dit ook de interne php-code in de content?
$html = ob_get_clean();
$newhtml = bewerken ($html); //bewerken is even een fictieve functie
ob_start(); // om te zorgen dat de buffer weer aan staat en er geen output naar de browser wordt gezonden ivm een probleempje elders
echo $newhtml; // of moet ik nog een keer ob_get_clean gebruiken?
?>
En dan kan ik $html bewerken? Dan kan ik het ook met simple_html_dom bewerken neem ik aan ...