Closed mbryne closed 3 years ago
Hi there, 👋
Yes you can absolutely extends Laravel Actions by creating your own DesignPattern
and Decorator
.
When creating a DesignPattern
you'd need to implement recognizeFrame
so Laravel Actions can tell if this decorator should be used when you're action is being resolved from the container.
Then you can add it to existing design patterns like this.
$currentDesignPatterns = Actions::getDesignPatterns();
Actions::setDesignPatterns(array_merge($currentDesignPatterns, [new MyDesignPattern()]));
// I need to add a `addDesignPattern` method tbf.
However, I'm not sure how you'll be using that AsLog
trait. If it does not require to be identified when resolved from the container, you can add static methods similar to how the AsJob
trait works.
I hope this helps.
lorisleiva thank you for your speedy reply, I will look into extending those classes. I'm mindful of your time but do you mind if I ask an additional question...
My use case will be to add a semi-transparent Activity Logging layer to my actions, rather than having to call $this->log()
within my handle
method all the time.
So my thought process is:
AsLog
Action trait that retrieves default log message from transation files < doneLoggingDesignPattern
and LoggingDecorator
< no worriesmake
or run
to retrieve it from the service container < no worriesLoggingDecorator
which will call the handle
method as outlined belowhandle
method will call LoggingDecorator.handle
which fires off an Activity Log message in a manner of my choosing and then call MyCoolAction.handle
method after that?...
public function handle()
{
if ($this->hasMethod('asLog')) {
$this->resolveAndCallMethod('asLog', ['command' => $this]);
} else {
$this->resolveAndCallMethod('asDefaultLog', ['command' => $this]);
}
if ($this->hasMethod('handle')) {
return $this->resolveAndCallMethod('handle', ['command' => $this]);
}
}
...
^ It's points 4 and 5 that I am keen to clarify with you if you don't mind, just to make sure I understand the reasoning behind the approach you have taken before I attempt to butcher it :)
Many thanks again
So my only worry with this approach is that your LoggingDesignPattern
will be in "competition" with other design patterns. Meaning this will only work if the action itself is not recognised as a ControllerDesignPattern
, ListenerDesignPattern
, etc.
It seems to me that this might be a slight overkill for what you're trying to achieve which, if I understand correctly, is a listener on the handle
method that logs things before the handle method is being called.
The easiest way to achieve this would probably be to create a AsLog
trait that simply contains a logAndHandle
method which you can then use in your asJob
, asController
, etc. methods instead of using handle
. Something like that:
trait AsLog
{
public function logAndHandle(...$arguments)
{
// Log here...
return $this->handle(...$arguments);
}
public static function logAndRun(...$arguments)
{
return static::make()->logAndHandle(...$arguments);
}
}
Use it in your action like so:
class MyAction
{
use AsAction;
use AsLog;
public function handle($foo)
{
// Your action logic here...
}
public function asController(ActionRequest $request)
{
// Don't forget to use logAndHandle in your "asPattern" methods if you need to.
return $this->logAndHandle($request->get('foo'));
}
}
And that's it. Now your action will be automatically logged when running as a controller. When running your action as an object, you can do:
// With logging.
MyAction::logAndRun('bar');
// Without logging.
MyAction::run('bar');
Or if you prefer dependency injection.
class MyOtherAction
{
use AsAction;
protected MyAction $myAction;
public function __construct(MyAction $myAction)
{
$this->myAction = $myAction;
}
public function handle()
{
// With logging.
$this->myAction->logAndHandle('bar');
// Without logging.
$this->myAction->handle('bar');
}
}
I hope this helps. 🙂
Yes @lorisleiva thank you very much!
I'll close the issue, cheers
Hello and thank you very much for your efforts on this package. I'm interested in the approach you have taken using the Action decorators.
What I am hoping to achieve is to extend your ActionManager and add some an additional design pattern to automatically add an activity log for certain actions by adding a
AsLog
trait.Am I correct in assuming that because of the decorator pattern you have used here, it should be possible to add a LoggingDecorator or similar that will fire off my own Log handler? That seems to be the case when I look at say:
Lorisleiva\Actions\Decorators\CommandDecorator
So theoretically I should be able to put something together like:
MyActions\Decorators\LoggingDecorator
Would you say my assumptions are correct and would you be able to provide a small amount of initial direction on extending the ActionManager to allow my custom Decorators and DesignPatterns?
Many thanks in advance for any assistance you can offer,