Как организован вывод списка в PHP-шаблонах
Основные методы отображения списков
Какое решение считается наиболее эффективным для вывода списка в современных проектах?
Наиболее эффективным считается использование шаблонизатора Twig с циклом for. Он обеспечивает четкое разделение логики и представления, автоматическое экранирование и гибкие фильтры. Рассмотрим пример вывода списка пользователей.
Код контроллера (PHP):
// index.php
require_once 'vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('templates');
$twig = new \Twig\Environment($loader);
$users = [
['id' => 1, 'name' => 'Анна', 'email' => 'anna@example.com'],
['id' => 2, 'name' => 'Иван', 'email' => 'ivan@example.com'],
['id' => 3, 'name' => 'Мария', 'email' => 'maria@example.com']
];
echo $twig->render('users.html.twig', ['users' => $users]);
View php list (просмотр списка php)
Шаблон users.html.twig:
<table border="1">
<tr><th>ID</th><th>Имя</th><th>Email</th></tr>
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
</tr>
{% else %}
<tr><td colspan="3">Пользователи не найдены</td></tr>
{% endfor %}
</table>
Результат:
<table border="1">
<tr><th>ID</th><th>Имя</th><th>Email</th></tr>
<tr><td>1</td><td>Анна</td><td>anna@example.com</td></tr>
<tr><td>2</td><td>Иван</td><td>ivan@example.com</td></tr>
<tr><td>3</td><td>Мария</td><td>maria@example.com</td></tr>
</table>
Типичная ошибка: переменная users не передана в шаблон. Вместо списка выводится пустая строка или ошибка Undefined variable. Решение: проверить наличие переменной через {% if users is defined %} или использовать фильтр default: {% for user in users|default([]) %}.
Цели использования: Twig идеален для сложных проектов с множеством представлений, где важна безопасность и поддержка.
Как отобразить список без использования стороннего шаблонизатора?
Использование чистого PHP с включением файлов (include) и циклом foreach.
<?php
// index.php
$users = [
['id' => 1, 'name' => 'Анна', 'email' => 'anna@example.com'],
['id' => 2, 'name' => 'Иван', 'email' => 'ivan@example.com']
];
include 'list.phtml';
?>
<!-- list.phtml -->
<ul>
<?php foreach ($users as $user): ?>
<li><?= htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8') ?></li>
<?php endforeach; ?>
</ul>
Проблема: легко забыть экранирование, что приводит к XSS-уязвимостям. Решение: всегда использовать htmlspecialchars или strip_tags для вывода данных.
Когда применять: для простых скриптов без сложной логики шаблонов.
Как использовать Smarty для перебора массива?
Smarty предлагает тег {foreach}.
// index.php
$smarty = new Smarty();
$smarty->assign('users', [
['id' => 1, 'name' => 'Анна'],
['id' => 2, 'name' => 'Иван']
]);
$smarty->display('list.tpl');
<ul>
{foreach from=$users item=user}
<li>{$user.name}</li>
{foreachelse}
<li>Список пуст</li>
{/foreach}
</ul>
Ошибка: если переменная $users не назначена, Smarty выведет предупреждение. Решение: проверить через {if isset($users)}...{/if}.
Цель: Smarty подходит для старых проектов или когда требуется строгий синтаксис.
Как в Blade (Laravel) отобразить коллекцию элементов?
Blade использует директиву @foreach и встроенную поддержку @forelse для пустых коллекций.
// Контроллер Laravel
$users = User::all();
return view('users.index', compact('users'));
<!-- resources/views/users/index.blade.php -->
@forelse ($users as $user)
<p>{{ $user->name }} ({{ $user->email }})</p>
@empty
<p>Нет пользователей.</p>
@endforelse
Проблема: отсутствие данных из-за неправильной передачи переменной. Решение: использовать @isset или проверять $users->count().
Применение: Blade рекомендуется в экосистеме Laravel для всех шаблонов.
Как создать универсальную функцию для рендеринга списка в чистом PHP?
Можно написать функцию, принимающую массив и замыкание для форматирования каждой строки.
function renderList(array $items, callable $formatItem): string {
if (empty($items)) {
return '<p>Список пуст.</p>';
}
$html = '<ul>';
foreach ($items as $item) {
$html .= '<li>' . $formatItem($item) . '</li>';
}
$html .= '</ul>';
return $html;
}
$users = [['name' => 'Анна'], ['name' => 'Иван']];
echo renderList($users, function($user) {
return htmlspecialchars($user['name']);
});
Ошибка: забыли экранировать вывод внутри замыкания. Решение: обязательное экранирование внутри callback.
Когда использовать: для мелких проектов без зависимостей, где нужна простая утилита.
Расширенные примеры работы со списками
Вложенные списки в Twig
Отображение категорий с подкатегориями.
// PHP
$categories = [
[
'name' => 'Электроника',
'children' => [
['name' => 'Телефоны'],
['name' => 'Ноутбуки']
]
],
[
'name' => 'Одежда',
'children' => []
]
];
echo $twig->render('categories.html.twig', ['categories' => $categories]);
<!-- categories.html.twig -->
<ul>
{% for category in categories %}
<li>
{{ category.name }}
{% if category.children is not empty %}
<ul>
{% for child in category.children %}
<li>{{ child.name }}</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
<ul>
<li>Электроника
<ul>
<li>Телефоны</li>
<li>Ноутбуки</li>
</ul>
</li>
<li>Одежда</li>
</ul>
Постраничная навигация (пагинация) с Blade
Передача объекта LengthAwarePaginator из Laravel в шаблон.
// Контроллер
$users = User::paginate(10);
return view('users.index', compact('users'));
<!-- users/index.blade.php -->
<table>
@foreach ($users as $user)
<tr><td>{{ $user->name }}</td></tr>
@endforeach
</table>
{{ $users->links() }}
Результат: Bootstrap-стилизованные ссылки на страницы.
Фильтрация и сортировка в Smarty
Использование модификаторов для изменения порядка вывода.
// PHP
$items = [3, 1, 2];
$smarty->assign('items', $items);
<ol>
{foreach from=$items|@sort item=val}
<li>{$val}</li>
{/foreach}
</ol>
<ol>
<li>1</li>
<li>2</li>
<li>3</li>
</ol>
Группировка элементов по ключу в чистом PHP
Вывод списка, сгруппированного по первой букве имени.
$users = ['Анна', 'Алексей', 'Борис', 'Валентина'];
$grouped = [];
foreach ($users as $name) {
$firstLetter = mb_strtoupper(mb_substr($name, 0, 1));
$grouped[$firstLetter][] = $name;
}
ksort($grouped);
echo '<dl>';
foreach ($grouped as $letter => $names) {
echo '<dt>' . htmlspecialchars($letter) . '</dt>';
echo '<dd><ul>';
foreach ($names as $name) {
echo '<li>' . htmlspecialchars($name) . '</li>';
}
echo '</ul></dd>';
}
echo '</dl>';
<dl>
<dt>А</dt>
<dd><ul>
<li>Анна</li>
<li>Алексей</li>
</ul></dd>
<dt>Б</dt>
<dd><ul>
<li>Борис</li>
</ul></dd>
<dt>В</dt>
<dd><ul>
<li>Валентина</li>
</ul></dd>
</dl>