Controllers

For package controllers changing we can use:

  1. Normal class extending - good for undefined methods - bad for defined methods
class SecondController extends FirstController {   
    public function new_method() {
        \\...
    }
    
    //NEED SAME DECLARATION AS IN FirstController 
    //not practical for controllers which will change their declaration - add or remove arguments
    public function old_method(Infopage $info) {
        $extendMe = 'extended';
        View::composer('welcome', function($view) use( $extendMe ){
            $view->with([
                'extendMe' => $extendMe,
            ]);
        });
        $args = func_get_args();

        return parent::old_method( ...$args );
    }
}
$this->app->bind(
    FirstController::class,
    SecondController::class
);
  1. Decorating - good for extending defined methods as well
 class TestControllerDecorator {
    private $service;

    public function __construct($service) {
        $this->service = $service;
    }

    public function new_method() {
        \\...
    }
    
    //DO NOT NEED SAME DECLARATION
    public function old_method() {
        $extendMe = 'extended';
        View::composer('welcome', function($view) use( $extendMe ){
            $view->with([
                'extendMe' => $extendMe,
            ]);
        });
        $args = func_get_args();
        return $this->service->old_method( ...$args );
    }

    public function __call($funcname, $args) {
        return $this->service->$funcname( ...$args );
    }
}
$this->app->extend(TestController::class, function ($service, $app) {
    return new TestControllerDecorator($service);
});

Models

For package models changing we can use:

  1. Normal class extending - not very practical, because should replace every use of old class with the new class
    Note: cannot be bind like controllers, because binding will affect only dependency injected classes, not the ones
    used in the workflow.

  2. Use MacroableModel - most package models should use MacroableModel trait, which give dynamic extending
    functionality though macros and mixins.

class TestModel {
    \\...
    use MacroableModel;
    \\...
}
TestModel::macro('new_method', function($arg1) {
    \\...
    $this->example_for_$this_use($arg1);
    \\...
}
class TestModelMixin {
    public function new_method() {
        return function($arg1) {
            \\...
            $this->example_for_$this_use($arg1);
            \\...
        };
    }
}
//second argument is to not replace existing `macros`
TestModel::mixin( new TestModelMixin, false );
  1. Base class class extending - extend directly the base class that model extends and change whatever need.