2015-02-28 1 views
11

Я пытаюсь поддерживать две версии кода PHP в одном файле с помощью version_compare, но у меня все еще есть ошибка.Как я могу кодировать для нескольких версий PHP в том же файле без ошибок?

Код:

if (version_compare(PHP_VERSION, '5.3.0') >= 0) { 
    $alias = preg_replace_callback('/&#x([0-9a-f]{1,7});/i', function($matches) { return chr(hexdec($matches[1])); }, $alias); 
    $alias = preg_replace_callback('/&#([0-9]{1,7});/', function($matches) { return chr($matches[1]); }, $alias); 
} else { 
    $alias = preg_replace('/&#x([0-9a-f]{1,7});/ei', 'chr(hexdec("\\1"))', $alias); 
    $alias = preg_replace('/&#([0-9]{1,7});/e', 'chr("\\1")', $alias); 
} 

Но я получаю:

PHP Parse error: syntax error, unexpected T_FUNCTION

На preg_replace_callback() звонки, вероятно, из-за анонимных функций.

+4

Я знаю, что на практике это не всегда так просто, но одно решение в этом случае просто не поддерживает [версии PHP, для которых официально не доступны патчи безопасности) (http://php.net/eol. php), который на момент написания означает, что ваша минимальная поддерживаемая версия должна быть 5.4! – IMSoP

+0

Большинство сайтов, которые я построил, для 5.2, к сожалению, вне моего управления, к сожалению, – orbitory

ответ

16

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

Если проверка ворса не выполняется для этой версии, она не будет работать, независимо от разветвленности:

> php -l file.php 
> PHP Parse error: syntax error, unexpected T_FUNCTION 
+0

он может объявить функцию как 'имя функции (args)', а затем передать как строку 'name' в' preg_replace_callback' –

+2

@kmlnvm Не меняет этот ответ, которая по-прежнему правильна - ОП задает вопрос о том, как использовать новый синтаксис *, когда это возможно, через условное. – user2864740

+0

Я так и думал, thx – orbitory

2

Просто сделай это так, и он должен работать для версий PHP под 5.3, которая не поддерживает анонимные функции:

function one($matches) { 
    return chr(hexdec($matches[1])); 
} 

function two($matches) { 
    return chr($matches[1]); 
} 

$alias = preg_replace_callback('/&#x([0-9a-f]{1,7});/i', "one", $alias); 
                 //^^^^ See here I 
                 //just passed the function name 
                 //as string 
$alias = preg_replace_callback('/&#([0-9]{1,7});/', "two", $alias); 
+0

Я думал об этом, но не идеален, я, вероятно, надеялся на оболочку кода, которая сообщает компилятору не анализировать этот PHP-код, как и для другой версии. – orbitory

+0

@ orbitory. Думаю, вы не получите очень далеко от своей надежды: D – Rizier123

+0

просто спрашиваю :), я реализовал ваше решение, но это не совсем правильный ответ. – orbitory

17

Одним из вариантов было бы поместить код в отдельные файлы, например, так:

if (version_compare(PHP_VERSION, '5.3.0') >= 0) { 
    include('file-5.3.0.php'); 
} else { 
    include('file-5.x.php'); 
} 

Затем внутри file-5.3.0.php, добавьте соответствующий код:

$alias = preg_replace_callback('/&#x([0-9a-f]{1,7});/i', function($matches) { return chr(hexdec($matches[1])); }, $alias); 
$alias = preg_replace_callback('/&#([0-9]{1,7});/', function($matches) { return chr($matches[1]); }, $alias); 

... и внутри file-5.x.php добавить оставшийся код:

$alias = preg_replace('/&#x([0-9a-f]{1,7});/ei', 'chr(hexdec("\\1"))', $alias); 
$alias = preg_replace('/&#([0-9]{1,7});/e', 'chr("\\1")', $alias); 
+0

Я думал об этом, но не идеален, я, вероятно, надеялся на оболочку кода, которая сообщает компилятору не анализировать этот php-код, как и для другой версии – orbitory

+2

@orbitory: PHP не скомпилирован, он интерпретируется =) – Mints97

+2

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

6

Синтаксический PHP файлы происходит перед тем запускается какой-либо код. if-Approach никогда не будет работать через один и тот же блок кода - то есть. PHP-файл. (И нет, я не буду один, чтобы предложить «Eval».)

Однако, если был другой включен файл (один для каждой версии), то if мог выбрать, какой файл включить - но каждый файлов должен по-прежнему синтаксически корректен в PHP-версии/контексте, в котором он разбирается.

Это фактически «разумный» подход к использованию , если вы используете инъекцию зависимостей или некоторые его варианты - если действительно важно поддерживать различные реализации компонентов. Это связано с тем, что контейнер/настройка IoC определит, какие файлы (файлы)/реализация (ы) включить, а потребители услуг будут агностическими для изменения.

2

Вы можете использовать eval и heredoc notation, но как указано Ilmari Karonen, heredocs действуют как строки с двойными кавычками, а переменные будут интерполированы. Для этого требуется, чтобы все знаки $ были экранированы, что может быть беспорядочным.

В качестве альтернативы вы можете использовать eval и nowdoc notation, который, к сожалению, доступно только в PHP 5.3.0 и выше. eval обычно запрещен, но в этой ситуации строка не указана пользователем и поэтому нет угрозы безопасности.

if (version_compare(PHP_VERSION, '5.3.0') >= 0) { 
    eval(<<<'CODE' 
    $alias = preg_replace_callback('/&#x([0-9a-f]{1,7});/i', function($matches) { return chr(hexdec($matches[1])); }, $alias); 
    $alias = preg_replace_callback('/&#([0-9]{1,7});/', function($matches) { return chr($matches[1]); }, $alias); 
CODE 
    ); 
} else { 
    eval(<<<'CODE' 
    $alias = preg_replace('/&#x([0-9a-f]{1,7});/ei', 'chr(hexdec("\\1"))', $alias); 
    $alias = preg_replace('/&#([0-9]{1,7});/e', 'chr("\\1")', $alias); 
CODE 
    ); 
} 

Насколько я знаю, это ближе всего к намерению ОП. Кроме того, если есть хорошее время и место для использования eval, эта ситуация точно такова, что время и место.

+1

Unfornato, это не будет работать так, как написано, потому что все, что похоже на переменную, будет интерполировано в heredoc * до * eval. (См. [Это демо на Ideone] (http://ideone.com/ZXGBuq), с 'echo' вместо' eval'.) Вы можете исправить это, используя [nowdocs] (http://php.net/manual /en/language.types.string.php#language.types.string.syntax.nowdoc), но они поддерживаются только с PHP 5.3; альтернативой было бы избежать каждого символа '$' (и '' '' ') в убранном коде с обратным слэшем, который работает, но является уродливым и утомительным (не говоря уже о склонности к ошибкам). –

+0

О, хорошо, что отстой. Спасибо, я добавил это к этому ответу. –

5

Я знаю этот ответ, почему ваш получаю синтаксическую ошибку, но другой вариант заключается в использовании create_function(), который совместим с PHP v4 и v5 ...

$alias = preg_replace(
       '/&#x([0-9a-f]{1,7});/i', 
       create_function(
        '$matches', 
        'return chr(hexdec($matches[1]));' 
      ), 
       $alias); 
$alias = preg_replace(
       '/&#([0-9]{1,7});/', 
       create_function(
        '$matches', 
        'return chr($matches[1]);' 
      ), 
       $alias); 

Следует также отметить, что PHP не поддержка условной компиляции, как и другие языки программирования (например, C/C++). Однако, как заявили другие, вы можете использовать его, используя require(), include() или eval().