Docs›Arquitetura›Tipos de Response
Arquitetura

Tipos de Response

MadResponse, ViewResponse, JSONResponse, RedirectResponse.

"Response" significa coisas diferentes dependendo de qual pipeline está respondendo. Esta página mapeia os tipos que você realmente vai encontrar neste codebase — e por que um deles (Mad\Web\ViewResponse/RedirectResponse) existe no pacote do framework mas não é o caminho ativo dentro deste app Laravel.

MadResponse — o builder do MadWire

Mad\Http\MadResponse não é uma resposta HTTP — é um builder de ops que uma action de MadComponent retorna. O MadComponentHandler extrai ->getOps() e empacota dentro do JSON que de fato volta para o browser. É o tipo de retorno mais comum em código MAD.

// Dentro de uma action de MadComponent
public function onSave(): MadResponse
{
    $produto = Produto::create($this->form->fields);

    return (new MadResponse())
        ->toast('Produto criado!', 'success')
        ->closeDrawer()
        ->html('#produtos-count', (string) Produto::count());
}

Catálogo completo de ops (toast, html, val, redirect, openModal, manageRow...) em MadResponse — todas as ops.

Respostas nativas Illuminate

Fora do ciclo MadWire — controllers de rota normal, REST, links públicos do GED — este app usa as classes nativas do Laravel diretamente: Illuminate\Http\Response, JsonResponse, RedirectResponse, e a fachada view() do próprio framework. É o que MadAppController, MadSiteWireController e Mad\Rest\ApiResourceController retornam.

// Mad\Http\Controllers\MadAppController::wire() — devolve JsonResponse nativo
return new JsonResponse(
    $result,
    isset($result['error']) ? 422 : 200,
    ['X-Mad-App-Wire' => '1', 'Cache-Control' => 'no-store, private']
);

// Mad\Rest\ApiResourceController::show() — idem, JsonResponse nativo
return response()->json($this->serializeItem($object, $this->showFields));

// App\Http\Controllers\GedPublicLinkController — Response/RedirectResponse nativos
return redirect()->route('ged.public', $token)->with('error', 'Senha incorreta.');

Mad\Web\ViewResponse / RedirectResponse

O pacote do framework também traz uma camada própria de response — Mad\Web\ViewResponse (renderiza Blade, injeta $errors/ $flash, chainable via ->with()) e Mad\Web\RedirectResponse (->with(), ->withInput(), ->withErrors()) — acessíveis pelos helpers globais view()/redirect()/back() de Mad\Web\helpers.php. Elas implementam um contrato de resposta do próprio pacote (parse()/getStatusCode()), pensado para o pipeline mais leve do framework (Mad\Rest\Router / entry points que não usam o Laravel Foundation completo).

namespace Mad\Web;

// view() (Mad\Web\helpers.php) -> ViewResponse chainable
function view(string $template, array $data = [], int $code = 200): ViewResponse
{
    return (new ViewResponse($template, $code))->with($data);
}

class ViewResponse implements ResponseInterface
{
    public function with(array $data): self { /* acumula dados extras */ }

    public function parse()
    {
        // injeta $errors (ErrorBag) e $flash automaticamente
        return MadBlade::render($this->template, array_merge($extra, $this->data));
    }
}
Neste app, view()/redirect() já são do Laravel

Mad\Web\helpers.php declara view(), redirect() e back() dentro de um if (!function_exists(...)) — uma guarda pensada para não colidir quando o app já carrega outro provedor dessas funções. Como este projeto é um app Laravel completo, o autoloader carrega vendor/laravel/framework antes de mad/framework, e o Laravel já declara view()/redirect()/back() globalmente — então a guarda nunca chega a definir as versões do Mad\Web. Na prática, chamar view() ou redirect() em qualquer controller deste app já é 100% Laravel nativo, não Mad\Web\ViewResponse.

Método estático (?static=1) — send()

Existe um terceiro caminho, fora do ciclo de vida do MadComponent: um método PHP-estático chamado por /app/Classe/metodo?static=1 (é o que Mad.exec, os botões/combos do notchbar e widgets JS como o feed do FullCalendar usam). MadAppController::run() detecta o método estático, o invoca dentro de um ob_start() e devolve o output bufferizado como application/json; charset=utf-8 — o valor de retorno do método é ignorado.

Por isso, num método estático você não retorna o MadResponse: você chama ->send(), que anexa dumps pendentes, faz echo json_encode(...) das ops e encerra a execução (assinatura send(): never). Se precisar montar o JSON à mão, use echo json_encode($resp->getOps()) — é exatamente o que send() faz por dentro.

// Metodo PHP-ESTATICO chamado por /app/Classe/metodo?static=1 (Mad.exec,
// notchPostAction, widget JS). Nao ha' ciclo de MadComponent: o retorno e'
// ignorado — o que vale e' o que o metodo ECHOA.
public static function onArquivarTudo(array $params): void
{
    Pedido::whereKey($params['ids'] ?? [])->update(['arquivado' => 1]);

    // send() serializa as ops como JSON e ENCERRA a execucao (`: never`).
    (new MadResponse())
        ->toast('Pedidos arquivados', 'success')
        ->send();
}

// Equivalente explicito, quando voce precisa continuar depois de montar as ops
// (juntar com outra fonte, envelopar, logar) em vez de encerrar ali:
public static function onFeed(array $params): void
{
    $resp = (new MadResponse())->html('#painel', $html);
    echo json_encode($resp->getOps(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
O envelope muda quando há debug

Normalmente send() serializa o array de ops direto ([ {op: …}, {op: …} ]), não um objeto com chave ops — diferente do JSON do /app/_mad-wire. A exceção é quando MadLogService::getDebugPayload() tem conteúdo: aí o payload vira { "ops": […], "_debug": {…} }. O client aceita as duas formas.

Qual usar

ContextoUse
Action de MadComponentMadResponse (ou void + auto-bind)
Método estático via ?static=1(new MadResponse())->…->send() — echo, não return
Controller de rota normal (routes/web.php)Illuminate\Http\Response / view() nativo do Laravel
Controller REST (ApiResourceController e afins)Illuminate\Http\JsonResponse (response()->json(...))
Redirect com flash/old inputredirect(...)->with(...)->withInput() nativo

Próximos passos