Transforma JSON en colecciones tipificadas con AsCollection::of() de Laravel

  • Publicado el 26 mayo, 2025
  • Palabras: 226

Al trabajar con datos complejos en aplicaciones de Laravel, a menudo es necesario almacenar información estructurada en columnas JSON. Sin embargo, trabajar con arrays sin formato puede generar rápidamente código desordenado y difícil de mantener. Aquí es donde entra en juego el potente método AsCollection::of() de Laravel: transforma tus datos JSON en colecciones de objetos de valor fuertemente tipados con un mínimo esfuerzo.

Transforma JSON en colecciones tipificadas con AsCollection::of() de Laravel

#¿Qué es  AsCollection::of()?

El método AsCollection::of() forma parte del robusto sistema de conversión de Laravel, que permite asignar automáticamente un atributo de Eloquent a una colección de instancias de clase específicas. En lugar de trabajar con arrays sin formato o colecciones genéricas, se puede trabajar con objetos tipificados correctamente que encapsulan tanto datos como comportamiento.

Así es como se define en el modelo de Eloquent:

 

use App\ValueObjects\Option;
use Illuminate\Database\Eloquent\Casts\AsCollection;
 
protected function casts(): array
{
    return [
        'options' => AsCollection::of(Option::class)
    ];
}

 

Detrás de escena, esto equivale a llamar:

 

Collection::make($this->attributes['options'])->mapInto(Option::class);

 

La magia ocurre cuando Laravel hidrata tu modelo desde la base de datos. Tu columna JSON se transforma automáticamente en una colección de tus objetos de valor, lo que te proporciona seguridad de tipos y encapsulamiento.

 

#Ejemplo práctico

Supongamos que estás creando una plataforma de comercio electrónico donde los productos ofrecen múltiples opciones de personalización. Cada opción podría tener un nombre, un ajuste de precio y un indicador de disponibilidad.

Primero, crea un objeto de valor para representar cada opción:

 

namespace App\ValueObjects;

use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;

class ProductOption implements Arrayable, JsonSerializable
{
    public function __construct(
        public readonly string $name,
        public readonly float $priceAdjustment,
        public readonly bool $isAvailable = true
    ) {}
    
    public function toArray()
    {
        return [
            'name' => $this->name,
            'price_adjustment' => $this->priceAdjustment,
            'is_available' => $this->isAvailable,
        ];
    }
    
    public function jsonSerialize(): mixed
    {
        return $this->toArray();
    }
    
    public function isValidForPurchase(): bool
    {
        return $this->isAvailable && $this->priceAdjustment >= 0;
    }
}

 

A continuación, en tu modelo Product, utiliza la conversión AsCollection::of():

 

namespace App\Models;

use App\ValueObjects\ProductOption;
use Illuminate\Database\Eloquent\Casts\AsCollection;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected function casts(): array
    {
        return [
            'options' => AsCollection::of(ProductOption::class)
        ];
    }
    
    public function getAvailableOptionsAttribute()
    {
        return $this->options->filter(fn ($option) => $option->isAvailable);
    }
}

 

Ahora puedes trabajar con las opciones de tu producto como ciudadanos de primera clase en tu base de código:

 

$product = Product::find(1);

// Get all options as ProductOption objects
$allOptions = $product->options;

// Filter using methods on your value object
$validOptions = $product->options->filter(fn ($option) => $option->isValidForPurchase());

// Add a new option (automatically serialized back to JSON)
$product->options->push(new ProductOption('Extra Large', 10.00, true));
$product->save();

 

Es perfecto para escenarios como configuraciones de productos, preferencias de usuario, respuestas de formularios complejos, indicadores de características con metadatos o cualquier situación donde se almacenen datos semiestructurados que siguen un patrón consistente.

¿Listo para ordenar tus columnas JSON y optimizar tus modelos de Laravel? ¡Prueba AsCollection::of() en tu próximo proyecto!

Antonio Jenaro

Desarrollador backend especializado en PHP y Laravel, con sede en Santander, Cantabria. Más de 15 años de experiencia en el desarrollo de aplicaciones web a medida y en la modernización de código heredado.

Archivado en:

Fuente: Harris Raftopoulos

Artículos relacionados

Transmitir grandes conjuntos de datos JSON en Laravel con streamJson()
252

Transmitir grandes conjuntos de datos JSON en Laravel con streamJson()

Personalización de colecciones en Laravel: conozca el atributo CollectedBy
114

Personalización de colecciones en Laravel: conozca el atributo CollectedBy

Inicia la conversación

Hazte miembro de Antonio Jenaro para comenzar a comentar.

Regístrate ahora

¿Ya estás registrado? Inicia sesión