awobaz/eloquent-mutators

Reusable accessors/mutators (getters/setters) for Laravel 5's Eloquent

1.0.14 2020-10-07 23:23 UTC

README

Eloquent Mutators allows us to define accessors and mutators outside of an Eloquent model. This gives us the ability to organize and reuse them on any model or any attribute of the same model.

The problem

Eloquent has support for accessors and mutators. However, it requires us to define them directly in the model. What if we want to reuse an accessor/mutator logic in another model? Or, what if we want to reuse an accessor/mutator logic for another attribute of the same model? We can't! Eloquent Mutators aims at solving this limitation.

Related discussions:

Installation

The recommended way to install Eloquent Mutators is through Composer

$ composer require awobaz/eloquent-mutators

The package will automatically register itself if you're using Laravel 5.5+. For Laravel 5.4, you'll have to register the package manually:

  1. Open your config/app.php and add the following to the providers array:
Awobaz\Mutator\MutatorServiceProvider::class,
  1. In the same config/app.php add the following to the aliases array:
'Mutator'   => Awobaz\Mutator\Facades\Mutator::class,

Note: Eloquent Mutators requires Laravel 5.4+.

After installation, publish the assets using the mutators:install Artisan command. The primary configuration file will be located at config/mutators.php. The installation also publishes and registers the app/Providers/MutatorServiceProvider.php. Within this service provider, you may register custom accessors/mutators extensions.

php artisan mutators:install

Usage

Using the Awobaz\Mutator\Database\Eloquent\Model class

Simply make your model class derive from the Awobaz\Mutator\Database\Eloquent\Model base class. The Awobaz\Mutator\Database\Eloquent\Model extends the Eloquent base class without changing its core functionality.

Using the Awobaz\Mutator\Mutable trait

If for some reasons you can't derive your models from Awobaz\Mutator\Database\Eloquent\Model, you may take advantage of the Awobaz\Mutator\Mutable trait. Simply use the trait in your models.

Syntax

After configuring your model, you may configure accessors and mutators for its attributes.

Defining accessors

For the following Post model, we configure accessors to trim whitespace from the beginning and end of the title and content attributes:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use \Awobaz\Mutator\Mutable;
    
    protected $accessors = [
        'title'   => 'trim_whitespace',
        'content' => 'trim_whitespace',
    ];
}

As you can see, we use an array property named accessors on the model to configure its accessors. Each key of the array represents the name of an attribute, and the value points to one or multiple accessors. To apply multiple accessors, pass an array as value (the accessors will be applied in the order they are specified):

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use \Awobaz\Mutator\Mutable;
    
    protected $accessors = [
        'title'   => ['trim_whitespace', 'capitalize'], 
        'content' => ['trim_whitespace', 'remove_extra_whitespace'],
    ];
}

Defining mutators

To define mutators, use an array property named mutators instead.

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use \Awobaz\Mutator\Mutable;
    
    protected $mutators = [
        'title'    => 'remove_extra_whitespace',
    ];
}

Note: The name of the properties used for accessors and mutators can be respectively configured in the config/mutators.php configuration file.

Defining accessors/mutators extensions

In the previous examples, we use accessors/mutators provided by the package. You may also register accessors/mutators extensions using the extend method of the Mutator facade. The extend method accepts the name of the accessor/mutator and a closure.

<?php

namespace App\Providers;

use Awobaz\Mutator\Facades\Mutator;
use Illuminate\Support\ServiceProvider;

class MutatorServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //Register your custom accessors/mutators extensions here.
        Mutator::extend('extension_name', function($model, $value, $key){
            //DO STUFF HERE AND RETURN THE VALUE
        });
    }
}

As you can see, the model ($model), the attribute's value ($value) and the attribute's name ($key) are passed to the closure, allowing you to access other attributes of the model to compute and return the desired value.

Additional parameters

You can also define additional parameters for an extension. This give us the flexibility to implement dynamic accessors/mutators.

<?php

namespace App\Providers;

use Awobaz\Mutator\Facades\Mutator;
use Illuminate\Support\ServiceProvider;

class MutatorServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //The following extension is an implementation for str_replace
        Mutator::extend('str_replace', function ($model, $value, $key, $search, $replace) {
            return str_replace($search, $replace, $value);
        });
    }
}

In the above example, the model ($model), the attribute's value ($value), the attribute's name ($key) and two additional parameters are passed to the closure.

To apply this extension, we can use the following syntaxes:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use \Awobaz\Mutator\Mutable;
    
    protected $accessors = [
        'content' => ['str_replace' => ['one', 'two']]
        //OR 
        //'content' => 'str_replace:one,two'
    ];
}

This will replace every occurence of one with two for the content attribute.

Built-in accessors/mutators

lower_case

Convert the attribute to lower case.

upper_case

Convert the attribute to upper case.

capitalize

Convert the first character of attribute to upper case.

capitalize_words

Convert the first character of each word of the attribute to upper case.

trim_whitespace

Strip whitespace from the beginning and end of the attribute.

camel_case

Convert the attribute to camel case.

snake_case

Convert the attribute to snake case.

studly_case

Convert the attribute to studly case.

kebab_case

Convert the attribute to kebab case.

title_case

Convert the attribute to title case.

plural

Convert the attribute to its plural form (only supports the English language).

singular

Convert the attribute to its singular form (only supports the English language).

slug

Convert the attribute to its URL friendly "slug" form.

remove_extra_whitespace

Remove extra whitespaces within the attribute.

preg_replace:pattern,replacement[,limit]

Perform a regular expression search and replace on the attribute.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Unit Tests

In order to run the test suite, install the development dependencies:

$ composer install --dev

Then, run the following command:

$ vendor/bin/phpunit

Authors

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests.

Sponsored by

  • Awobaz - Web/Mobile agency based in Montreal, Canada

License

Eloquent Mutators is licensed under the MIT License.