Vai al contenuto
DedicatedPHP Contatto

Come progettare un registro delle attività in PHP utile al supporto

Progetta uno storico operativo consultabile dal backoffice, così il supporto può ricostruire gli incidenti in PHP senza copiare dati sensibili né confonderlo con un sistema di audit.

Storico delle attività in un backoffice PHP con eventi di abbonamento ordinati per data

Quando il supporto deve spiegare perché è cambiato lo stato di un ordine, chi ha avviato un’azione o dove si è interrotto un processo, i log tecnici sparsi non sempre offrono una risposta comprensibile. Un registro delle attività nelle applicazioni PHP può conservare gli eventi operativi rilevanti e renderli consultabili dal backoffice, senza diventare una copia di tutti i dati di business né un sostituto di un sistema di audit.

La progettazione inizia definendo a quali domande deve rispondere lo storico. Poi si decidono gli eventi, i dati che contengono, le garanzie di persistenza e i controlli di accesso. I criteri seguenti si applicano a diversi framework PHP: i nomi di tabelle, servizi e codice devono essere adattati all’architettura e alle policy di ogni applicazione.

Registro delle attività, log tecnici e audit risolvono problemi diversi

Registro delle attività, log tecnici e audit risolvono problemi diversi — guía visual de DedicatedPHP

I log tecnici aiutano a diagnosticare il comportamento interno dell’applicazione: errori, eccezioni, tempi di esecuzione o chiamate non riuscite. Sono rivolti principalmente all’ingegneria del software e possono includere dettagli utili per l’osservabilità, ma non necessariamente il contesto di business di cui ha bisogno il supporto.

Il registro delle attività descrive fatti operativi con un linguaggio che il team può interpretare: «il pagamento è passato in revisione» oppure «è stato richiesto un rimborso». Il registro di audit risponde a esigenze di accountability, conformità o indagine: chi ha avuto accesso o ha modificato cosa, quando e secondo quali controlli. Può richiedere una copertura più ampia, protezione contro le alterazioni e policy formali di conservazione.

Le categorie possono utilizzare un’infrastruttura condivisa, ma uno storico funzionale non soddisfa automaticamente un obbligo di audit. Se sono richieste prove resistenti alle alterazioni o una catena di custodia, questi requisiti devono essere progettati e convalidati separatamente.

Definire cosa deve poter indagare il supporto

Prima di creare una tabella o un’interfaccia, raccogli casi concreti del supporto e delle operations. Per esempio: determinare perché un abbonamento è stato sospeso, quando è stato ritentato un’integrazione o quale passaggio ha completato un utente prima che una richiesta fallisse. Per ogni caso, chiediti quale decisione prenderebbe il supporto sulla base della risposta e quali informazioni dovrebbe vedere per ricostruire quanto accaduto.

Registra le modifiche rilevanti, le transizioni di stato e gli esiti dei processi importanti. Per impostazione predefinita, non registrare ogni lettura del database né ogni chiamata interna: questo aumenta il volume senza garantire il contesto. Se un evento non aiuta a rispondere a una domanda operativa, probabilmente appartiene ai log tecnici oppure non è necessario conservarlo.

Lo storico può aiutare a ricostruire ciò che l’applicazione ha elaborato, ma non dimostra necessariamente ciò che una persona ha visto sullo schermo né permette di recuperare dati che non sono mai stati registrati. È opportuno esplicitare questi limiti nell’interfaccia e nelle aspettative del supporto.

Progettare un evento utile e integrarlo in PHP

Un evento ha bisogno di una struttura stabile, non di una frase diversa improvvisata in ogni controller. Uno schema relazionale minimo potrebbe includere:

activity_events
- id              UUID o identificatore interno
- tenant_id       identificatore dell’account, se applicabile
- event_type      subscription.paused
- actor_type      user | system | service
- actor_id        identificatore, può essere null
- subject_type    subscription
- subject_id      identificatore dell’entità
- outcome         succeeded | failed | pending
- occurred_at     istante UTC
- correlation_id  identificatore della richiesta o del processo
- context         JSON limitato e convalidato

Lo schema è indicativo. In PHP può essere implementato tramite una migration e un model; definisci tipi, chiavi, indici e policy di cancellazione in base al database e alle query previste. Per uno storico per entità sono spesso utili indici che includano l’ambito di accesso, come tenant_id, l’entità e la data. Verificali con il piano di esecuzione e dati rappresentativi.

Centralizza la scrittura in un servizio applicativo, per esempio ActivityRecorder, invece di costruire le righe in modo diverso nei controller e nei task in background. Questo frammento mostra la struttura dell’evento, non una specifica API di framework:

$event = [
    'event_type' => 'subscription.paused',
    'actor_type' => 'user',
    'actor_id' => $authenticatedUser->id,
    'subject_type' => 'subscription',
    'subject_id' => $subscription->id,
    'outcome' => 'succeeded',
    'occurred_at' => new DateTimeImmutable('now', new DateTimeZone('UTC')),
    'correlation_id' => $requestId,
    'context' => ['reason_code' => 'payment_review'],
];

$activityRecorder->record($event);

Il servizio deve convalidare il tipo di evento e le chiavi consentite in context, normalizzare l’istante e ricavare l’identità dal contesto autenticato lato server, non da un valore inviato dal client. Tieni separato il tipo di evento dal testo mostrato: in questo modo è possibile modificare le etichette senza perdere filtri stabili. In un task automatico, registra l’attore come sistema o servizio e conserva l’identificatore del processo se aggiunge contesto.

Omettere, riassumere e proteggere i dati sensibili

Non copiare automaticamente la richiesta HTTP, l’oggetto completo di un’entità né tutti i valori precedenti e successivi dei suoi campi. Queste pratiche possono esporre password, token, dati personali o informazioni di pagamento e complicano la conservazione e il controllo degli accessi.

Includi solo ciò che serve per rispondere alla domanda del supporto. Può bastare registrare che è cambiato il metodo di contatto, senza indicarne il valore; oppure specificare che un provider ha rifiutato un’operazione, senza salvare la risposta completa. Se un dato identificativo è indispensabile, valuta se sia possibile mascherarlo o mostrarlo soltanto al personale autorizzato.

Convalida e limita il contenuto JSON, proteggi le esportazioni e valuta la possibilità di registrare l’accesso alle informazioni particolarmente sensibili. La policy deve contemplare backup, ambienti di test e cancellazione, oltre alla tabella principale.

Scegliere tra scrittura transazionale ed elaborazione asincrona

Se l’evento descrive un cambiamento di business che non deve comparire senza che il cambiamento sia confermato, salvarlo nella stessa transazione mantiene allineati entrambi i fatti. In PHP, la scrittura deve usare la stessa connessione e partecipare alla transazione aperta dall’operazione. Se quest’ultima viene annullata, anche l’evento dovrebbe essere annullato.

Questa scelta fa sì che la scrittura influisca sulla latenza e sulla disponibilità del flusso. In caso di errore, l’applicazione può interrompere l’intera operazione oppure consentire il cambiamento senza storico: non sono comportamenti equivalenti e vanno decisi esplicitamente.

Per distribuire eventi ad altri sistemi, un’opzione consiste nel salvare una voce outbox nella stessa transazione e pubblicarla in seguito. Il consumer deve tollerare i tentativi ripetuti e i duplicati, per esempio tramite identificatori idempotenti. Una coda diretta senza coordinamento transazionale può disallinearsi dal cambiamento di business.

Rendere consultabile lo storico nel backoffice

Una scheda di abbonamento potrebbe mostrare una riga come: «12:40 UTC · Ana López ha messo in pausa l’abbonamento · Motivo: revisione del pagamento · Riuscito». La vista può offrire una sezione espandibile con l’identificatore di correlazione, in modo che il team di ingegneria possa collegarlo a una traccia. Non è necessario esporre il JSON completo a tutti i ruoli.

La query può filtrare per ambito, entità e data, e ordinare gli eventi dal più recente. In SQL parametrizzato, l’idea sarebbe:

SELECT event_type, actor_type, actor_id, outcome,
       occurred_at, correlation_id, context
FROM activity_events
WHERE tenant_id = :tenant_id
  AND subject_type = :subject_type
  AND subject_id = :subject_id
ORDER BY occurred_at DESC
LIMIT :page_size;

In PHP, usa parametri associati tramite il livello di accesso ai dati del progetto; non concatenare in SQL i valori ricevuti dall’utente. Aggiungi paginazione e limiti temporali, ed evita di caricare l’intero storico o di applicare filtri costosi su JSON. Poter aprire una scheda non implica necessariamente il permesso di consultare o esportare tutti i suoi eventi: applica controlli in base ai dati esposti.

Gestire conservazione, volume e integrità

Definisci un periodo di conservazione, una modalità di eliminazione o archiviazione e cosa succede ai record associati a entità eliminate. La decisione deve tenere conto dell’uso operativo, degli obblighi applicabili e dei costi di archiviazione; conservare i dati a tempo indeterminato non è una policy di conservazione.

Il volume dipende dalla frequenza degli eventi e dalle dimensioni del loro contesto. Limita i campi variabili, misura i tempi di query e separa i dati recenti da quelli storici se i pattern di utilizzo lo giustificano. Una tabella nel database dell’applicazione non è immutabile solo perché si chiama «audit»: chi dispone di autorizzazioni sufficienti potrebbe modificarla. Se è richiesta integrità probatoria, servono controlli specifici e una valutazione indipendente.

Checklist per un’applicazione PHP esistente

Checklist per un’applicazione PHP esistente — guía visual de DedicatedPHP
  • Documentare le domande del supporto e gli eventi necessari per rispondervi.
  • Definire uno schema con attore, azione, entità, esito, istante e correlazione, quando pertinente.
  • Centralizzare la scrittura in un servizio che convalidi l’evento e limiti il contesto.
  • Escludere i segreti e ridurre i dati personali al minimo strettamente necessario.
  • Decidere quali scritture condividono una transazione con il cambiamento di business e come gestire gli errori.
  • Testare filtri, autorizzazioni, paginazione e indici con i pattern di query reali.
  • Stabilire conservazione, cancellazione, accesso ai dati storici e gestione dei backup.
  • Testare operazioni riuscite, errori, tentativi ripetuti, duplicati e rollback delle transazioni.

Un buon registro delle attività non cerca di raccontare tutto ciò che accade in PHP. Conserva i fatti operativi necessari per spiegare decisioni ed esiti, con un contesto sicuro e consultabile dal backoffice. Se emergono requisiti di prova formale, copertura esaustiva o protezione contro le alterazioni, trattali come un progetto di audit distinto e definiscine i controlli prima di affidarti allo storico per questo scopo.

Vuoi applicare queste idee al tuo progetto?Parliamo della tua piattaforma PHP.
Visualizza il servizio correlato