PHPackages                             hyvor/laravel-json-meta - 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. hyvor/laravel-json-meta

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

hyvor/laravel-json-meta
=======================

Strict meta data for Eloquent Models, saved in JSON columns

1.0.1(2y ago)108.3k↓31.8%1[1 issues](https://github.com/hyvor/laravel-json-meta/issues)MITPHPPHP ^8.3|^8.2

Since Apr 22Pushed 2y ago1 watchersCompare

[ Source](https://github.com/hyvor/laravel-json-meta)[ Packagist](https://packagist.org/packages/hyvor/laravel-json-meta)[ RSS](/packages/hyvor-laravel-json-meta/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (4)Versions (9)Used By (0)

Laravel JSON Meta
=================

[](#laravel-json-meta)

A library for saving metadata in a JSON column, with strict type checking using PHPStan.

- Best for saving configuration options and other metadata
- Nested objects are not supported

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

[](#installation)

Install the package via composer.

```
composer require hyvor/laravel-json-meta
```

If you use PHPStan (highly recommended), add the following to your `phpstan.neon` file. This improves the type checking of the library.

```
includes:
    - vendor/hyvor/laravel-json-meta/extension.neon
```

### Metadata or column?

[](#metadata-or-column)

When saving data, you have to decide between meta vs column. A general rule is that if that data is needed for a `WHERE` or `ORDER BY`, save it in a column. If not, you may save it in metadata. In most cases, configuration options are the best things to save in metadata.

(You can still use metadata in `WHERE` queries if your database engine supports JSON operations.)

Usage
-----

[](#usage)

Let's say you want to save metadata of `blogs` in a JSON column named `meta`.

First, add a JSON `meta` column to the table.

```
Schema::create('blogs', function (Blueprint $table) {
    // other columns

    $table->json('meta')->nullable();
});
```

> If your database does not support native JSON columns, Laravel will create a TEXT column, which works fine with this library.

### Update the Model

[](#update-the-model)

- Add `HasMeta` trait
- Declare the `defineMeta` method

```
use Hyvor\JsonMeta\HasMeta;
use Hyvor\JsonMeta\MetaDefinition;

class Blog extends Model
{

    use HasMeta;

    protected function defineMeta(MetaDefinition $meta)
    {
        // definition goes here
    }

}
```

### Definition

[](#definition)

"Definition" is which data types you allow saving in the `meta` field. By defining them, you can make sure that incorrect data is never inserted by invalid user input or typos in your code. The following methods are available in the `MetaDefinition` class.

- `string(string $name)`
- `integer(string $name)`
- `float(string $name)`
- `boolean(string $name)`
- `enum(string $name, string[]|class-string $values)`

```
protected function defineMeta(MetaDefinition $meta)
{

    // string
    $meta->string('seo_robots')->nullable();

    // integer
    $meta->integer('max_comments')->default(100);

    // float
    $meta->float('comment_delay')->default(0.5);

    // boolean
    $meta->boolean('seo_indexing')->default(true);

    // enum (string)
    $meta->enum('comments_type', ['hyvor', 'other'])->default('hyvor');

    // enum (PHP Enum)
    $meta->enum('comments_type', CommentType::class)->default(CommentType::HYVOR);

}
```

### Default value

[](#default-value)

You should always set a default value for each metadata.

Use the `default` method to set the default value. The value should be of the same type as the type you defined.

```
$meta->string('seo_robots')->default('index, follow');
```

Or, you can use `nullable` to set the default value to `null`.

```
$meta->string('seo_robots')->nullable();
```

In the above example, the type of `seo_robots` is now `string|null`.

### Methods

[](#methods)

The `HasMeta` trait adds the following methods to the model.

**metaGet(string $name) : mixed**

To get a meta value by name. The `$name` should be one of the names you defined in the `metaDefinition` function. If the value is not set, the default value will be returned.

```
$seoIndexingOn = $blog->metaGet('seo_indexing');
```

**metaGetAll() : array**

To get all meta values. All keys you define in `metaDefinition` function will be set in the returned array, filled with default values if missing in the `meta` field.

```
$meta = $blog->metaGetAll();

if ($meta['seo_indexing']) {
    echo "Hey Google, Please index me!";
}
```

**metaSet(string|array $name, mixed $value) : void**

Set meta `$name` to `$value`. In addition to static type checking via PHPStan, runtime type checking is done here to prevent invalid values from being saved.

```
$blog->metaSet('seo_indexing', false);
```

```
// throws an error (wrong type)
$blog->metaSet('seo_indexing', 'no');
```

You may also send an array as the first param to update multiple values.

```
$blog->metaSet([
    'seo_indexing' => false,
    'comments_type' => CommentType::OTHER
]);
```

Types
-----

[](#types)

Include the PHPStan extension to get better type checking.

```
includes:
    - vendor/hyvor/laravel-json-meta/extension.neon
```

This registers the generic utility type `meta-of`. You can use this type to easily get the type of the meta fields as a constant array.

```
/**
*  @param key-of $key
*/
function handleMeta($key) {
    // $key is a key of the meta definition of Blog
}
```

Why?
----

[](#why)

Why save metadata in a JSON column?

Let's see other options:

**CASE 1**: You could save metadata in separate columns.

- Maintaining a lot of columns is hard. You would need migrations to add new columns.
- Most of the time, users do not change the default values. So, most of the columns will be empty. It's much better to save them only when they are changed (which is what this library does). See "How data is saved" section below.
- Databases have max row size. In MYSQL it is around 65KB. At [Hyvor Talk](https://talk.hyvor.com), we are closer to this limit, and it is one of the main reasons we developed this library. Note that in this library, we save metadata in TEXT, BLOB, and JSON columns, which are not counted in the row size limit.

**CASE 2**: You could save metadata in a separate table.

This is actually a good option. Check the [laravel-meta](https://github.com/kodeine/laravel-meta) library which has a similar concept like this library but saves data in a separate table.

How data is saved
-----------------

[](#how-data-is-saved)

When a new model is created, `meta` is `NULL`. Meta column only contains fields that were changed. For example, if you set `seo_indexing` to `false`, you will have the following JSON in the `meta` column:

```
{
  "seo_indexing": false
}
```

This way, you will save a lot of space in the database.

### Adding new metadata

[](#adding-new-metadata)

Let's say you want to add a new metadata called `seo_follow_external_links`. This task is pretty easy. All you have to do is adding this to the definition.

```
use Hyvor\JsonMeta\MetaDefinition;

public function defineMeta(MetaDefinition $meta)
{
    // old definitions

    // the new one
    $meta->boolean('seo_follow_external_links')->default(false);

}
```

### Updating metadata

[](#updating-metadata)

Updating is a bit tricky. Let's say you want to rename `seo_indexing` to `seo_indexing_on`. You could update the definition, but the problem is with the values that are already saved in the database.

How do you update this:

```
{
  "seo_indexing": false
}
```

to this:

```
{
  "seo_indexing_on": false
}
```

One option is to use JSON operations in the database. Or, use a custom script. Currently, this library does not provide this feature out of the box. But, if required in the future, we will add a command to do this. (Contributions/ideas are welcome)

### Removing metadata

[](#removing-metadata)

If you need to remove `seo_indexing` option from your application, you should first remove it in the meta definition.

You will still have old data saved in the database meta fields, but it should not be a problem as that data will be not be used even its there.

However, if you are required to delete those data (ex: for legal reasons), you will need an option similar to the "Updating metadata" section. Again, contributions are welcome.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity31

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity69

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 ~123 days

Recently: every ~185 days

Total

7

Last Release

746d ago

Major Versions

0.0.3 → v1.x-dev2024-05-01

PHP version history (3 changes)0.0.1PHP ^8.1

v1.x-devPHP ^8.3|^8.2|^8.1|^8.0

1.0.0PHP ^8.3|^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/53796347?v=4)[HYVOR](/maintainers/HYVOR)[@hyvor](https://github.com/hyvor)

---

Top Contributors

[![supun-io](https://avatars.githubusercontent.com/u/44988673?v=4)](https://github.com/supun-io "supun-io (18 commits)")

---

Tags

databaseeloquentjsonlaravel

###  Code Quality

TestsPest

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/hyvor-laravel-json-meta/health.svg)

```
[![Health](https://phpackages.com/badges/hyvor-laravel-json-meta/health.svg)](https://phpackages.com/packages/hyvor-laravel-json-meta)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90440.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)[wildside/userstamps

Laravel Userstamps provides an Eloquent trait which automatically maintains `created\_by` and `updated\_by` columns on your model, populated by the currently authenticated user in your application.

7511.7M13](/packages/wildside-userstamps)

PHPackages © 2026

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