Skip to content

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

License

MIT, MIT licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE.md
Notifications You must be signed in to change notification settings

chargefield/laravel-savable

Repository files navigation

Social Icon of Laravel Savable

Laravel Savable

Latest Stable Version Total Downloads License Tests

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

Installation

You can install the package via composer:

composer require chargefield/laravel-savable

Usage

Savable Trait

namespace App\Models;

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

class Post extends Model
{
    use IsSavable;
}

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

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

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

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 must set rules([...]) in order to validate their data.

Fields

String Field:

StringField::make('title');

Slug Field:

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

File Field:

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

Boolean Field:

BooleanField::make('is_featured');

Integer Field:

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

Json Field:

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

Datetime Field:

DatetimeField::make('published_at');

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):

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

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

You can run the tests with:

vendor/bin/phpunit

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

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

Credits

License

The MIT License (MIT). Please see License File for more information.

About

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

Resources

License

MIT, MIT licenses found

Licenses found

MIT
LICENSE
MIT
LICENSE.md

Stars

Watchers

Forks

Packages

No packages published

Languages