Как этот действительный php-код?

Я изменяю шаблон Wordpress, и мне любопытно, как это допустимая структура управления в PHP. У кого-нибудь есть понимание?

<?php if(condition): ?>
<?php if(!condition || !function()) ?>
<?php elseif(condition): ?>
<?php if(!condition || !function()) ?>
<?php endif; ?>

Если я удалю все теги, я получаю (с более строгим отступом):

<?php
if(condition):
    if(!condition || !function())
elseif(condition):
    if(!condition || !function())
endif;
?>

что недействительно, поскольку отступы if не заканчиваются. Итак, как/почему этот код действителен, если во всем мире открываются и закрываются теги php?


Изменить для Kerrek SB. Создайте файл php и запустите его. Это действительно:

<?php if(true): ?>
<?php if(true) ?>
<?php endif; ?>
<?php echo 'here'; ?>

Ответ 1

Ваш (приведенный) примерный код эквивалентен этому:

<?php
if(condition):
    if(!condition || !function()) { }
endif;
?>

Или даже:

<?php
if(condition):
    if(!condition || !function());
endif;
?>

Закрыв тэг <?php, вы получите бесплатную "пустое выражение".

Ваш реальный пример может быть однострочным:

<?php if(true): if(true); endif; echo 'here'; ?>

Но обратите внимание, что elseif делает это двусмысленным!

<?php
if(condition):
    if(!condition || !function());
elseif(condition):   // Bogus! which block does this belong to?
    if(!condition || !function());
endif;
?>

Нам нужно было бы устранить эту проблему:

<?php
if(condition):
{
    if(!condition || !function());
}
elseif(condition):
{
    if(!condition || !function());
}
endif;
?>

Теперь ясно, но теперь мы могли бы полностью избавиться от синтаксиса двоеточия.

Спасибо Лекенштейну за то, что указали это!

См. обсуждение ниже для дальнейших странностей.

Ответ 2

Ваш код не будет работать, потому что PHP удаляет одну новую строку после ?>, если она существует. ?>[newline]<?php будет таким же, как ?><?php

Что-то вроде ниже имеет смысл (function заменяется на fn, так как function - это ключевое слово;)):

<?php if(condition): ?>
<?php if(!condition || !fn()) ?>
some
<?php elseif(condition): ?>
<?php if(!condition || !fn()) ?>
thing
<?php endif; ?>

Он будет интерпретироваться как:

<?php
if(condition): 
    if(!condition || !fn()) echo "some";
elseif(condition):
    if(!condition || !fn()) echo "thing";
endif;
?>

Обратите внимание, что на двух ifs нет :, они будут обрабатываться как if, которые ожидают тела рядом с ним. Написано другим способом:

<?php
if (condition) {
    if (!condition || !fn()) {
        echo "some";
    }
} else if (condition) {
    if (!condition || !fn()) {
        echo "thing";
    }
}
?>

Ответ 3

Если вы не используете, вам нужно следить за: для логики после вложенных if (s).

    <?php
    function foobar() {
            return true;
    }
    function bar() {
            return false;
    }

    $foobar = true;
    $bar = false;

    if($foobar):
        if(!$bar || !foobar()):
            echo 'foobar';
        endif;
    elseif($bar):     
        if(!$foobar || !bar()):
            echo 'bar';
        endif;
    endif;

Ответ 4

", что является недопустимым, поскольку инструкции с отступом if не заканчиваются"

Да, да. Как указано на php.net, смешение обеих нот не поддерживается, а значит, у вас есть новый код-блок (два if() без следующей двойной точки) в ваших if():, elseif(): и endif;.

if(condition):
    if(!condition || !function())
        // do nothing here, end of first inner if
elseif(condition):
    if(!condition || !function())
        // also do nothing here, end of second inner if
endif; // end of outer if/else

Ответ 5

что является недопустимым, поскольку инструкции с отступами if не заканчиваются

Собственно, это так. ?> завершает оператор, как и любой другой, поэтому:

<?php
if(condition):
    if(!condition || !function());
elseif(condition):
    if(!condition || !function());
endif;
?>

Если бы это было не так, тогда также была бы синтаксическая ошибка:

Lol <?php echo "cakes" ?> extravaganza <?php echo "innit" ?>

Ответ 6

Я вижу, что вы смешиваете две возможные формы построения "if" в php.

Первая форма:

if ( condition ) instruction;

if ( condition ) { more; than; one; instructions; }

Второй:

if ( condition ): instruction; another; endif;

Когда вы пишете

  <?php if (condition) ?>

... без тега '{' или ':' перед тегом закрытия?? > , на самом деле вы усекаете команду if, опускающую инструкции, и PHP это принимает. Когда вы снова откроете тег php, вы уже находитесь за пределами if.

То же самое не применимо, если вы просто "забудете" инструкцию в одном блоке, где "endif;" не разрешено в качестве инструкции;

Итак:

<?php if (condition) ?>
anything outside the if
<?php instruction_outside_the_if; ?>

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

<?php if (condition 1): ?> <!-- note the ':' in this if -->
<?php if (condition 2) ?>
anything outside the second if but inside the first
<?php endif; ?> <!-- this closes the first if

... здесь у вас есть первое, если это работает, но второе по-прежнему пусто.

<?php if (condition 1): ?> <!-- note the ':' in this if -->
<?php if (condition 2) ?>
anything outside the second if but inside the first
<?php else: ?>
still outside the second if but inside the first, in the ELSE part
<?php endif; ?> <!-- this closes the first if

... это более или менее похоже на ваш пример, где else (или elseif) принадлежит первому, если.


<?php if (true) ?>
<?php elseif(foo){ }; ?>

Это другое исключение, поскольку вы не помещаете ничего между закрывающим тегом и открывающим тегом, поэтому парсер "оптимизирует" их (это не совсем так, но это правильное приближение). Попробуйте поставить что-нибудь между двумя тегами php, например:

<?php if (true) ?>
anything
<?php elseif(foo){ }; ?>

... и увидите "синтаксическую ошибку, неожиданный T_ELSEIF".