PHPackages                             thinktomorrow/dynamic-attributes - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. thinktomorrow/dynamic-attributes

ActiveLibrary[Database &amp; ORM](/categories/database)

thinktomorrow/dynamic-attributes
================================

easily store and retrieve document values of an eloquent model

2.0.3(3mo ago)1125.0k↑23.5%12MITPHPPHP &gt;=8.3CI passing

Since Oct 9Pushed 3mo ago2 watchersCompare

[ Source](https://github.com/thinktomorrow/dynamic-attributes)[ Packagist](https://packagist.org/packages/thinktomorrow/dynamic-attributes)[ RSS](/packages/thinktomorrow-dynamic-attributes/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (4)Versions (14)Used By (2)

Dynamic attributes
==================

[](#dynamic-attributes)

This small package adds nosql-like storage behaviour to your eloquent model. It allows the model to interact with json column values as if they were top-level attributes.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require thinktomorrow/dynamic-attributes
```

Setup
-----

[](#setup)

Here's the quick how to on setting up the package. We'll assume you already have an eloquent model set up.

1. Add a json column to the database scheme of your eloquent model. By default, it should be named `values`.
2. Add the `HasDynamicAttributes` trait to your eloquent model.
3. Add a `dynamicKeys` property on the model and fill it with the value keys that should be stored and fetched from the json column.

Here's an example setup:

```
use Illuminate\Database\Eloquent\Model;
use Thinktomorrow\DynamicAttributes\HasDynamicAttributes;

class ExampleModel extends Model
{
+    use HasDynamicAttributes;

+    protected $dynamicKeys = ['firstname', 'lastname'];

    // ...
}
```

### A json column

[](#a-json-column)

Behind the scenes the values are automatically transposed to and from the json attribute. On the model, no custom eloquent cast is needed, because the trait itself will handle the conversion to and from the stored value.

The dynamic attributes are preferably stored as a json database column but a string typed column should also be fine. The json column will just make your life easier when you need to query the database.

By default, the database column name is assumed to be `values`. You are free to change this.

Usage
-----

[](#usage)

### Setting a value: setDynamic(string $key, $value)

[](#setting-a-value-setdynamicstring-key-value)

The value can be set just like you're used to with any other eloquent attribute. There's a `setDynamic($key, $value)` method which allows you to explicitly set a dynamic attribute.

```
// Setting a dynamic attribute just like a regular attribute.
$model = new ExampleModel(['firstname' => 'Ben']);

// .. or by setting it after instantiation
$model->firstname = 'Ben';

// Is the same as
$model->setDynamic('firstname', 'Ben');
```

### Getting a value: dynamic(string $key)

[](#getting-a-value-dynamicstring-key)

The value can be retrieved like a regular attribute. You can use the `dynamic($key)` method to retrieve the dynamic attribute value as well.

```
// Retrieve a dynamic attribute just like a regular attribute
$model = new ExampleModel(['firstname' => 'Ben']);
$model->firstname; // Ben

// Or via the 'dynamic' method
$model->dynamic('firstname'); // Ben

// In case that the value is an array, a second parameter is used to require a specific key of the array value.
$model = new ExampleModel(['person' => ['name' => 'Ben', 'age' => 39]);
$model->dynamic('person', 'name'); // Ben
$model->dynamic('person', 'age'); // 39

// The 'dynamic' method allows for a default value in case the attribute isn't found
$model->dynamic('xxx', null, 'default'); // default
```

### Checking a value: isDynamic()

[](#checking-a-value-isdynamic)

Checks if the passed key refers to a dynamic attribute key or not.

```
$model->isDynamic('firstname'); // true
$model->isDynamic('xxx'); // false
```

### Raw values

[](#raw-values)

You can get the raw array of dynamic values via the `rawDynamicValues` method.

```
$model->rawDynamicValues() // outputs the entire array: ['firstname' => 'Ben']
```

Localization
------------

[](#localization)

Dynamic attributes are built with localization in mind.

Setting a localized value is done by passing the locale as a nested key:

```
// You can use dot syntax
$model->setDynamic('title.en', 'My article title');
$model->setDynamic('title.nl', 'Mijn blogtitel');

// Optionally pass the locale as third argument
$model->setDynamic('title', 'My article title', 'en');
```

Retrieve the localized value:

```
// When fetching the attribute without locale indication,
// the current application locale will be used.
$model->title; // My article title

app()->setLocale('nl');
$model->title; // Mijn blogtitel

// You can target a specific localized value with the dynamic() method
$model->dynamic('title.en'); // My article title

// If the localized value isn't found, null is returned
$model->dynamic('title.fr'); // null
```

An extra thing you can do is to add a `dynamicLocales` property on your model. This is an array and should contain all the locales of the model. This ensures you return an null value in case a localized value isn't found instead of the entire value array itself.

```
use ...

class ExampleModel extends Model
{
    use HasDynamicAttributes;

    protected $dynamicKeys = ['title'];

+    protected $dynamicLocales = ['en', 'nl'];
}
```

Changing the database column name
---------------------------------

[](#changing-the-database-column-name)

By default the column name is set to `values`. You can change this by overriding the `dynamicDocumentKey` in your model and returning your custom column/attribute name.

Eloquent method inheritance
---------------------------

[](#eloquent-method-inheritance)

The trait class overrides some eloquent methods. These methods are: `getAttribute`, `setAttribute`, `setRawAttributes` and `removeTableFromKey`. This is because of the integral connection with eloquent attribute logic and the way eloquent allows for behavioural change via inheritance.

If you use another trait that also overrides one of these methods, you're gonna bump into a method collision and need to alias the trait methods.

Other solutions
---------------

[](#other-solutions)

There's another great package that provides a similar functionality and that's [spatie/laravel-schemaless-attributes](https://github.com/spatie/laravel-schemaless-attributes). It also provides a nosql-like behaviour for json columns but takes a different approach. The main difference is that our package allows to work with top-level attributes and localized values, which was a requirement for some of our projects. With the package from Spatie, on the other hand, you can add multiple 'nosql' columns, which is currently not possible with our package.

Testing
-------

[](#testing)

```
composer test
```

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [bencavens](https://github.com/bencavens)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

55

—

FairBetter than 98% of packages

Maintenance79

Regular maintenance activity

Popularity35

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity76

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~161 days

Recently: every ~92 days

Total

13

Last Release

111d ago

Major Versions

0.4.2 → 1.0.02025-01-08

1.0.1 → 2.0.02025-02-25

PHP version history (5 changes)0.1PHP ^7.4

0.2.0PHP ^7.4|^8.0

0.4.0PHP ^8.1

1.0.0PHP ^8.3

2.0.3PHP &gt;=8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/497668?v=4)[Ben Cavens](/maintainers/BenCavens)[@BenCavens](https://github.com/BenCavens)

---

Top Contributors

[![BenCavens](https://avatars.githubusercontent.com/u/497668?v=4)](https://github.com/BenCavens "BenCavens (93 commits)")

---

Tags

eloquentjsonlaravelnosql

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/thinktomorrow-dynamic-attributes/health.svg)

```
[![Health](https://phpackages.com/badges/thinktomorrow-dynamic-attributes/health.svg)](https://phpackages.com/packages/thinktomorrow-dynamic-attributes)
```

###  Alternatives

[owen-it/laravel-auditing

Audit changes of your Eloquent models in Laravel

3.4k33.0M95](/packages/owen-it-laravel-auditing)[staudenmeir/eloquent-json-relations

Laravel Eloquent relationships with JSON keys

1.1k5.8M24](/packages/staudenmeir-eloquent-json-relations)[bavix/laravel-wallet

It's easy to work with a virtual wallet.

1.3k1.1M11](/packages/bavix-laravel-wallet)[dragon-code/migrate-db

Easy data transfer from one database to another

15717.4k](/packages/dragon-code-migrate-db)[gearbox-solutions/eloquent-filemaker

A package for getting FileMaker records as Eloquent models in Laravel

6454.8k2](/packages/gearbox-solutions-eloquent-filemaker)[cybercog/laravel-ownership

Laravel Ownership simplify management of Eloquent model's owner.

9126.6k3](/packages/cybercog-laravel-ownership)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
