Come Flare gestisce i componenti single file di Livewire v4
Una delle funzionalità di Livewire v4 è la possibilità di creare componenti single file. Invece di distribuire la logica tra una classe PHP e una vista Blade, ora puoi scrivere tutto in un singolo file .php.
È un'esperienza di sviluppo fantastica.
Finché qualcosa non si rompe.
Quando si verifica un errore all'interno di un componente single file, la stack trace punta a un file compilato con un nome hash come ab1234cd.php. Non è molto utile quando stai cercando di capire cosa sia andato storto. Volevamo che Flare ti mostrasse il file sorgente reale al numero di riga reale, proprio come fa per i componenti Livewire normali.
Ecco come abbiamo fatto.
Il problema dei file compilati
I componenti Livewire tradizionali sono semplici da gestire per Flare. C'è una classe PHP e una vista Blade. Sappiamo come mappare entrambi ai rispettivi file sorgente.
I componenti single file sono diversi. Livewire li compila in classi anonime con nomi file hash e li memorizza nella directory di cache. Quando viene lanciata un'eccezione, la stack trace assomiglia a questa:
/storage/framework/cache/livewire/ab1234cd.php:42
Quel percorso non ti dice nulla su quale componente ha fallito. E la riga 42 nell'output compilato non corrisponderà alla riga 42 del tuo file sorgente.
Mappare gli hash ai file sorgente
Durante la fase di compilazione, Livewire crea una cache che mappa i nomi dei componenti alle loro classi compilate.
Flare legge quella cache usando la reflection:
$factory = $this->app->make('livewire.factory');
$reflection = new ReflectionProperty($factory, 'resolvedComponentCache');
$resolvedComponents = $reflection->getValue($factory);
La mappa assomiglia più o meno a questa:
[ 'counter' => "class@anonymous\x00/storage/framework/cache/livewire/ab1234cd.php:12$0", ]
Poi eseguiamo un loop su ogni componente risolto. La stringa della classe di un componente single file contiene un byte nullo seguito dal percorso del file compilato:
foreach ($resolvedComponents as $name => $class) {
$compiledClassPath = preg_replace('/:\d+\$.*$/', '', substr($class, strpos($class, "\x00") + 1));
}
A questo punto abbiamo l'hash del percorso compilato, ma solo il nome del componente come counter. Non sappiamo ancora dove si trovi il file sorgente. Quindi chiediamo al Finder di Livewire di risolverlo:
$sourcePath = $this->livewireComponentFinder->findSingleFileComponentFile($name);
if (preg_match('/[\/\\\\]([a-f0-9]+)\.php$/', $compiledClassPath, $matches)) {
$this->compiledPathMap[$matches[1]] = $sourcePath;
}
Il risultato finale è una semplice mappa inversa:
"ab1234cd" => "/resources/views/livewire/counter.php"
Quando successivamente Flare incontra un percorso hash in una stack trace, controlla questa mappa e sostituisce il percorso reale del file. La mappa viene costruita in modo lazy, solo quando un componente single file è presente nella richiesta corrente. Se non stai utilizzando componenti single file, nessuno di questo codice viene eseguito.
Correggere le stack trace
Con la mappa inversa pronta, dobbiamo integrarla nell'elaborazione delle stack trace di Flare. Il LaravelStacktraceMapper esamina ogni frame in una stack trace e controlla se punta a una vista compilata:
public function map(array $frames, ?Throwable $throwable): array
{
$frames = array_map(function (Frame $frame) {
if ($originalPath = $this->viewFrameMapper->findCompiledView($frame->file)) {
$frame->file = $originalPath;
$frame->lineNumber = $this->viewFrameMapper->getBladeLineNumber(
$frame->file,
$frame->lineNumber
);
}
return $frame;
}, $frames);
return parent::map($frames, $throwable);
}
Se il percorso del file di un frame corrisponde a un hash nella nostra mappa inversa, lo sostituiamo con il percorso sorgente reale.
Il passaggio successivo è correggere il numero di riga, che a questo punto è ancora il numero di riga del componente Blade compilato.
Flare sa già come mappare i numeri di riga di Blade compilati ai numeri di riga sorgente. Usiamo la stessa logica getBladeLineNumber che abbiamo sempre usato per le viste Blade normali. Poiché un componente single file è essenzialmente una vista Blade, non è stata necessaria una nuova mappatura dei numeri di riga. Dovevamo solo prima arrivare al percorso reale del file.
Etichettare correttamente le trace
Flare non si limita a correggere le stack trace. Registra anche le trace delle prestazioni della tua applicazione. Una traccia è una linea temporale di tutto ciò che accade durante una richiesta, suddivisa in span individuali. Ogni componente Livewire ha il suo span, che mostra quando è stato montato, idratato e renderizzato.
Quando un componente inizia il rendering, il LivewireRecorder controlla se si tratta di un componente single file e tagga lo span di conseguenza:
$isSingleFileComponent = $this->livewireComponentFinder->isSingleFileComponent($component);
$attributes = [
'livewire.component.name' => $component,
'livewire.component.single_file_component' => $isSingleFileComponent,
];
if (! $isSingleFileComponent) {
$attributes['livewire.component.class'] = $class;
}
Per i componenti basati su classi, Flare registra il nome della classe. Per i componenti single file, non esiste un nome di classe significativo, quindi risolviamo il percorso del file sorgente dal nome del componente e registriamo quello:
if (
$componentState->isSingleFileComponent
&& ($viewFile = $this->livewireComponentFinder->findSingleFileComponentFile($component->getName()))
) {
$componentState->span->addAttribute('view.file', $viewFile);
}
Lo stesso accade per gli span delle viste. Quando il ViewRecorder rileva che la vista corrente appartiene a un componente single file, sostituisce il percorso del file compilato con il file sorgente reale e tagga lo span:
$singleFileComponentFile = $this->livewireComponentFinder->findCurrentSingleFileComponentFile();
if ($singleFileComponentFile) {
$file = $singleFileComponentFile;
$attributes['view.is_livewire_single_file_component'] = true;
}
In questo modo, ogni span nelle tue trace punta al file giusto, che si tratti di un componente basato su classi o di un componente single file.
Progettato per Laravel
Flare è la piattaforma di monitoraggio degli errori e delle prestazioni per Laravel. Ogni funzionalità che creiamo, incluso il supporto ai componenti single file, è progettata per funzionare come gli sviluppatori Laravel si aspettano.
Man mano che il framework si evolve, anche Flare si evolve. Siamo impegnati a integrarci profondamente con l'ecosistema Laravel, così non devi mai lottare con i tuoi strumenti per comprendere la tua applicazione.
Altri articoli recenti
Laravel AI 1.1 e 1.2: Agent Skills, Cohere e structured output più solidi
Le release 1.1.0 e 1.2.0 di laravel/ai portano gli Agent Skills, l'approvazione obbligatoria per i tool built-in e nuovi provider come Cohere e Laya self-hosted. Sul fronte qualità arrivano i fix allo structured output per Bedrock e il supporto alle provider options. Aggiornati anche i modelli di default, con Claude 4.7+ che ignora i sampling params.
Laravel 13.35.0: scheduler più controllabile, code più flessibili e response Markdown
Laravel 13.35.0 porta Schedule::alwaysOnOneServer(), il supporto a schedule:interrupt per i comandi di lunga durata, --memory in percentuale per queue:work e il nuovo metodo markdown() sulla response factory. Tante piccole migliorie anche a test, view compilate in parallelo e dischi local.
BashBox: un interprete Bash in sandbox per agenti AI in PHP
BashBox è un interprete bash scritto in puro PHP che permette di eseguire gli script generati dagli agenti AI senza mai ricorrere a proc_open, exec o shell_exec. Ogni comando è una classe PHP che lavora su un filesystem virtuale, con limiti di esecuzione, quote disco e accesso di rete configurabili. Ideale per chi sviluppa agenti con il Laravel AI SDK o altre librerie simili.