Produkty Objednávky Zákazníci Dokumentace
Nepřihlášen Uživatel 1 Uživatel 2 Uživatel 3
Část III · Sloupce

7. Nabídka hodnot – addSelect

addSelect($alias, $title, $options, $multi = true, $custom = false, $preserveKeys = false) – pevná nabídka hodnot. Táž nabídka slouží jako filtr i jako překlad hodnoty z databáze na popisek v buňce.

Ukázka

Platba má nabídku zapsanou v kódu, Stav složenou z databáze i s počty a Doprava je seznam bez popisků, do kterého smí uživatel dopsat vlastní hodnotu.

Zdrojový kód

php app/Modules/AdminModule/Components/Docs/Columns/ColumnSelectGridControl/ColumnSelectGridControl.php
<?php

declare(strict_types=1);

namespace App\Components\Docs\Columns\ColumnSelectGridControl;

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 7 – Nabídka hodnot (addSelect).
 *
 * Tytéž sloupce objednávky, jaké jinde v dokumentaci obsluhuje addEnum() – tady ale bez enumu,
 * s nabídkou zapsanou polem a s nabídkou složenou z databáze.
 */
class ColumnSelectGridControl extends GridControl
{
    public function createDataSource(): DataSource
    {
        return new SQLDataSource(__DIR__ . '/ColumnSelectGridControl.sql');
    }


    public function columns(ColumnManager $cm): void
    {
        $cm->add('number', 'Číslo');

        // Asociativní pole: klíč je hodnota v databázi, hodnota popisek v buňce i v nabídce filtru.
        $cm->addSelect('payment', 'Platba', [
            'card' => 'Kartou online',
            'transfer' => 'Bankovní převod',
            'paypal' => 'PayPal',
            'cash' => 'Hotově / Dobírka',
        ], multi: false);

        // Nabídka složená z databáze – hodí se tam, kde číselník žije v tabulce, ne v kódu.
        $cm->addSelect('status', 'Stav', $this->statusOptions());

        // Seznam (ne asociativní pole) se převede na [hodnota => hodnota]; popisek je pak sama
        // hodnota, takže se v buňce vypíše to, co je v databázi.
        $cm->addSelect('shipping', 'Doprava', ['ppl', 'dpd', 'zasilkovna', 'post', 'pickup'], custom: true);

        $cm->addNumber('total_price', 'Celkem', 2, 'Kč');
    }


    /**
     * Nabídka pro sloupec „Stav“ – hodnoty, které v datech opravdu jsou, i s počtem objednávek.
     * Čte se přes query() (v databázi sandboxu jsou rozbité pohledy, kvůli kterým padá table()).
     *
     * @return array<string, string>
     */
    private function statusOptions(): array
    {
        $rows = $this->db->query(
            'SELECT status, COUNT(*) AS count FROM `order` GROUP BY status ORDER BY status',
        )->fetchAll();

        $options = [];
        foreach ($rows as $row) {
            $options[(string) $row->status] = sprintf('%s (%d)', $row->status, $row->count);
        }

        return $options;
    }


    public function buttons(ButtonManager $bm): void
    {
    }


    public function rows(Row $row): void
    {
    }


    public function render(): void
    {
        $this->template->render(__DIR__ . '/ColumnSelectGridControl.latte');
    }
}
sql app/Modules/AdminModule/Components/Docs/Columns/ColumnSelectGridControl/ColumnSelectGridControl.sql
SELECT
    o.id,
    o.number,
    o.payment,
    o.shipping,
    o.status,
    o.total_price / 100 AS total_price
FROM `order` o

Tvar nabídky

Asociativní pole [hodnota => popisek] je obvyklý zápis: klíč musí sedět na to, co je v databázi, hodnota je to, co uvidí uživatel. Filtr pak posílá klíč, buňka vypisuje popisek.

Seznam (['ppl', 'dpd', …]) se pro pohodlí převede na [hodnota => hodnota] – popisek je tedy sama hodnota. Výjimka jsou číselné klíče 0 a 1: ty jsou v PHP k nerozeznání od seznamu, takže se pole převede taky. Když je chcete zachovat, předejte $preserveKeys = true. Právě to dělá addBoolean(), který je jinak celý jen addSelect() s nabídkou ['1' => 'Ano', '0' => 'Ne'].

Nabídka z databáze

Nabídka je obyčejné PHP pole, takže si ji stejně dobře načtete z tabulky – grid má z DI po ruce $this->db:

$rows = $this->db->query('SELECT status, COUNT(*) AS count FROM `order` GROUP BY status')->fetchAll();

columns() se volá při každém požadavku na data, takže dotaz běží často – u velkého číselníku se vyplatí výsledek cachovat. A pozor na hodnoty, které v datech nejsou: co v nabídce chybí, to uživatel nevyfiltruje a v buňce zůstane syrová hodnota.

Parametry nabídky

$multi Zatrhnout jde víc hodnot naráz, podmínky se spojí přes OR. Výchozí je zapnuto; false udělá z nabídky přepínač.
$custom Uživatel smí do filtru dopsat hodnotu, která v nabídce není – k něčemu je to jen tam, kde data obsahují i něco mimo číselník.
$preserveKeys Vypne převod seznamu na [hodnota => hodnota] a klíče nechá být.

Když nabídka žije v PHP enumu, je na to addEnum() – kapitola 8. Filtr je v obou případech tentýž AbstractSelectFilter, liší se jen tím, odkud se nabídka bere.