mehradsadeghi/laravel-decorator

This package is abandoned and no longer maintained. No replacement package was suggested.

Decorate and extend functionalities of methods without causing any break to the existing codebase.

Maintainers

Package info

github.com/mehradsadeghi/laravel-decorator

pkg:composer/mehradsadeghi/laravel-decorator

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.1.0 2020-07-23 04:50 UTC

This package is auto-updated.

Last update: 2021-05-23 06:44:20 UTC


README

Decorate and extend functionalities of methods without causing any break to the existing codebase.

Installation

$ composer require mehradsadeghi/laravel-decorator

Usage

Assuming you have a class named Person with a method named getFullName which its inputs and output should get decorated:

class Person {

    public function makeFullName($firstName, $lastName)
    {
        return "$firstName $lastName";
    }
}

$person = new Person();
$person->makeFullName('mehrad', 'sadeghi'); // mehrad sadeghi

When using decorator without setting any decoration, The default behavior of makeFullName method will remain the same:

decorate([Person::class, 'makeFullName'], ['mehrad', 'sadeghi']); // mehrad sadeghi

In order to decorate makeFullName method:

$decorator = function ($callable) {
    return function (...$params) use ($callable) {
    
        // decorating the inputs
        foreach($params as $key => $param) {
            $params[$key] = trim($param);
        }

        // real call to makeFullName method
        $output = app()->call($callable, $params);

        // decorating the output
        $output = strtoupper($output);

        return $output;
    };
};

decorator([Person::class, 'makeFullName'])->set($decorator);

Note that the decorator should be a valid PHP callable. So it can be a Closure or an array callable, Which can be defined as follows:

class PersonDecorator {

    public function decorateFullName($callable)
    {
        return function (...$params) use ($callable) {
        
            // decorating the inputs
            foreach($params as $key => $param) {
                $params[$key] = trim($param);
            }

            // real call to makeFullName method
            $output = app()->call($callable, $params);

            // decorating the output
            $output = strtoupper($output);

            return $output;
        };
    }
}

decorator([Person::class, 'makeFullName'])->set([PersonDecorator::class, 'decorateFullName']);

Now we've assigned our decorator to the makeFullName method. Calling makeFullName with decorate helper function will apply its decoration:

decorate([Person::class, 'makeFullName'], ['  mehrad ', '     sadeghi ']); // MEHRAD SADEGHI

Multiple Decorators

You can easily set multiple decorators on a method:

decorator([Person::class, 'makeFullName'])
        ->set(function($callable) {
            // decoration
        })
        ->set(function($callable) {
            // decoration
        });

or

decorator([Person::class, 'makeFullName'])
    ->set([PersonDecorator::class, 'secondDecorator'])
    ->set([PersonDecorator::class, 'firstDecorator']);

Forgetting (Removing) Decorator(s)

You can easily remove one or all decorators assigned to a callable. From example above, Assume we have two decorators:

class PersonDecorator {

    public function decorateInput($callable)
    {
        return function (...$params) use ($callable) {

            // decorating the inputs
            foreach($params as $key => $param) {
                $params[$key] = trim($param);
            }

            // real call to makeFullName method
            $output = app()->call($callable, $params);

            return $output;
        };
    }

    public function decorateOutput($callable)
    {
        return function (...$params) use ($callable) {

            // real call to makeFullName method
            $output = app()->call($callable, $params);

            // decorating the output
            $output = strtoupper($output);

            return $output;
        };
    }
}

decorator([Person::class, 'makeFullName'])
    ->set([PersonDecorator::class, 'decorateInput'])
    ->set([PersonDecorator::class, 'decorateOutput']);

The output of calling decorate would be:

decorate([Person::class, 'makeFullName'], ['  mehrad ', '     sadeghi ']); // MEHRAD SADEGHI

Then for removing decorateOutput:

decorator([Person::class, 'makeFullName'])
    ->forget([PersonDecorator::class, 'decorateOutput']);

And the output of calling decorate would be:

decorate([Person::class, 'makeFullName'], ['  mehrad ', '     sadeghi ']); // mehrad sadeghi

Note that for removing all decorations of a callable, just leave the forget parameter empty:

decorator([Person::class, 'makeFullName'])->forget();