PHPackages                             chargefield/laravel-savable - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. chargefield/laravel-savable

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

chargefield/laravel-savable
===========================

Savable is a Laravel package that will help you organize your business logic.

v1.0.0(4y ago)05MITPHPPHP ^7.4|^8.0

Since Sep 5Pushed 4y ago1 watchersCompare

[ Source](https://github.com/chargefield/laravel-savable)[ Packagist](https://packagist.org/packages/chargefield/laravel-savable)[ Docs](https://github.com/chargefield/laravel-savable)[ RSS](/packages/chargefield-laravel-savable/feed)WikiDiscussions main Synced 3w ago

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

[![Social Icon of Laravel Savable](/logo.png "Laravel Savable")](/logo.png)

Laravel Savable
===============

[](#laravel-savable)

[![Latest Stable Version](https://camo.githubusercontent.com/73cf518dae0c89ba299ad46c971b44fd1f0004ae1750af8a0e44d07d07180e2c/68747470733a2f2f706f7365722e707567782e6f72672f6368617267656669656c642f6c61726176656c2d73617661626c652f762f737461626c65)](https://packagist.org/packages/chargefield/laravel-savable)[![Total Downloads](https://camo.githubusercontent.com/3aadaee503798df06301c7a6f90d37162440c47917ef18fae787ee3cfc77fc13/68747470733a2f2f706f7365722e707567782e6f72672f6368617267656669656c642f6c61726176656c2d73617661626c652f646f776e6c6f616473)](https://packagist.org/packages/chargefield/laravel-savable)[![License](https://camo.githubusercontent.com/4ebf88c35a2644842d2fd44c59780e8ba16b08e170c1b7b1c23f97d93fd41b0f/68747470733a2f2f706f7365722e707567782e6f72672f6368617267656669656c642f6c61726176656c2d73617661626c652f6c6963656e7365)](https://packagist.org/packages/chargefield/laravel-savable)[![Tests](https://github.com/chargefield/laravel-savable/actions/workflows/main.yml/badge.svg)](https://github.com/chargefield/laravel-savable/actions/workflows/main.yml)

Savable is a Laravel package that will help you organize your business logic.

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

[](#installation)

**You can install the package via composer:**

```
composer require chargefield/laravel-savable
```

Usage
-----

[](#usage)

### Savable Trait

[](#savable-trait)

```
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Chargefield\Savable\Traits\IsSavable;

class Post extends Model
{
    use IsSavable;
}
```

### Example

[](#example)

**A simple example for storing a record from a controller:**

```
namespace App\Http\Controllers;

use App\Models\Post;
use Chargefield\Savable\Fields\SlugField;
use Chargefield\Savable\Fields\StringField;
use Illuminate\Http\Request;

class PostController
{
    public function store(Request $request)
    {
        $post = Post::make()->savable($request->all())->columns([
            StringField::make('title'),
            SlugField::make('slug')->fromField('title'),
            StringField::make('body'),
        ])->save();
    }
}
```

### Savable Columns

[](#savable-columns)

**Setting columns:**

```
$post = Post::make()->savable([...])->columns([
    StringField::make('title'),
    SlugField::make('slug')->fromField('title'),
    StringField::make('body'),
])->save();
```

**Alternatively, you can set savable columns in a model:**

```
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Chargefield\Savable\Fields\Field;
use Chargefield\Savable\Traits\IsSavable;
use Chargefield\Savable\Fields\JsonField;
use Chargefield\Savable\Fields\SlugField;
use Chargefield\Savable\Fields\FileField;
use Chargefield\Savable\Fields\StringField;
use Chargefield\Savable\Fields\BooleanField;
use Chargefield\Savable\Fields\IntegerField;
use Chargefield\Savable\Fields\DatetimeField;

class Post extends Model
{
    use IsSavable;

    /**
     * @return Field[]
     */
    public function savableColumns(): array
    {
        return [
            StringField::make('title')->rules('required|string'),
            SlugField::make('slug')->fromField('title'),
            StringField::make('body')->rules('required|string'),
            FileField::make('image')->nullable()->rules('nullable|image'),
            BooleanField::make('is_featured')->rules('required|boolean'),
            IntegerField::make('order')->strict()->rules('required|integer|min:1'),
            JsonField::make('options')->nullable(),
            DatetimeField::make('published_at')->nullable(),
        ];
    }
}
```

**NOTE:** *`savableColumns()` will get overridden by `columns([...])`*

### Savable Data

[](#savable-data)

**Setting data:**

```
$post = Post::make()->savable(request()->all())->columns([...])->save();
```

or

```
$post = Post::make()->savable()->data(request()->all())->columns([...])->save();
```

**Setting data from request:**

```
$post = Post::make()->savable()->fromRequest()->columns([...])->save();
```

**Setting data from a given request:**

```
$post = Post::make()->savable()->fromRequest(request())->columns([...])->save();
```

### Validation

[](#validation)

**Validating before saving** *(throws Illuminate\\Validation\\ValidationException):*

```
$post = Post::make()->savable()->data([...])->columns([...])->validate()->save();
```

**Validating without throwing an exception:**

```
Post::make()->savable()->data([...])->columns([...])->hasErrors();
// return bool
```

or

```
Post::make()->savable()->data([...])->columns([...])->getErrors();
// return Illuminate\Support\MessageBag
```

**NOTE:** *[Fields](https://github.com/chargefield/laravel-savable#fields) must set `rules([...])` in order to validate their data.*

Fields
------

[](#fields)

### String Field:

[](#string-field)

```
StringField::make('title');
```

### Slug Field:

[](#slug-field)

```
SlugField::make('slug')->fromField('title')->separateBy('-');
```

### File Field:

[](#file-field)

```
FileField::make('image')->disk('local')->path('images')->withOriginalName();
```

### Boolean Field:

[](#boolean-field)

```
BooleanField::make('is_featured');
```

### Integer Field:

[](#integer-field)

```
IntegerField::make('age')->strict();
```

### Json Field:

[](#json-field)

```
JsonField::make('options')->pretty()->depth(512);
```

### Datetime Field:

[](#datetime-field)

```
DatetimeField::make('published_at');
```

### Additional Methods:

[](#additional-methods)

**Sets the column name and default value:**

```
StringField::make('title', 'Default Title');
```

or

```
StringField::make('title')->value('Default Title');
```

**Sets the field name if not the same as the column name:**

```
StringField::make('title')->fieldName('name');
```

**Sets the nullable flag, null will be returned if value is empty/null/exception:**

```
StringField::make('title')->nullable();
```

**Sets the validation rules for the field ([Laravel validation rules](https://laravel.com/docs/8.x/validation#available-validation-rules)):**

```
StringField::make('user_id')->rules('required|exists:users,id');
```

or

```
StringField::make('user_id')->rules([
    'required',
    Rule::exists('users', 'id'),
]);
```

**Sets a closure to transform the value:**

```
StringField::make('title')->transform(function ($fieldName, $fieldValue, $fieldsData) {
    return Str::title($fieldValue);
});
```

### Custom Fields

[](#custom-fields)

You can create custom fields with ease using the artisan command.

```
php artisan make:field CustomField
```

**Outputs:**

```
namespace App\Fields;

use Chargefield\Savable\Fields\Field;

class CustomField extends Field
{
    /**
     * @param array $data
     * @return mixed
     */
    public function handle(array $data = [])
    {
        if (empty($this->value) && $this->nullable) {
            return null;
        }

        // Logic goes here

        return $this->value;
    }
}
```

**Testing custom fields:**

*Field::assertHandle*

```
$field = CustomField::fake('title');
$field->value('Example Title');
$field->assertHandle('Example Title'); // passed
$field->assertHandle('Not The Same'); // failed
```

*Field::assertTransform*

```
$field = CustomField::fake('title');
$field->value('Example Title');
$field->transform(function ($name, $value, $data) {
    return "{$data['prefix']} {$value}";
});
$field->assertTransform('Prefixed Example Title', ['prefix' => 'Prefixed']); // passed
$field->assertTransform('Example Title', ['prefix' => 'Prefixed']); // failed
```

*Field::assertValidation*

```
$field = CustomField::fake('title');
$field->rules('required|string');
$field->assertValidation('Example Text'); // passed
$field->assertValidation(''); // failed
```

Testing
-------

[](#testing)

**You can run the tests with:**

```
vendor/bin/phpunit
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

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

Credits
-------

[](#credits)

- [Clayton D'Mello](https://github.com/chargefield)
- [All Contributors](../../contributors)

License
-------

[](#license)

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

###  Health Score

24

—

LowBetter than 31% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 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

Unknown

Total

1

Last Release

1761d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7b4308d6364461310c6b27d2c0e93835fc3e1237a918967350648aa80a0ab8b9?d=identicon)[chargefield](/maintainers/chargefield)

---

Top Contributors

[![chargefield](https://avatars.githubusercontent.com/u/13471440?v=4)](https://github.com/chargefield "chargefield (79 commits)")

---

Tags

laravelchargefieldsavable

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/chargefield-laravel-savable/health.svg)

```
[![Health](https://phpackages.com/badges/chargefield-laravel-savable/health.svg)](https://phpackages.com/packages/chargefield-laravel-savable)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[renatomarinho/laravel-page-speed

Laravel Page Speed

2.5k1.7M11](/packages/renatomarinho-laravel-page-speed)[vinkius-labs/laravel-page-speed

Laravel Page Speed

2.5k12.5k1](/packages/vinkius-labs-laravel-page-speed)[emargareten/inertia-modal

Inertia Modal is a Laravel package that lets you implement backend-driven modal dialogs for Inertia apps.

90142.9k](/packages/emargareten-inertia-modal)[wearepixel/laravel-cart

A cart implementation for Laravel

1374.8k](/packages/wearepixel-laravel-cart)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

119.4k](/packages/tomshaw-electricgrid)

PHPackages © 2026

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