Cargando…

Esto está tardando más de lo esperado.

Estándares de código

Laravel Observers

Estos son los estándares que aplica el analizador. Cada regla dice qué revisa y por qué existe.

Todos los estándares

Reglas generales para Observers

Orden de eventos preferido: saving → creating/updating → created/updated
Si una lógica siempre se ejecuta en cambios del modelo, modifica datos relacionados y debe mantenerse centralizada → pertenece a un Observer.
Los jobs y efectos secundarios que siempre deben ejecutarse después de que se guarda un modelo (p. ej., sincronizar con un servicio externo) pertenecen al hook saved del observer, no al llamador. El componente Livewire o el controller nunca deben despachar jobs en nombre de un modelo, ni deben llamar efectos secundarios directamente sobre modelos relacionados. Las acciones de UI que eliminan o cambian datos relacionados solo deben actualizar el estado pendiente local — el observer se encarga de la persistencia al guardar.

// Correct — observer owns the side effect
public function saved(Plan $plan)
{
    SyncWithExternalServiceJob::dispatch($plan)->afterCommit();
}

// Incorrect — caller dispatches the job
public function save()
{
    $this->object->save();
    SyncWithExternalServiceJob::dispatch($this->object)->afterCommit(); // wrong place
}

Cuando un observer tiene más de 4 métodos en total, organízalos con comentarios de sección usando el mismo estilo /* */ que en los modelos: Live Events (hooks que se ejecutan antes de la escritura en la BD: saving, creating, updating, deleting) → Events (hooks que se ejecutan después: saved, created, updated, deleted) → Methods (todos los helpers private). Incluye solo las secciones que estén presentes — no agregues una sección vacía. No agregues comentarios de sección cuando el observer tenga 4 métodos o menos.
Los métodos hook del observer (saving, updating, saved, etc.) deben delegar a métodos private con nombre cuando la lógica tenga 3 o más líneas, o cuando la misma lógica se llame desde múltiples hooks. Las operaciones de una sola línea deben quedarse inline — extraerlas a un método private agrega indirección sin aportar beneficio.

// Correct — 1 line stays inline
public function creating(BillingPrice $price): void
{
    $price->stripe_price_id = app(StripeSyncService::class)->syncPrice($price);
}

// Correct — 3+ lines get a named private method
public function updating(BillingPrice $price): void
{
    $this->preventAmountModification($price);
}

private function preventAmountModification(BillingPrice $price): void
{
    if ($price->isDirty('amount')) {
        throw CannotModifyCreatedPriceAmount::for($price);
    }
}

// Incorrect — 1-line logic extracted unnecessarily
public function creating(BillingPrice $price): void
{
    $this->assignStripePriceId($price);
}

private function assignStripePriceId(BillingPrice $price): void
{
    $price->stripe_price_id = app(StripeSyncService::class)->syncPrice($price);
}

No usar ValidationException en Observers

Los Observers no deben lanzar ni importar Illuminate\Validation\ValidationException. Los Observers se ejecutan como infraestructura del ciclo de vida del modelo, por lo que no deben encargarse de la validación de formularios/entradas ni de los mensajes de campos orientados al usuario.
Marca esta regla solo cuando un observer importe, lance o construya directamente ValidationException, o cuando use excepciones de estilo de validación para informar errores normales de formulario que el usuario puede corregir.
Al reemplazar un ValidationException en un observer:

  • Mueve la validación a nivel de campo y los errores orientados al usuario al componente Livewire, form request, action class o regla de validación dedicada antes de que el modelo se guarde.
  • Si quien llama necesita saber si una operación esperada puede continuar, expón esa decisión antes del guardado mediante un método del modelo, policy, rule o un resultado explícito de la operación controlada por quien llama.
  • No exijas que los métodos hook del observer devuelvan bool solo porque se eliminó un ValidationException. Los hooks del observer deben seguir siendo manejadores del ciclo de vida; los fallos esperados y corregibles por el usuario deben gestionarse antes de que el observer se ejecute.
  • Se permiten excepciones de invariante de dominio cuando el estado sea realmente excepcional y deba bloquearse a nivel del ciclo de vida, pero usa una excepción específica del dominio en lugar de ValidationException.
// Correct — Livewire owns the user-facing validation before save
if ($this->object->amountCannotBeModified()) {
    $this->addError('amount', __('The price amount cannot be modified once created.'));
    return;
}

$this->object->save();

// Incorrect — observer throws a UI/form validation exception
throw ValidationException::withMessages([
    'amount' => __('The price amount cannot be modified once created.'),
]);

Orden de los hooks del observer

Los hooks se declaran en el orden en que Eloquent los ejecuta:

saving  →  creating / updating  →  created / updated

Dentro de un grupo el orden da igual: creating arriba de updating, o al revés, ambos se leen bien porque ninguno corre antes que el otro para el mismo registro.
Lo que no debe pasar es que un hook retroceda a una etapa anterior. Leer created() y encontrar saving() más abajo le dice al lector que la clase corre en ese orden, y no es así — así que el único lugar al que alguien acude para conocer la secuencia es el único lugar que le miente.

// Correcto
public function saving(Order $order) { ... }
public function creating(Order $order) { ... }
public function created(Order $order) { ... }

// Incorrecto — saving se declara después de una etapa posterior
public function created(Order $order) { ... }
public function saving(Order $order) { ... }
Weblabor Logo Desarrollado por Weblabor