Persist schemaless attributes
mainSchemaless attributes are persisted to the database just like standard Eloquent attributes by calling save() on the model.
$yourModel->save();repository·main·Indexed 22 days ago
https://github.com/spatie/laravel-schemaless-attributesA Laravel package that allows storing arbitrary, schemaless data in a single JSON column of an Eloquent model. It provides a NoSQL-like experience within a relational database, featuring a custom Eloquent cast, a Blueprint migration macro, and a modelScope for querying JSON keys using dot notation and custom operators.
Schemaless attributes are persisted to the database just like standard Eloquent attributes by calling save() on the model.
$yourModel->save();To enable schemaless attributes on a model, you must add a custom cast to the $casts array using Spatie\SchemalessAttributes\Casts\SchemalessAttributes.
If you only have one schemaless column, add the cast directly to the model.
If you need to support multiple schemaless columns, use the SchemalessAttributesTrait and define the columns in a protected $schemalessAttributes array.
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
use Spatie\SchemalessAttributes\SchemalessAttributesTrait;
class TestModel extends Model
{
// For a single column:
public $casts = [
'extra_attributes' => SchemalessAttributes::class,
];
// OR for multiple columns:
use SchemalessAttributesTrait;
protected $schemalessAttributes = [
'extra_attributes',
'other_extra_attributes',
];
// Recommended: Add a scope to use the modelScope functionality
public function scopeWithExtraAttributes(Builder $query):
{
return $this->extra_attributes->modelScope();
}
}Install the package via composer. Note that for Laravel versions 6 & 7 or PHP 7, you must use version 1.x of the package.
Requirements: A database with json column support (e.g., MySQL 5.7+).
composer require spatie/laravel-schemaless-attributesTo store schemaless attributes, add a JSON column to your table using the schemalessAttributes method on the Blueprint object. You can name the column anything (e.g., extra_attributes).
Schema::table('your_models', function (Blueprint $table) {
$table->schemalessAttributes('extra_attributes');
});Use the modelScope() provided by the attribute object to build queries. This is typically exposed via a custom model scope.
Returns models that match all provided key-value pairs:
$model->withExtraAttributes(['name' => 'value', 'name2' => 'value2'])->get();// Exact match
$model->withExtraAttributes('name', 'value')->get();
// Using a custom operator (e.g., LIKE)
$model->withExtraAttributes('name', 'LIKE', 'value%')->get();Use dot notation within the scope to query nested JSON keys:
$model->withExtraAttributes('han->side', 'light')->get();You can interact with schemaless attributes using object notation, array notation, or the get() and set() methods. The get() and set() methods support dot notation for nested attributes.
$model->extra_attributes->name = 'value';
$model->extra_attributes['name'] = 'value';Assigning an array to the column replaces all existing attributes:
$model->extra_attributes = ['name' => 'value'];// Set a nested value
$model->extra_attributes->set('rey.side', 'dark');
// Get a nested value
$model->extra_attributes->get('rey.side');
// Get with a default value
$model->extra_attributes->get('non_existing', 'default');
// Delete a key
$model->extra_attributes->forget('key');The modelScope() method returns an Eloquent Builder instance configured to filter models based on their schemaless attributes. This allows you to perform queries against JSON keys using standard Eloquent syntax.
It supports several argument patterns:
modelScope($builder): Returns the builder as is.modelScope($builder, $attributes): Filters by an array of attributes.modelScope($builder, $name, $value): Filters by a specific key and value (defaults to = operator).modelScope($builder, $name, $operator, $value): Filters by a specific key, operator, and value.// Example: Filtering a query by a schemaless attribute
$query = User::query();
$schemaless = SchemalessAttributes::createForModel($user, 'settings');
// Using the scope to add where clauses
$users = $schemaless->modelScope($query, 'theme', '=', 'dark')
->get();To use schemaless attributes on a model, you must cast a specific database column to the Spatie\SchemalessAttributes\Casts\SchemalessAttributes class. This class acts as an Eloquent cast that returns a Spatie\SchemalessAttributes\SchemalessAttributes object, allowing you to interact with the JSON column as a collection of dynamic attributes.
use Spatie\SchemalessAttributes\Casts\SchemalessAttributes;
class YourModel extends Model
{
protected $casts = [
'custom_attributes' => SchemalessAttributes::class,
];
}To interact with the schemaless attributes of an Eloquent model, use the SchemalessAttributes::createForModel() method. You must provide the model instance and the name of the database column where the JSON attributes are stored.
$schemalessAttributes = SchemalessAttributes::createForModel($model, 'custom_attributes');The SchemalessAttributes object implements Arrayable, Jsonable, and JsonSerializable, allowing it to be easily converted for API responses or debugging.
toArray(): Returns the underlying attributes as an associative array.toJson(): Returns the JSON string representation.$array = $schemalessAttributes->toArray();
$json = $schemalessAttributes->toJson();The package provides a Blueprint macro to simplify adding the required JSON column for schemaless attributes in your Laravel migrations. You can use the schemalessAttributes method on a Blueprint instance. By default, it creates a nullable JSON column named schemaless_attributes.
$table->schemalessAttributes(); // Creates a nullable JSON column named 'schemaless_attributes'
// Or specify a custom column name:
$table->schemalessAttributes('custom_attributes_column');