Část III · Sloupce
10. Avatar
addAvatar($alias, $title, $filterOptions = null) – v datech je jen
identifikátor osoby. Jméno, fotku, online stav i odkaz na profil si grid
vyzvedne u UserProvideru, kterého má z DI.
Ukázka
Sloupec Id zákazníka vedle je tatáž hodnota bez presetu – v datech je opravdu jen číslo. Fotku má v demu jen půlka lidí, ostatní mají iniciály.
Zdrojový kód
php
app/Modules/AdminModule/Components/Docs/Columns/ColumnAvatarGridControl/ColumnAvatarGridControl.php
<?php
declare(strict_types=1);
namespace App\Components\Docs\Columns\ColumnAvatarGridControl;
use Xart\Grid\Button\ButtonManager;
use Xart\Grid\Column\ColumnManager;
use Xart\Grid\Control\GridControl;
use Xart\Grid\DataOutput\Row;
use Xart\Grid\DataSource\DataSource;
use Xart\Grid\DataSource\SQL\SQLDataSource;
/**
* Dokumentace, kapitola 10 – Avatar.
*
* V datech je jen id zákazníka; jméno, fotku, online stav i odkaz na profil dodá UserProvider.
* Vedle je totéž id přes add(), aby bylo vidět, s čím sloupec doopravdy pracuje.
*/
class ColumnAvatarGridControl extends GridControl
{
public function createDataSource(): DataSource
{
return new SQLDataSource(__DIR__ . '/ColumnAvatarGridControl.sql');
}
public function columns(ColumnManager $cm): void
{
$cm->add('number', 'Číslo');
// Nabídka filtru [id => jméno]; bez ní by sloupec filtr neměl (textový by hledal v id).
$cm->addAvatar('id_customer', 'Zákazník', $this->customerOptions());
// Tatáž hodnota bez presetu – v buňce zůstane holé id.
$cm->add('id_customer_raw', 'Id zákazníka');
$cm->addNumber('total_price', 'Celkem', 2, 'Kč');
}
/**
* Zákazníci, kteří mají aspoň jednu objednávku – nabízet ve filtru někoho, kdo v gridu není,
* nemá smysl.
*
* @return array<string, string>
*/
private function customerOptions(): array
{
$rows = $this->db->query(
'SELECT c.id, CONCAT(c.first_name, " ", c.last_name) AS name
FROM `customer` c
WHERE EXISTS (SELECT 1 FROM `order` o WHERE o.id_customer = c.id)
ORDER BY c.last_name, c.first_name',
)->fetchAll();
$options = [];
foreach ($rows as $row) {
$options[(string) $row->id] = (string) $row->name;
}
return $options;
}
public function buttons(ButtonManager $bm): void
{
}
public function rows(Row $row): void
{
}
public function render(): void
{
$this->template->render(__DIR__ . '/ColumnAvatarGridControl.latte');
}
}
php
app/Helpers/DemoUserProvider.php
<?php
declare(strict_types=1);
namespace App\Helpers;
use Nette\Application\LinkGenerator;
use Nette\Database\Explorer;
use Xart\Grid\User\UserDTO;
use Xart\Grid\User\UserProvider;
final class DemoUserProvider extends UserProvider
{
public function __construct(
private Explorer $db,
private LinkGenerator $linkGenerator,
) {
}
protected function loadUser(string $id): ?UserDTO
{
$row = $this->db->query('SELECT * FROM customer WHERE id = ?', $id)->fetch();
if ($row === null) {
return null;
}
$numericId = (int) $id;
return new UserDTO(
$id,
(string) $row->first_name,
(string) $row->last_name,
// Demo: fotku má jen půlka lidí, ať je vidět i vykreslení iniciál.
$numericId % 2 === 0 ? 'https://i.pravatar.cc/256?u=' . urlencode($id) : null,
null,
$numericId % 4 === 0 ? $numericId % 3 === 0 : null,
$numericId % 3 === 0 ? $this->linkGenerator->link('Customer:Form', [$id]) : null,
);
}
}
Cesta k avataru
- V buňce je identifikátor (
id_customer). - Grid se na něj zeptá
UserProvideru–loadUser(string $id). Opakované dotazy na tutéž osobu si knihovna pamatuje, takže na stránku plnou objednávek jednoho zákazníka připadá jeden dotaz. - Odpovědí je
UserDTO, nebonull– pak zůstane buňka prázdná. - Z
UserDTOse vykreslí avatar se jménem.
Co UserDTO nese
id, jméno | Povinné. |
imageUrl | Bez ní se vykreslí iniciály na podkladu z náhradní palety – barvu určuje identifikátor, takže je pro touž osobu pokaždé stejná. |
color | Vlastní barva podkladu místo té z palety. |
online | Zelená tečka u avataru. |
profileUrl | Jméno se stane odkazem. |
Filtr
Bez $filterOptions sloupec filtr nedostane – textový by hledal
v syrových identifikátorech, což uživateli nepomůže. S nabídkou [id => jméno]
z něj je vícenásobný výběr; klíče se zachovávají tak, jak přišly z databáze (id bývají čísla).
V ukázce se nabízejí jen zákazníci, kteří aspoň jednu objednávku mají.
Na co si dát pozor
- Řazení běží podle identifikátoru v databázi, ne podle jména – kdo chce řadit podle jména, musí je mít v dotazu (kapitola 3.3).
- Prázdná buňka znamená, že řádek k žádné osobě nepatří; na
UserProviderse grid v takovém případě neptá. UserProviderje povinná služba celé knihovny, i když žádný avatar nemáte – viz kapitola 1.