Перейти к содержимому

7. Циклы

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

  • Цикл while
  • Цикл do-while
  • Цикл for
  • Цикл foreach (для массивов)
  • break и continue
  • Вложенные циклы
  • Альтернативный синтаксис для шаблонов

Выполняется пока условие истинно.

<?php
// Базовый синтаксис
$i = 1;
while ($i <= 5) {
echo "Итерация $i<br>";
$i++;
}
// Обратный отсчет
$countdown = 10;
while ($countdown > 0) {
echo "$countdown...<br>";
$countdown--;
}
echo "Пуск!";
// Чтение файла построчно
$file = fopen("data.txt", "r");
while (!feof($file)) {
$line = fgets($file);
echo htmlspecialchars($line) . "<br>";
}
fclose($file);
?>
```text
### Бесконечный цикл (осторожно!)
```php
<?php
// ❌ Зависнет! Условие всегда true
/*
$i = 1;
while ($i <= 5) {
echo $i;
// Забыли $i++
}
*/
// ✅ Правильно
$i = 1;
while ($i <= 5) {
echo $i;
$i++; // Обязательно меняем условие!
}
// Иногда бесконечный цикл нужен (серверные скрипты)
/*
while (true) {
processQueue();
sleep(1); // Пауза 1 секунда
}
*/
?>
```text
## Цикл do-while
Похож на while, но выполняется минимум 1 раз (проверка условия в конце).
```php
<?php
// while — может не выполниться ни разу
$i = 10;
while ($i < 5) {
echo $i; // НЕ выполнится
}
// do-while — выполнится минимум 1 раз
$i = 10;
do {
echo $i; // Выполнится 1 раз
$i++;
} while ($i < 5);
// Практический пример: валидация ввода
do {
$input = readline("Введите число от 1 до 10: ");
} while ($input < 1 || $input > 10);
echo "Вы ввели: $input";
?>
```text
## Цикл for
Удобен когда заранее известно количество итераций.
```php
<?php
// Синтаксис: for (инициализация; условие; инкремент)
for ($i = 1; $i <= 5; $i++) {
echo "Итерация $i<br>";
}
// Обратный порядок
for ($i = 10; $i >= 1; $i--) {
echo "$i<br>";
}
// Шаг 2
for ($i = 0; $i <= 20; $i += 2) {
echo "$i "; // 0 2 4 6 8 10...
}
// Таблица умножения
for ($i = 1; $i <= 10; $i++) {
echo "5 × $i = " . (5 * $i) . "<br>";
}
// Генерация списка лет
$current_year = date("Y");
echo "<select>";
for ($year = $current_year; $year >= 1950; $year--) {
echo "<option value='$year'>$year</option>";
}
echo "</select>";
?>
```text
### Части for могут быть пустыми
```php
<?php
// Инициализация вне цикла
$i = 0;
for (; $i < 5; $i++) {
echo $i;
}
// Инкремент внутри цикла
for ($i = 0; $i < 5; ) {
echo $i;
$i++;
}
// Бесконечный цикл
for (;;) {
// Все части пустые = while(true)
break; // Без break зависнет!
}
?>
```text
## Цикл foreach
Специально для перебора массивов.
```php
<?php
// Индексированный массив
$fruits = ["яблоко", "банан", "апельсин"];
foreach ($fruits as $fruit) {
echo "$fruit<br>";
}
// С индексами
foreach ($fruits as $index => $fruit) {
echo "$index: $fruit<br>";
}
// 0: яблоко
// 1: банан
// 2: апельсин
// Ассоциативный массив
$user = [
"name" => "Иван",
"email" => "[email protected]",
"age" => 25
];
foreach ($user as $key => $value) {
echo "$key: $value<br>";
}
// name: Иван
// age: 25
// Только значения
foreach ($user as $value) {
echo "$value<br>";
}
?>
```text
### Модификация элементов массива
```php
<?php
$numbers = [1, 2, 3, 4, 5];
// ❌ Не изменит исходный массив (копия)
foreach ($numbers as $num) {
$num = $num * 2;
}
print_r($numbers); // [1, 2, 3, 4, 5] - не изменился
// ✅ Изменит исходный массив (по ссылке &)
foreach ($numbers as &$num) {
$num = $num * 2;
}
unset($num); // Важно! Удаляем ссылку
print_r($numbers); // [2, 4, 6, 8, 10]
// Альтернатива: использовать индексы
foreach ($numbers as $key => $num) {
$numbers[$key] = $num * 2;
}
?>
```text
### Перебор многомерных массивов
```php
<?php
$users = [
["name" => "Иван", "age" => 25],
["name" => "Мария", "age" => 30],
["name" => "Петр", "age" => 28]
];
foreach ($users as $user) {
echo "Имя: {$user['name']}, Возраст: {$user['age']}<br>";
}
// С вложенным foreach
$products = [
"Электроника" => ["Ноутбук", "Смартфон", "Планшет"],
"Одежда" => ["Футболка", "Джинсы", "Куртка"],
"Книги" => ["PHP", "JavaScript", "Python"]
];
foreach ($products as $category => $items) {
echo "<h3>$category</h3><ul>";
foreach ($items as $item) {
echo "<li>$item</li>";
}
echo "</ul>";
}
?>
```text
## break и continue
Управляют выполнением циклов.
### break — выход из цикла
```php
<?php
// Поиск числа
$numbers = [5, 12, 8, 20, 3, 15];
$search = 20;
foreach ($numbers as $num) {
if ($num == $search) {
echo "Найдено: $num";
break; // Прекращаем поиск
}
}
// Первое простое число
for ($i = 2; $i <= 100; $i++) {
$is_prime = true;
for ($j = 2; $j < $i; $j++) {
if ($i % $j == 0) {
$is_prime = false;
break; // Не простое, выходим
}
}
if ($is_prime) {
echo "Первое простое: $i";
break; // Нашли, выходим из внешнего цикла
}
}
?>
```text
### continue — пропуск итерации
```php
<?php
// Печатаем только четные числа
for ($i = 1; $i <= 10; $i++) {
if ($i % 2 != 0) {
continue; // Пропускаем нечетные
}
echo "$i "; // 2 4 6 8 10
}
// Пропускаем пустые элементы
$items = ["яблоко", "", "банан", null, "апельсин", ""];
foreach ($items as $item) {
if (empty($item)) {
continue; // Пропускаем пустые
}
echo "$item<br>";
}
// Пропускаем забаненных пользователей
$users = [
["name" => "Иван", "banned" => false],
["name" => "Петр", "banned" => true],
["name" => "Мария", "banned" => false]
];
foreach ($users as $user) {
if ($user['banned']) {
continue; // Пропускаем забаненных
}
echo "Привет, {$user['name']}!<br>";
}
?>
```text
### break и continue с уровнями
```php
<?php
// break из вложенных циклов
for ($i = 1; $i <= 3; $i++) {
for ($j = 1; $j <= 3; $j++) {
if ($i == 2 && $j == 2) {
break 2; // Выход из обоих циклов
}
echo "($i,$j) ";
}
echo "<br>";
}
// continue для внешнего цикла
for ($i = 1; $i <= 3; $i++) {
for ($j = 1; $j <= 3; $j++) {
if ($j == 2) {
continue 2; // Переход к следующей итерации внешнего цикла
}
echo "($i,$j) ";
}
echo "<br>";
}
?>
```text
## Вложенные циклы
Циклы внутри циклов.
```php
<?php
// Таблица умножения
echo "<table border='1'>";
for ($i = 1; $i <= 10; $i++) {
echo "<tr>";
for ($j = 1; $j <= 10; $j++) {
$result = $i * $j;
echo "<td>$result</td>";
}
echo "</tr>";
}
echo "</table>";
// Шахматная доска
for ($row = 1; $row <= 8; $row++) {
for ($col = 1; $col <= 8; $col++) {
$color = ($row + $col) % 2 == 0 ? "white" : "black";
echo "<div class='cell $color'></div>";
}
echo "<br>";
}
// Генерация комбинаций
$colors = ["красный", "синий", "зеленый"];
$sizes = ["S", "M", "L"];
foreach ($colors as $color) {
foreach ($sizes as $size) {
echo "$color - $size<br>";
}
}
?>
```text
## Альтернативный синтаксис (для шаблонов)
Удобен при смешивании PHP и HTML.
```php
<?php $fruits = ["яблоко", "банан", "апельсин"]; ?>
<!-- Обычный синтаксис -->
<ul>
<?php foreach ($fruits as $fruit) { ?>
<li><?php echo $fruit; ?></li>
<?php } ?>
</ul>
<!-- Альтернативный синтаксис (чище) -->
<ul>
<?php foreach ($fruits as $fruit): ?>
<li><?php echo $fruit; ?></li>
<?php endforeach; ?>
</ul>
<!-- Работает для всех циклов -->
<?php for ($i = 1; $i <= 5; $i++): ?>
<p>Параграф <?php echo $i; ?></p>
<?php endfor; ?>
<?php while ($i < 10): ?>
<span><?php echo $i++; ?></span>
<?php endwhile; ?>
```text
## WordPress контекст
Циклы — основа WordPress.
### The Loop (главный цикл WordPress)
```php
<?php
// Стандартный цикл WordPress
if (have_posts()) {
while (have_posts()) {
the_post();
?>
<article>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<div><?php the_excerpt(); ?></div>
</article>
<?php
}
} else {
echo "<p>Посты не найдены</p>";
}
?>
```text
### Кастомный запрос (WP_Query)
```php
<?php
$args = [
'post_type' => 'product',
'posts_per_page' => 10,
'orderby' => 'date',
'order' => 'DESC'
];
$query = new WP_Query($args);
if ($query->have_posts()) {
echo '<div class="products">';
while ($query->have_posts()) {
$query->the_post();
?>
<div class="product">
<?php the_post_thumbnail('medium'); ?>
<h3><?php the_title(); ?></h3>
<p><?php the_excerpt(); ?></p>
<a href="<?php the_permalink(); ?>">Подробнее</a>
</div>
<?php
}
echo '</div>';
wp_reset_postdata(); // Важно!
} else {
echo "Товары не найдены";
}
?>
```text
### Вывод меню
```php
<?php
$menu_items = wp_get_nav_menu_items('main-menu');
if ($menu_items) {
echo '<ul class="menu">';
foreach ($menu_items as $item) {
$active = ($item->object_id == get_the_ID()) ? 'active' : '';
echo '<li class="' . $active . '">';
echo '<a href="' . $item->url . '">' . $item->title . '</a>';
echo '</li>';
}
echo '</ul>';
}
?>
```text
### Вывод категорий
```php
<?php
$categories = get_categories([
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => true
]);
foreach ($categories as $category) {
echo '<div class="category">';
echo '<h3>' . $category->name . '</h3>';
echo '<p>' . $category->description . '</p>';
echo '<span>Постов: ' . $category->count . '</span>';
echo '</div>';
}
?>
```text
### Пагинация постов
```php
<?php
$paged = get_query_var('paged') ?: 1;
$posts_per_page = 5;
$args = [
'post_type' => 'post',
'posts_per_page' => $posts_per_page,
'paged' => $paged
];
$query = new WP_Query($args);
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
// Вывод поста
}
// Пагинация
$total_pages = $query->max_num_pages;
if ($total_pages > 1) {
echo '<div class="pagination">';
for ($i = 1; $i <= $total_pages; $i++) {
$active = ($i == $paged) ? 'active' : '';
$link = get_pagenum_link($i);
echo "<a href='$link' class='$active'>$i</a>";
}
echo '</div>';
}
wp_reset_postdata();
}
?>
```text
## Практика
### Задание 1: Таблица умножения
Создайте HTML-таблицу с таблицей умножения от 1 до 10.
```php
<?php
echo "<table border='1'>";
echo "<tr><th></th>";
for ($i = 1; $i <= 10; $i++) {
echo "<th>$i</th>";
}
echo "</tr>";
for ($i = 1; $i <= 10; $i++) {
echo "<tr><th>$i</th>";
for ($j = 1; $j <= 10; $j++) {
echo "<td>" . ($i * $j) . "</td>";
}
echo "</tr>";
}
echo "</table>";
?>
```text
### Задание 2: Список годов
Создайте выпадающий список с годами от текущего до 1950.
### Задание 3: Четные числа
Выведите только четные числа от 1 до 100.
### Задание 4: Сумма элементов массива
Найдите сумму всех элементов массива с помощью цикла.
```php
<?php
$numbers = [10, 25, 8, 42, 15, 30];
$sum = 0;
foreach ($numbers as $num) {
$sum += $num;
}
echo "Сумма: $sum";
?>
```text
### Задание 5: Поиск максимального
Найдите максимальное значение в массиве без использования max().
## Онлайн-редакторы
Тестируйте примеры:
- **PHPSandbox**: https://phpsandbox.io/
- **3v4l**: https://3v4l.org/
## Итоги
В этом уроке вы изучили:
✅ **while** — цикл с предусловием
✅ **do-while** — цикл с постусловием
✅ **for** — цикл со счетчиком
✅ **foreach** — перебор массивов
✅ **break/continue** — управление циклом
✅ **Вложенные циклы** — циклы в циклах
✅ **WordPress Loop** — главный цикл WP
### Следующий шаг
Теперь изучим функции для организации кода: [Функции](/php/functions/)
### Ключевые моменты
1. **foreach для массивов** — самый удобный способ
2. **Не забывайте изменять условие** — иначе бесконечный цикл
3. **unset() после &$var** — очищайте ссылки
4. **break/continue** — делают код читабельнее
5. **Альтернативный синтаксис** — для чистых шаблонов
**Совет:** Циклы — это автоматизация. Используйте их вместо копипаста!
---
**Готовы двигаться дальше?** Переходите к следующему уроку: [Функции](/php/functions/)