HTML, Excel, Word, SEOPHP курс для чайников ⇒ Управляющие структуры

PHP для "чайников"

Инструменты
Выбираем IDE
Выбираем Web-сервер
Выбираем СУБД
Структура языка PHP
Первый шаг
Синтаксис
Типы данных
Переменные и константы
Операторы
Выражения
Управляющие структуры
Функции
Классы
Исключения
Ошибки
Массивы
Глобальные массивы
Cookies
Сессии
Загрузка файлов
Работа с файлами
Работа с файлами на диске
Работа с данными в файле
Пример управления файлами
Работа с базами данных
Подключение
Анализ результатов
Выполнение запросов
Отключение
Пример: отслеживание пользователей
Работа в сети
Отправка почты
Безопасность
HTTP-аутентификация
Защита логином и паролем
Автоматизация
Регулярные выражения в PHP
Интеграция
PHP и JavaScript

 

Управляющие структуры

Автор: Артемьев Сергей Игоревич
ICQ: 438856621
email: _spin_@bk.ru

Все скрипты в PHP представляют собой набор различных выражений, которые выполняются последовательно. Выражения можно объединять в группы выражений при помощи т.н. "операторных скобок" "{" и "}". Группы выражений используются в основном вместе с управляющими конструкциями языка PHP.


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


Конструкции бинарного (двойственного) выбора позволяют в зависимости от условия выполнить либо первое, либо второе действие. В PHP эти конструкции представлены ключевыми словами if, else, elseif и endif.


Конструкция if позволяет выполнить какое-то действие, если условие истинно. Этот пример читается как "ЕСЛИ условие истинно ТО выполнить выражения".

<?php
    if(условие)
        одиночное_выражение;
    // или
    if(условие)
    {
        несколько;
        последовательных;
        выражений;
    }
?>

Конструкция else используется совместно с if и определяет действие, когда условие ложно. Нижеследующий пример читается как "ЕСЛИ условие истинно ТО выполнить выражения-1 ИНАЧЕ выполнить выражения-2".

<?php
    if(условие)
    {
       выражения-1;
    }
    else
    {
       выражения-2;
    }
?>

Конструкция elseif аналогична else, но позволяет создавать цепочки условий и действий. Приведённый ниже пример читается как "ЕСЛИ условие-1 истинно ТО выполнить выражения-1 ИНАЧЕ ЕСЛИ условие-2 истинно ТО выполнить выражения-2 ИНАЧЕ ...".

<?php
    if(условие-1)
    {
       выражения-1;
    }
    elseif(условие-2)
    {
       выражения-2;
    }
    elseif(условие-3)
    ...

?>

Конструкция endif может использоваться в случае альтерантивной формы записи управляющих конструкций. Отличие альтернативной формы от стандартной в том, что открывающая операторная скобка "{" заменяется на двоеточие ":", закрывающая скобка удалятся, а граница конструкции определяется по ключевому слову endXXX, где XXX - тип конструкции. Например, для связки if...endif...else тип конструкции - "if", значит граница будет определяться по ключевому слову "endif". Сравните:

<?php
    // Стандартная форма записи:
    if(условие-1)
    {
       выражения-1;
    }
    elseif(условие-2)
    {
       выражения-2;
    }
    else
    {
       выражения-3;
    }

    // Альтернативная форма записи:
    if(условие-1):
       выражения-1;
    elseif(условие-2):
       выражения-2;
    else:
       выражения-3;
    endif;

?>

Какой из форм пользоваться - каждый разработчик решает для себя сам, но большинство всё же придерживается стандартной формы записи (т.е. с нормальными операторными скобками "{" и "}")

Конструкция множественного выбора представляет собой компактную форму записи длинных цепочек условий вида "if...elseif....elseif.......else". В PHP такая конструкция носит название switch и имеет достаточно простую форму записи:

<?php
    switch (выражение/переменная)
    {
        case значение-1:
            выражения-1;
            break;
        case значение-2:
            выражения-2;
            break;
        ...

        default:
            выражения-N;
            break;
    }
?>

Т.е. мы указываем переменную или выражение, после чего указываем возможные значения и действия, соответствующие этим значениям. Все значения, которые мы явно не указали, попадут в блок "default". Замечательная особенность switch - возможность указывать список выражений одновременно для нескольких вариантов. Для этого несколько блоков "case" записываются последовательно, например:

<?php
    switch (выражение/переменная)
    {
        case значение-1:
        case значение-2:
        case значение-3:
        case значение-4:
            выражения_для_случаев_1_2_3_4;
            break;
        case значение-5:
            выражения_для_случая_5;
            break;
        ...
        default:
            выражения-N;
            break;
    }
?>

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

<?php
    $color = 'red';

    switch ($color)
    {
        case 'красный':
            echo 'Стоять';
            break;

        case 'красно-желтый':
            echo 'Приготовиться';
            break;

        case 'желтый':
            echo 'Остановиться';
            break;

        case 'желтый мигающий':
            echo 'По обстановке';
            break;

        case 'зелёный':
            echo 'Ехать';
            break;

        default:
            // например, светофор выключен
            echo 'По обстановке';
            break;
    }
?>

Конструкции повторения (организации циклов) предназначены для многократного выполнения одних и тех же выражений. К этим конструкциям относятся while, do-while, for и foreach.

While ("уайл") и do-while ("ду-уайл") предназначены для организации циклов в случаях, когда число повторений заранее неизвестно или может измениться в процессе выполнения цикла. Основой этих конструкций является логическое выражение (условие), а цикл повторяется до тех пор, пока условие истинно (равно TRUE).

Формальная запись конструкций выглядит так:

<?php
    while (условие)
    {
        выражения;
    }

    do
    {
        выражения;
    }
    while (условие);
?>

Главное отличие while от do-while в том, что do-while всегда выполняется хотя бы один раз даже если условие изначально ложно. Например:

<?php
    $i = 0;
    while ($i > 0)
    {
        echo 'i больше нуля! (цикл while)';
    }
    // не выводится ничего

    do
    {
        echo 'i больше нуля! (цикл do-while)';
    }
    while ($i > 0);

    // выводится "i больше нуля! (цикл do-while)"
?>

Из примера видно, что пользоваться циклом do-while нужно аккуратно, иначе есть большой риск получить неожиданные и парадоксальные результаты, такие как в нашем примере. Неверное применение циклов очень часто приводит к повялению логических ошибок, которые на порядок сложнее выявить и локализовать, нежели все прочие.

Конструкции while и do-while очень удобно использовать при построчном чтении из файла или обработке результатов запросов к базам данных, т.к. заранее неизвестно, сколько раз надо будет выполнить требуемый набор выражений.

<?php
    $i = 0;
    while ($i > 0)
    {
        echo 'i больше нуля! (цикл while)';
    }
    // не выводится ничего

    do
    {
        echo 'i больше нуля! (цикл do-while)';
    }
    while ($i > 0);

    // выводится "i больше нуля! (цикл do-while)"
?>

Следующая конструкция - for ("фор"). Эта конструкция предполагает, что количество итераций цикла заранее известно или вычислимо до начала цикла. Формально for записывается так:

<?php
    for (переменная; условие; оператор )
    {
        выражения;
    }
?>

Блок "переменная" описывает переменную-счётчик и её начальное значение, "условие" определяет количество итераций, а "оператор" - действие над переменной-счётчиком ПОСЛЕ каждой итерации. Например, если вам надо вывести 10 раз одну и ту же строку, можно воспользоваться таким кодом:

<?php
    for ($i = 0; $i < 10; $i++ )
    {
        echo "Копия строки номер " . $i;
    }
?>

Здесь мы указали, что $i - это переменная счётчик, считать начинаем с нуля, после каждой итерации учеличиваем $i на единицу, продолжаем итерации пока $i меньше 10. Приведённй код цикла функционально эквивалентен следующему (записанному без цикла):

<?php
    echo "Копия строки номер 0";
    echo "Копия строки номер 1";
    ...
    echo "Копия строки номер 9";
?>

Для цикла for совершенно не обязательно знать количество итераций на этапе написания скрипта. Главное - мы должны суметь вычислить это количество и передать в цикл. Например:

<?php
    // код можно использовать, например, для
    // создания навигатора по
    // страницам каталога товаров

    // общее количество элементов в каталоге
    $rows = 100;

    // количество одновременно отображаемых
    // элементов на странице
    $rows_per_page = 16;

    // вычисляем количество страниц
    $pages = ceil($rows/$rows_per_page);

    $page_line = '';

    // для каждой страницы создаём соответствующую ссылку
    for ($i = 0; $i < $pages; $i++ )
    {
        $page_line .= '<a href="?page=' . $i .
                '">[' . ($i + 1) . ']</a>';
    }

    // выводим готовую строку навигации
    echo $page_line;
    // выведет "[1][2][3][4][5][6][7]";
?>

Последняя конструкция циклов - foreach. Это самая простая и самая своеобразная конструкция из рассмотренных. Записывается она так:

<?php
    foreach(массив as формат_элемента)
    {
        выражения;
    }
?>

Здесь "массив" - переменная типа array, созданная ранее, а "формат_элемента" - это формальное описание одного элемента массива. Рассмотрим на примерах:

<?php
    // одномерный не-ассоциативный массив
    $names = array('Александр', 'Владимир', 'Ярослав');

    foreach($names as $single_name)
    {
        echo 'имя из массива:' . $name . '<br />\n';
    }

    // одномерный ассоциативный массив
    $names = array(
                'Имя' => 'Александр',
                'Фамилия' => 'Владимирович',
                'Отчество' => 'Генералов',
                'Телефон' => '+7(123)456-78-90');

    foreach($names as $param => $value)
    {
        echo $param . ': ' . $value . '<br />\n';
    }

?>

При использования многомерных массивов в foreach они будут интерпретироваться как вложенные ассоциативные массивы. Если в последнем примере $names будет двумерным массивом, то $param будет содержать номер массива перового уровня, а $value - массив второго уровня. Подробнее о массивах и работе с ними мы поговорим в соответствующем уроке.

Цикл foreach перебирает все элементы массива, независимо от их количества. Недостаток этой конструкции - невозможность модификации элементов массива во время итерации. Связано это с тем, что foreach перед началом цикла создаёт копию массива, которая уничтожается после окончания цикла. Следовательно, все изменения при выходе из цикла теряются. Этот недостаток был исправлен в PHP версии 5 и выше за счет добавления ссылки на элемент данных:

<?php
    // одномерный не-ассоциативный массив
    $names = array('Александр', 'Владимир', 'Ярослав');

    foreach($names as &$single_name)
    {
        $name .= 'ович';
    }

    echo implode(', ', $names);
    // в PHP до 5 версии выведет:
    // "Александр, Владимир, Ярослав"
    // в PHP 5 выведет:
    // "Александрович, Владимирович, Ярославович"
?>

Специально для управления исполнением циклов и скриптов в PHP существует несколько ключевых слов: break, continue и return.

break применяется внутри циклов и служит для немендленного прекращения итераций цикла. Управление передаётся на следующее после цикла выражение. Например, можно прервать цикл при возникновении определённых условий:

<?php
    $names = ('Ярослав', 'Александр', ...);
    foreach($i = 0; $i < 100; $i++)
    {
        if($names[$i] == 'Александр') break;
    }
    echo 'Имя "Александр" стоит на ' . $i . ' позиции';

    // выведет:
    // 'Имя "Александр" стоит на 2 позиции'
?>

break очень полезен в случае поиска нужного элемента массива, т.к. можно остановить поиск сразу после нахождения нужного элемента и не лопатить заведомо пустой остаток массива.

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

<?php
    $names = ('Ярослав', 'Александр', ...);
    foreach($i = 0; $i < 100; $i++)
    {
        if($names[$i] != 'Александр') continue;
        echo 'Имя "Александр" стоит на ' . $i . ' позиции';
    }

    // выведет:
    // 'Имя "Александр" стоит на 2 позиции'
?>

Такой цикл переберёт все элементы массива и выполнит код "echo ..." только для тех элементов, где значение равно "Александр". Такое построение цикла удобно применять для случаев, когда выражения должны быть применены к нескольким элемента массива.

Последнее ключевое слово - return. Оно предназначено для немедленного выхода из функции и возврата значения (при необходимости). Подробнее об использовании return мы поговорим при рассмотрении функций.

Последняя группа конструкций - конструкции включения. Они предназначены для включения в текст скрипта каких-либо данных и кода, находящихся в другом файле. Всего существует четыре варианта: include, include_once, require, require_once.

Конструкции с приставкой "_once" отличаются от прочих тем, что гарантируют однократное включение файла в рамках всех задействованых файлов. Т.е. если у вас есть 10 файлов и в каждом необходимо подключить файл с описанием, например, класса, то при использовании обычных require или include PHP выдаст ошибку "недопустимо повторное обявление класса" уже на второй встретившейся команде включения. С другой стороны, include_once или require_once предварительно проверят предыдущие включения, и если файл уже был подключен - повторно подключать его не будут.

Отличие между include и require заключено в поведении при отсутсвующем файле для подключения. Если include или inclide_once не находят указанный файл, то выдают предупреждение для пользователя. А вот require и require_once генерируют ошибку и прекращают дальнейшее выполнение скрипта.

Формат всех четырёх конструкций практически одинаков. Имена подключаемых файлов можно записывать как в полной, так и сокращённой форме.

<?php
    include('engine/filename.php');
    include_once('myclass.class.php');
    require('./../utils/db.php');
    require_once('./../config/config_db.inc');

?>

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



В начало страницы



В начало страницы