v0.4.0 — Cast-mode storage via DataField value object
Ground-up rework of JSON-mode storage. The trait-based HasDataFieldsJson is replaced by a Laravel custom cast that hydrates one self-describing DataField document per JSON column — schema and values merged, no envelope, no separate schema column, multiple "forms" per model.
Pre-release package, no compatibility shim provided. See the migration guide in the README and the CHANGELOG for the full list of breaking changes.
Headline changes
New cast surface
use Ssntpl\DataFields\Support\DataField;
class User extends Model
{
protected $casts = [
'preferences' => DataField::class,
];
}
$user->preferences = DataField::section(items: [
['key' => 'dark_mode', 'type' => 'bool', 'value' => true],
['key' => 'language', 'type' => 'text', 'value' => 'en'],
]);
$user->preferences->dark_mode->value; // bool true
$user->preferences->dark_mode->value = false;
$user->save();Ssntpl\DataFields\Support\DataField— cast value object (Castable,IteratorAggregate,JsonSerializable,ArrayAccess,Countable).Ssntpl\DataFields\Casts\DataFieldCast— Laravel cast (resolved viaCastable::castUsing; consumers writeDataField::class).Ssntpl\DataFields\Support\FieldType— PHP 8.1 backed enum covering all 12 leaf + 3 container types.Ssntpl\DataFields\Concerns\FieldAttributes— shared trait between cast and row modes.
Renames
| Before | After |
|---|---|
Ssntpl\DataFields\Models\DataField (Eloquent model) |
Ssntpl\DataFields\Models\DataRow |
Ssntpl\DataFields\Casts\FieldValueCast |
Ssntpl\DataFields\Casts\RowValueCast |
Ssntpl\DataFields\Traits\HasDataFields |
Ssntpl\DataFields\Concerns\HasDataFields |
Config key data_field_model |
data_row_model |
Column meta_data |
meta |
Constants DataField::BOOL etc. |
FieldType::Bool->value etc. |
DataRow also gains a label column (the short display string) so the description column is freed up for actual long-form helper text — matching the cast-mode shape.
Removed
HasDataFieldsJsontrait — replaced by the cast.JsonModeMigration,SchemaValidator,FieldValue,DataSetValue,FieldLike— folded intoDataFieldor no longer needed.DataSetmodel + trait +data_setstable — grouping is a consuming-app concern; cast-mode containers handle the structured case.- Envelope handling (
{"version": "1.0", ...}wrapping),strict_writesconfig,clearDataFieldsCache().
Other improvements
ValueCasteracceptsFieldType|stringat every entry point.DataRow::delete()cascades wrapped inDB::transaction().FILEvsFILESdecided by declared type, never by stored structure (emptyfilesround-trips as[], not null).select_*rules useRule::in()and reject,/|in option keys.data_fieldsindexed on(owner_id, owner_type, key)as a single composite.auto_load_migrationsconfig flag for consumers who'd rather skipvendor:publish.HasDataFieldsgainsgetFieldValue/setFieldValueupsert helpers.
Migration from 0.2.x
- use Ssntpl\DataFields\Traits\HasDataFields;
+ use Ssntpl\DataFields\Concerns\HasDataFields;
- use Ssntpl\DataFields\Models\DataField;
+ use Ssntpl\DataFields\Models\DataRow;Replace HasDataFieldsJson with the DataField::class cast — see the README's "Migrating from 0.2.x" section for a worked example.
Full changelog
See CHANGELOG.md for the complete list of changes and rationales.