Как PHP выполняет рекурсивные вызовы функций? - PullRequest
1 голос
/ 30 октября 2008

PHP (в том числе) сначала выполнит самую глубокую функцию, выходя из нее. Например,

$text = strtoupper(str_replace('_', ' ', file_get_contents('file.txt')));

Я делаю что-то очень похожее на приведенный выше пример для анализатора шаблонов. Похоже на теги

{@tag_name}

и заменяет его переменной с именем $ tag_name . Еще один пример:

$a = 'hello';
$b = ' world';
INPUT = 'This is my test {@a{@b}} string.';
OUTPUT (step 1) = 'This is my test {@a} world string.';
OUTPUT output = 'This is my test hello world string.';

Как я могу это сделать? Имеет ли это смысл? Если нет, я могу попытаться объяснить лучше.

Ответы [ 4 ]

4 голосов
/ 31 октября 2008

Я не уверен, что понимаю вложение в вашем примере, так как пример не демонстрирует цели, стоящей за вложением. Ваш пример ввода очень легко может быть

'This is my test {@a} {@b} string.'

И использование массивов в str_replace справится с этим очень просто и быстро.

$aVars = array('{@a}' => 'hello', '{@b}' => 'world');
$sString = 'This is my test {@a} {@b} string.';

echo str_replace(array_keys($aVars), array_values($aVars), $sString);

Что дает нам

Это моя тестовая строка "Hello World".

Теперь, рекурсивная функция для этого не слишком сложна, хотя я не уверен, что понимаю, насколько это было бы полезно. Вот рабочий пример:

<code>function template($sText, $aVars) {
    if (preg_match_all('/({@([^{}]+)})/',
                       $sText, $aMatches, PREG_SET_ORDER)) {
        foreach($aMatches as $aMatch) {
            echo '<pre>' . print_r($aMatches, 1) . '
'; if (array_key_exists ($ aMatch [2], $ aVars)) { // заменить парня внутри $ sText = str_replace ($ aMatch [1], $ aVars [$ aMatch [2]], $ sText); // теперь снова просматриваем текст, так как у нас есть новые переменные $ sText = template ($ sText, $ aVars); } } } вернуть $ sText; }

Этот print_r покажет вам, как выглядят совпадения, чтобы вы могли следить за функцией по ее шагам. Теперь попробуем ...

$aVars = array('a' => 'hello', 'b' => 'world');
$sStringOne = 'This is my test {@a} {@b} string.';
$sStringTwo = 'This is my test {@a{@b}} string.';

echo template($sStringOne, $aVars) . '<br />';

Первый результат:

Это моя тестовая строка "Hello World".

Теперь попробуем две строки

echo template($sStringTwo, $aVars) . '<br />';

Второй результат:

Это моя тестовая строка {@aworld}.

Это вполне может быть тем, что вы ищете. Очевидно, вам понадобится переменная aworld, чтобы это работало рекурсивно ...

$aVars = array('a' => '', 'b' => '2', 'a2' => 'hello world');

echo template($sStringTwo, $aVars) . '<br />';

И наш результат.

Это моя тестовая строка "Hello World".

И просто для развлечения с рекурсией ...

$aVars = array('a3' => 'hello world', 'b2' => '3', 'c1' => '2', 'd' => '1');
$sStringTre = 'This is my test {@a{@b{@c{@d}}}} string.';

echo template($sStringTre, $aVars) . '<br />';

Это моя тестовая строка "Hello World".

Не уверен, что вы просите об этом ...

1 голос
/ 30 октября 2008

Используйте стек - поместите сверху array_push каждый открытый элемент и оцените самый верхний array_pop по первой отметке закрытия.

1 голос
/ 30 октября 2008

Это не тривиальная задача. Вам нужно разобрать строку вручную и сделать свои собственные логические подстановки. Там нет волшебной функции или функциональности, которая сделает это за вас.

Мой собственный шаблонизатор справляется с этим (и не только), и весит только ядро ​​(без макросов шаблонов) при 600+.

0 голосов
/ 30 октября 2008

По крайней мере, в данном примере я не понимаю, почему токен @b будет вложен в токен @a. Эти двое, похоже, не нуждаются друг в друге. Вы пытаетесь сделать что-то подобное в Perl?

$a = "b";
$b = "Hello World!";

print $$a;

вывод будет "Hello World"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...