Ik ben bezig met het upgraden van de applicatie die hier intern gebruikt wordt. We gaan van PHP7.2 naar PHP8.1. Daarnaast maakt het systeem gebruik van Smarty Templating. Bij het genereren van een template waarin Block Functions worden gebruikt, loopt het vast. Resultaat is géén error, maar een wit scherm.
Ik heb een test template met deze code:
<div>Een of andere tekst</div>
Deze wordt gerenderd. Geen probleem. Maar dan deze:
<div>{translate}Een of andere tekst{/translate}</div>
Wit scherm. Het 'registeren' van deze blockfunctie gaat goed. Want als ik de bedoelde method
smarty_waf_translate
hernoem, dan gaat die registry niet goed. Dus Smarty vindt de plugin wel degelijk.
Zo'n wit scherm had ik hier al eerder geplaatst. De functie
class_exists()
zorgt ervoor dat de autoload wordt afgevuurd en resulteerde óók in een wit scherm. Ik heb deze opgelost met een workaround. Maar nu zit ik dus vast aan een wit scherm bij het afvuren van block functions.
Ik heb xDebug in PHPStorm aan de praat gekregen en kan de code helemaal tot diep in smartyview code volgen. En dáár gaat het ergens fout. Dit, terwijl Smarty compatible zou moeten zijn met PHP8.1. Daarnaast, áls het überhaupt al ligt aan de code van Smarty, dan zou de hele wereld met het probleem moeten komen.
Dus wat nu dan?
Ik heb het gevoel dat het aan serverinstellingen ligt. Heb al de php.ini van de server met PHP 7.2 op mijn lokale PHP 8.1 server gezet. Dat gaf het verrassende resultaat dat mysqli_report() niet gedefinieerd was. Maar dit was een false flag. Dus daar kwam ik geen stap verder mee.
Goeie. Maar nee. Ik heb gekeken of in de PHP.ini de "default_charset" ingesteld stond op UTF-8. Dit was het geval.
Daarna gekeken of in de "httpd.conf" de regel "AddDefaultCharset UTF-8" stond. Dit was niet het geval. Dus toegevoegd en opnieuw opgestart, maar geen resultaat.
Oké, door die regel telkens op een 'verdere' plek in je code te zetten, kun je makkelijk bepalen op welk moment de fout ontstaat. Je volgende stap zou bijvoorbeeld dit kunnen zijn:
?>
Zie je nu ineens de sterretjes niet meer? Dan zit de fout dus in:
$this->html = $smarty->fetch($modTemplate);
Vervolgens kun je dan in die fetch() functie weer hetzelfde 'trucje' toepassen en zo kom je steeds dichter bij het punt waar er iets niet goed gaat. Ongeveer hetzelfde wat jouw editor ook doet, alleen doe je dat nu handmatig. Ik vind het persoonlijk wat makkelijker werken, maar wellicht vind jij de debug-functie van de editor handiger. Je moet het maar eens proberen.
Ik heb zelf ook zo aan debuggen gedaan en dat werkt inderdaad tot op zekere hoogte wel. Alleen niet in dit geval. Het probleem zit heel diep in de Smarty code en dan is het wel handig dat je breakpoints kan invoeren met één klik. Die breakpoints die je in PHP Storm invoert zijn eigenlijk ook exit() of die(). Maar dan met een volledige var_dump van alle variabelen.
Maar omdat je dus snel breakpoints kunt zetten en vanaf je breakpoint stapsgewijs de volgende regel kunt parsen totdat het fout gaat is het me dus na lang onderzoek gelukt om de bron van de ellende te achterhalen. De oplossing heb ik nog niet, maar het is wel een heel frappant iets en ik had er ook hier op deze site al eerder over geschreven.
Dit is de regel/code die de fout veroorzaakt:
$class_name = 'Smarty_Internal_Compile_' . implode('_', $_tag);
if (class_exists($class_name) ...
Wat Smarty hier doet is het volgende.
Ten eerste is het nodig de template te weten. In het kort is het dit:
<div>{translate}Vertaal dit naar het engels{/translate}</div>
Bij het parsen van de template ziet hij die {translate} en probeert éérst op de plek van de PHP code die ik aanwijs te achterhalen of er een SMARTY class van bestaat. Nu, die bestaat niet, want het is mijn eigen custom plugin.
Omdat de class niet bestaat, moet ie door met andere mogelijkheden, waaronder dus kijken of {translate} een plugin is. Maar daar komt ie niet.
class_exists()
Wat doet deze method? Die zegt ten eerste natuurlijk of de class bestaat. Bestaat ie niet, dan vuurt ie de autoload af om te zien of de class nadat de autoload is afgevuurd wél bestaat. En dáár gaat het mis. De autoload afvuren lukt niet waardoor hij hangt.
Maar waarom? Ik weet het niet. Ik heb dit al eerder gezien. Als ik een bestand in de root van de applicatie doe en een class_exists() uitvoer dan is er geen probleem. Maar staat het bestand in zeg maar /modules/orders/module.php, dan werkt het niet. Dan klapt ie eruit met een wit scherm. Ik heb dat destijds opgelost met een workaround, omdat de code van de applicatie zelf was. Maar nu is het van Smarty, een 3e partij, dus kan ik die code niet aanpassen.
Het is nu dus tijd om dat witte scherm na een class_exists() goed op te lossen. Maar waar ligt het aan? Ik weet dat het én op de server zelf gebeurt, maar ook op mijn lokale machine én ook op de lokale machine van een externe developer collega die ik heb ingehuurd.
Iedereen bedankt zover en bedankt voor het meedenken in het oplossen van de class_exists.
...dan moet ie de function 'smarty_waf_translate' uitvoeren. Dat weet ie, omdat je dat bij registerPlugin in de tweede parameter hebt toegekend aan de {translate} tag.
Smarty controleert echter eerst of er een betreffende class bestaat.
Bestaat die niet, dan gaat ie door met de rest van de code, waaronder kijken of het een plugin betreft zodat ie de 'smarty_waf_translate' function kan uitvoeren.
Maar dat is in feite niet van belang bij het oplossen van dit probleem. Het probleem is dat als je een class_exists uitvoert op een class die niet bestaat dan hangt de hele applicatie en doet ie verder niks meer. Je moet dan natuurlijk gewoon wel verder kunnen, al doe je class_exists('belachelijkeclassdienietbestaat'), dan moet je geen wit scherm krijgen.
Ik zoek dus een oplossing om class_exists() by default te laten werken. Dus dat ie blijft werken als ie de autoload ook afvuurt.