MAD Lab
/
Tutor > Listagens e tabelas > Pivot table

Pivot table

Listagens e tabelas

mad-pivot-table mad-pivot-field mad-pivot-row mad-pivot-view
mad_validate acusa R045/R031 aqui — falsos positivos (schema desatualizado)
O schema do mad_props pra mad-pivot-table conhece só ~13 props — name, joins, além de label/aggregation/ format/currency em row/col/value/filter e area em mad-pivot-field, existem de verdade (confirmado em packages/mad-framework/src/mad/views/components/pivot-table.blade.php e em MadGridCompiler::buildPivotFieldAttrs) mas disparam R045. O aviso R031 sobre database="business" também é esperado aqui: neste projeto (mad-framework-laravel-teste) "business" é a conexão real configurada — mesmo valor já usado no gabarito (tutor.examples.forms-texto.db-combo). Vale reportar pra quem mantém o schema do MCP.
Básico (mad-pivot-row + mad-pivot-value)

Uma linha (categoria) e um valor agregado (soma). model + :joins resolvem a query sozinhos — zero PHP no controller.

Pedidos por categoria
resources/views/tutor/examples/grids-pivot/basico.blade.php
<mad-pivot-table name="tutor_pivot_basico" model="TutorDemoPedido" database="business"
    :joins="['tutor_categorias' => ['categoria_id', 'tutor_categorias.id']]"
    title="Pedidos por categoria" height="420">

    <mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
    <mad-pivot-value field="valor_total" label="Valor total"
        aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Cross-tab (mad-pivot-row + mad-pivot-col)

Categoria nas linhas, estado do pedido nas colunas — dois joins pra trazer os dois nomes.

Categoria x Estado
resources/views/tutor/examples/grids-pivot/cross-tab.blade.php
<mad-pivot-table name="tutor_pivot_cross_tab" model="TutorDemoPedido" database="business"
    :joins="[
        'tutor_categorias'     => ['categoria_id', 'tutor_categorias.id'],
        'tutor_estados_pedido' => ['estado_id', 'tutor_estados_pedido.id'],
    ]"
    title="Categoria x Estado" height="450">

    <mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
    <mad-pivot-col field="tutor_estados_pedido.nome" label="Estado" />
    <mad-pivot-value field="valor_total" label="Valor"
        aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Multi-nível com subtotais + mad-pivot-filter

Dois níveis de linha (estado > categoria) com subtotals, mais um filtro interativo por mês (SQL raw com alias).

Estado > Categoria (com subtotais e filtro por mês)
resources/views/tutor/examples/grids-pivot/subtotais.blade.php
<mad-pivot-table name="tutor_pivot_subtotais" model="TutorDemoPedido" database="business"
    :joins="[
        'tutor_categorias'     => ['categoria_id', 'tutor_categorias.id'],
        'tutor_estados_pedido' => ['estado_id', 'tutor_estados_pedido.id'],
    ]"
    title="Estado > Categoria (com subtotais e filtro por mês)" height="500" subtotals>

    <mad-pivot-row field="tutor_estados_pedido.nome" label="Estado" />
    <mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
    <mad-pivot-value field="valor_total" label="Valor"
        aggregation="sum" format="currency" currency="BRL" />
    <mad-pivot-filter field="SUBSTR(dt_pedido,1,7) as mes" label="Mês (AAAA-MM)" />
</mad-pivot-table>
Múltiplas agregações do mesmo campo

valor_total três vezes: soma, média (ticket médio) e contagem de pedidos.

Categoria — múltiplas agregações
resources/views/tutor/examples/grids-pivot/multi-agregacao.blade.php
<mad-pivot-table name="tutor_pivot_multi_agregacao" model="TutorDemoPedido" database="business"
    :joins="['tutor_categorias' => ['categoria_id', 'tutor_categorias.id']]"
    title="Categoria — múltiplas agregações" height="420">

    <mad-pivot-row field="tutor_categorias.nome" label="Categoria" />
    <mad-pivot-value field="valor_total" label="Total vendido"
        aggregation="sum" format="currency" currency="BRL" />
    <mad-pivot-value field="valor_total" label="Ticket médio"
        aggregation="avg" format="currency" currency="BRL" />
    <mad-pivot-value field="id" label="Qtd. pedidos"
        aggregation="count" format="number" />
</mad-pivot-table>
Catálogo de campos + views salvas (mad-pivot-field + mad-pivot-view)

Campos declarados uma vez em mad-pivot-field; duas mad-pivot-view viram presets que o usuário troca no seletor da UI.

Pedidos — catálogo de campos + views
resources/views/tutor/examples/grids-pivot/campos-views.blade.php
<mad-pivot-table name="tutor_pivot_campos_views" model="TutorDemoPedido" database="business"
    :joins="[
        'tutor_categorias'     => ['categoria_id', 'tutor_categorias.id'],
        'tutor_estados_pedido' => ['estado_id', 'tutor_estados_pedido.id'],
    ]"
    title="Pedidos — catálogo de campos + views" height="500" field-list>

    <mad-pivot-field field="tutor_categorias.nome" label="Categoria" area="rows" />
    <mad-pivot-field field="tutor_estados_pedido.nome" label="Estado" area="columns" />
    <mad-pivot-field field="valor_total" label="Valor" area="values"
        aggregation="sum" format="currency-BRL" />

    <mad-pivot-view name="Por categoria" default>
        <mad-pivot-row field="tutor_categorias.nome" />
        <mad-pivot-value field="valor_total" />
    </mad-pivot-view>

    <mad-pivot-view name="Categoria x Estado">
        <mad-pivot-row field="tutor_categorias.nome" />
        <mad-pivot-col field="tutor_estados_pedido.nome" />
        <mad-pivot-value field="valor_total" />
    </mad-pivot-view>
</mad-pivot-table>
Código-fonte completo da página
app/control/Tutor/TutorGridsPivot.php
<?php

namespace App\Control\Tutor;

use App\Support\Tutor\TutorDemoSeed;
use App\Support\Tutor\TutorPage;

/**
 * TutorGridsPivot — catálogo grids_pivot.
 *
 * <mad-pivot-table> é 100% declarativo: `model=` + `database=` + `:joins`
 * resolvem a query sozinhos (packages/mad-framework/src/mad/views/
 * components/pivot-table.blade.php monta o SELECT via Query Builder e
 * renderiza um iframe React em manager.madbuilder.com.br/mad-table — "Zero
 * codigo PHP no controller" é literal, comentário no próprio arquivo). A doc
 * do componente (components-admin/pivot-table.md) proíbe explicitamente
 * "query manual + array_reduce no controller para depois passar pro Blade".
 * Por isso esta página NÃO tem nenhum método de query: os 5 exemplos usam
 * só model="TutorDemoPedido" + :joins pra alcançar tutor_categorias/
 * tutor_estados_pedido (FK id → nome) direto no Blade.
 */
class TutorGridsPivot extends TutorPage
{
    protected string $catalogKey = 'grids_pivot';

    public function mount(array $params = []): void
    {
        TutorDemoSeed::ensure();
    }
}
resources/views/tutor/grids/pivot.blade.php
<x-tutor-page page="grids_pivot">
    <mad-callout type="warning" title="mad_validate acusa R045/R031 aqui — falsos positivos (schema desatualizado)" icon="alert-triangle">
        O schema do <code>mad_props</code> pra <code>mad-pivot-table</code> conhece só ~13 props —
        <code>name</code>, <code>joins</code>, além de <code>label</code>/<code>aggregation</code>/
        <code>format</code>/<code>currency</code> em row/col/value/filter e <code>area</code> em
        <code>mad-pivot-field</code>, existem de verdade (confirmado em
        <code>packages/mad-framework/src/mad/views/components/pivot-table.blade.php</code> e em
        <code>MadGridCompiler::buildPivotFieldAttrs</code>) mas disparam R045. O aviso R031 sobre
        <code>database="business"</code> também é esperado aqui: neste projeto (mad-framework-laravel-teste)
        "business" é a conexão real configurada — mesmo valor já usado no gabarito
        (tutor.examples.forms-texto.db-combo). Vale reportar pra quem mantém o schema do MCP.
    </mad-callout>

    <x-tutor-demo demo="tutor.examples.grids-pivot.basico"
        title="Básico (mad-pivot-row + mad-pivot-value)"
        desc="Uma linha (categoria) e um valor agregado (soma). model + :joins resolvem a query sozinhos — zero PHP no controller." />

    <x-tutor-demo demo="tutor.examples.grids-pivot.cross-tab"
        title="Cross-tab (mad-pivot-row + mad-pivot-col)"
        desc="Categoria nas linhas, estado do pedido nas colunas — dois joins pra trazer os dois nomes." />

    <x-tutor-demo demo="tutor.examples.grids-pivot.subtotais"
        title="Multi-nível com subtotais + mad-pivot-filter"
        desc="Dois níveis de linha (estado > categoria) com subtotals, mais um filtro interativo por mês (SQL raw com alias)." />

    <x-tutor-demo demo="tutor.examples.grids-pivot.multi-agregacao"
        title="Múltiplas agregações do mesmo campo"
        desc="valor_total três vezes: soma, média (ticket médio) e contagem de pedidos." />

    <x-tutor-demo demo="tutor.examples.grids-pivot.campos-views"
        title="Catálogo de campos + views salvas (mad-pivot-field + mad-pivot-view)"
        desc="Campos declarados uma vez em mad-pivot-field; duas mad-pivot-view viram presets que o usuário troca no seletor da UI." />
</x-tutor-page>