W Symfony 6 tworzenie tablic i wyświetlanie ich w widoku jest stosunkowo proste i intuicyjne. Najczęściej tworzymy tablice w kontrolerze, gdzie mogą zawierać różne rodzaje danych, na przykład rekordy z bazy danych lub formularze. Po stworzeniu tablicy przekazujemy ją do widoku, który zajmuje się jej wyświetleniem.
W widoku możemy wykorzystać różne mechanizmy do wyświetlania tablic, np. pętlę for
lub foreach
, która pozwala na iterację po elementach tablicy i wyświetlanie ich w sposób dynamiczny. Dodatkowo możemy wykorzystać mechanizmy sortowania, filtrowania i paginacji, które pozwolą na bardziej zaawansowane operacje na danych.
Widoki w Symfony 6 korzystają z szablonów Twig, który pozwala na łatwe generowanie HTML i wykorzystanie różnych funkcji pomocniczych, np. do formatowania tekstu czy tworzenia linków. W ten sposób możemy w łatwy sposób wyświetlać dane w formie tabel, list czy nawet formularzy.
Stwórzmy kontroler ArrayController:
php bin/console make:controller Array
Następnie w pliku kontrolera dodajmy następujący kod:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ArrayController extends AbstractController
{
#[Route('/array', name: 'app_array')]
public function array(): Response
{
$data = array(
array('name' => 'Adam', 'surname' => 'Smith', 'age' => 35, 'email' => 'adam.smith@example.com'),
array('name' => 'Emily', 'surname' => 'Jones', 'age' => 27, 'email' => 'emily.jones@example.com'),
array('name' => 'Michael', 'surname' => 'Brown', 'age' => 42, 'email' => 'michael.brown@example.com'),
array('name' => 'Samantha', 'surname' => 'Lee', 'age' => 23, 'email' => 'samantha.lee@example.com'),
array('name' => 'William', 'surname' => 'Davis', 'age' => 31, 'email' => 'william.davis@example.com'),
array('name' => 'Olivia', 'surname' => 'Miller', 'age' => 29, 'email' => 'olivia.miller@example.com'),
array('name' => 'Benjamin', 'surname' => 'Wilson', 'age' => 38, 'email' => 'benjamin.wilson@example.com'),
array('name' => 'Isabella', 'surname' => 'Taylor', 'age' => 26, 'email' => 'isabella.taylor@example.com'),
);
return $this->render('array/index.html.twig', [
'data' => $data,
]);
}
}
Jak widać stworzona została tablica dwuwymiarowa, gdzie każdy rekord podstawowej tablicy jest kolejną tablicą asocjacyjną z kluczami i przyporządkowanymi do nich wartościami. Po stworzeniu tablicy przekazywana ona jest do widoku.
W widoku stwórzmy następujący kod:
{% extends 'base.html.twig' %}
{% block title %}ArrayView{% endblock %}
{% block body %}
<table>
<thead>
<tr>
<th>Name
<th>Surname
<th>Age
<th>Email
</thead>
<tbody>
{% for record in data %}
<tr>
<td>{{ record.name }}
<td>{{ record.surname }}
<td>{{ record.age }}
<td>{{ record.email }}
{% endfor %}
</tbody>
</table>
{% endblock %}
W widoku jak widać można wyświetlić dane z tablicy przekazanej z kontrolera w tabeli HTML za pomocą pętli „for” lub „foreach”.
Dodajmy sortowanie tabeli po danych kolumnach. Wykonamy to za pomocą przekazania w URL odpowiednich parametrów.
Najpierw dodajmy w widoku linki służące do sortowania tabeli:
{% extends 'base.html.twig' %}
{% block title %}ArrayView{% endblock %}
{% block body %}
<table>
<thead>
<tr>
<th><a href="{{ path('app_array', {'sortBy': 'name'}) }}">Name</a>
<th><a href="{{ path('app_array', {'sortBy': 'surname'}) }}">Surname</a>
<th><a href="{{ path('app_array', {'sortBy': 'age'}) }}">Age</a>
<th><a href="{{ path('app_array', {'sortBy': 'email'}) }}">Email</a>
</thead>
<tbody>
{% for record in data %}
<tr>
<td>{{ record.name }}
<td>{{ record.surname }}
<td>{{ record.age }}
<td>{{ record.email }}
{% endfor %}
</tbody>
</table>
{% endblock %}
Następnie w kontrolerze dodajemy kod odpowiedzialny za sortowanie:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ArrayController extends AbstractController
{
#[Route('/array', name: 'app_array')]
public function array(Request $request): Response
{
$data = array(
array('name' => 'Adam', 'surname' => 'Smith', 'age' => 35, 'email' => 'adam.smith@example.com'),
array('name' => 'Emily', 'surname' => 'Jones', 'age' => 27, 'email' => 'emily.jones@example.com'),
array('name' => 'Michael', 'surname' => 'Brown', 'age' => 42, 'email' => 'michael.brown@example.com'),
array('name' => 'Samantha', 'surname' => 'Lee', 'age' => 23, 'email' => 'samantha.lee@example.com'),
array('name' => 'William', 'surname' => 'Davis', 'age' => 31, 'email' => 'william.davis@example.com'),
array('name' => 'Olivia', 'surname' => 'Miller', 'age' => 29, 'email' => 'olivia.miller@example.com'),
array('name' => 'Benjamin', 'surname' => 'Wilson', 'age' => 38, 'email' => 'benjamin.wilson@example.com'),
array('name' => 'Isabella', 'surname' => 'Taylor', 'age' => 26, 'email' => 'isabella.taylor@example.com'),
);
$sortBy = $request->query->get('sortBy', 'default');
if ($sortBy == 'name') {
usort($data, function($a, $b) {
return strcmp($a['name'], $b['name']);
});
} elseif ($sortBy == 'surname') {
usort($data, function($a, $b) {
return strcmp($a['surname'], $b['surname']);
});
} elseif ($sortBy == 'age') {
usort($data, function($a, $b) {
return $a['age'] - $b['age'];
});
} elseif ($sortBy == 'email') {
usort($data, function($a, $b) {
return strcmp($a['email'], $b['email']);
});
}
return $this->render('array/index.html.twig', [
'data' => $data,
]);
}
}
Jak widać możemy sortować daną kolumnę, jednak tylko w jedną stronę. Dodajmy możliwość sortowania w górę i w dół danej kolumny – po drugim kliknięciu w link kolumna posortuje się odwrotnie. Aby to wykonać musimy przekazać w URL kolejny parametr określający kierunek sortowania, tworzymy odpowiednie linki w widoku:
{% extends 'base.html.twig' %}
{% block title %}ArrayView{% endblock %}
{% block body %}
<table>
<thead>
<tr>
<th><a href="{{ path('app_array', {'sortBy': 'name', 'sortOrder': (sortBy == 'name' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Name</a>
<th><a href="{{ path('app_array', {'sortBy': 'surname', 'sortOrder': (sortBy == 'surname' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Surname</a>
<th><a href="{{ path('app_array', {'sortBy': 'age', 'sortOrder': (sortBy == 'age' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Age</a>
<th><a href="{{ path('app_array', {'sortBy': 'email', 'sortOrder': (sortBy == 'email' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Email</a>
</thead>
<tbody>
{% for record in data %}
<tr>
<td>{{ record.name }}
<td>{{ record.surname }}
<td>{{ record.age }}
<td>{{ record.email }}
{% endfor %}
</tbody>
</table>
{% endblock %}
Zwróć uwagę, że w tagu a href
używany jest helper path
, który generuje URL na podstawie nazwy routingu oraz przekazanych parametrów. W tym przypadku, generowany jest URL dla nazwy routingu „app_array”, czyli dla metody array
w kontrolerze ArrayController
. Następnie, w przekazanych parametrach podajemy sortBy
z wartością np. „name”, co oznacza, że chcemy posortować po kolumnie „name”. Dodatkowo, używany jest parametr sortOrder
, który odpowiada za kierunek sortowania – „asc” (rosnąco) lub „desc” (malejąco). Ten parametr jest obliczany w locie w oparciu o aktualny stan sortowania. Jeśli sortBy
jest równy „name” i sortOrder
jest równy „asc”, to ustawiamy sortOrder
na „desc”, aby umożliwić sortowanie malejąco po kolumnie „name”. W przeciwnym razie, ustawiamy sortOrder
na „asc”, aby umożliwić sortowanie rosnąco po kolumnie „name”.
W kontrolerze dodajemy obsługę sortowania w górę i w dół:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ArrayController extends AbstractController
{
#[Route('/array', name: 'app_array')]
public function array(Request $request): Response
{
$data = array(
array('name' => 'Adam', 'surname' => 'Smith', 'age' => 35, 'email' => 'adam.smith@example.com'),
array('name' => 'Emily', 'surname' => 'Jones', 'age' => 27, 'email' => 'emily.jones@example.com'),
array('name' => 'Michael', 'surname' => 'Brown', 'age' => 42, 'email' => 'michael.brown@example.com'),
array('name' => 'Samantha', 'surname' => 'Lee', 'age' => 23, 'email' => 'samantha.lee@example.com'),
array('name' => 'William', 'surname' => 'Davis', 'age' => 31, 'email' => 'william.davis@example.com'),
array('name' => 'Olivia', 'surname' => 'Miller', 'age' => 29, 'email' => 'olivia.miller@example.com'),
array('name' => 'Benjamin', 'surname' => 'Wilson', 'age' => 38, 'email' => 'benjamin.wilson@example.com'),
array('name' => 'Isabella', 'surname' => 'Taylor', 'age' => 26, 'email' => 'isabella.taylor@example.com'),
);
$sortBy = $request->query->get('sortBy', 'default');
$sortOrder = $request->query->get('sortOrder', 'asc');
if ($sortBy == 'name') {
usort($data, function($a, $b) use ($sortOrder) {
$result = strcmp($a['name'], $b['name']);
return $sortOrder === 'asc' ? $result : -$result;
});
} elseif ($sortBy == 'surname') {
usort($data, function($a, $b) use ($sortOrder) {
$result = strcmp($a['surname'], $b['surname']);
return $sortOrder === 'asc' ? $result : -$result;
});
} elseif ($sortBy == 'age') {
usort($data, function($a, $b) use ($sortOrder) {
$result = $a['age'] - $b['age'];
return $sortOrder === 'asc' ? $result : -$result;
});
} elseif ($sortBy == 'email') {
usort($data, function($a, $b) use ($sortOrder) {
$result = strcmp($a['email'], $b['email']);
return $sortOrder === 'asc' ? $result : -$result;
});
}
return $this->render('array/index.html.twig', [
'data' => $data,
'sortOrder' => $sortOrder,
'sortBy' => $sortBy
]);
}
}
Na sam koniec dodajmy jeszcze znacznik sortowania, tak aby po kliknięciu w dany link było wiadomo, względem której kolumny mamy posortowaną tabelę. Dodajemy warunki do widoku:
{% extends 'base.html.twig' %}
{% block title %}ArrayView{% endblock %}
{% block body %}
<table>
<thead>
<tr>
<th><a href="{{ path('app_array', {'sortBy': 'name', 'sortOrder': (sortBy == 'name' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Name</a>
{% if sortBy == 'name' %}
{% if sortOrder == 'asc' %}
<span>↑</span>
{% else %}
<span>↓</span>
{% endif %}
{% endif %}
<th><a href="{{ path('app_array', {'sortBy': 'surname', 'sortOrder': (sortBy == 'surname' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Surname</a>
{% if sortBy == 'surname' %}
{% if sortOrder == 'asc' %}
<span>↑</span>
{% else %}
<span>↓</span>
{% endif %}
{% endif %}
<th><a href="{{ path('app_array', {'sortBy': 'age', 'sortOrder': (sortBy == 'age' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Age</a>
{% if sortBy == 'age' %}
{% if sortOrder == 'asc' %}
<span>↑</span>
{% else %}
<span>↓</span>
{% endif %}
{% endif %}
<th><a href="{{ path('app_array', {'sortBy': 'email', 'sortOrder': (sortBy == 'email' and sortOrder == 'asc') ? 'desc' : 'asc'}) }}">Email</a>
{% if sortBy == 'email' %}
{% if sortOrder == 'asc' %}
<span>↑</span>
{% else %}
<span>↓</span>
{% endif %}
{% endif %}
</thead>
<tbody>
{% for record in data %}
<tr>
<td>{{ record.name }}
<td>{{ record.surname }}
<td>{{ record.age }}
<td>{{ record.email }}
{% endfor %}
</tbody>
</table>
{% endblock %}
W kodzie powyżej zostały dodane kolejne bloki warunkowe, które sprawdzają, czy dana kolumna jest aktualnie sortowana, i w zależności od tego, czy sortowanie jest w kolejności rosnącej czy malejącej, wyświetlają odpowiedni znak sortowania (↑ dla rosnącej, ↓ dla malejącej).
Udało Ci się stworzyć prosty kontroler oraz widok, w którym mogliśmy wyświetlać przykładowe dane w tabeli. Następnie zaktualizowaliśmy kontroler i widok, tak aby umożliwić sortowanie w górę i w dół po kliknięciu na nagłówki tabeli. Teraz użytkownicy Twojej aplikacji będą mieli większą kontrolę nad sposobem sortowania danych, co z pewnością poprawi ich wrażenia z korzystania z Twojej aplikacji. Pamiętaj, że w trakcie pisania kodu ważne jest dbanie o czystość i czytelność kodu, dzięki czemu będzie on łatwiejszy do zrozumienia i utrzymania w przyszłości.