Skip to content
4 changes: 4 additions & 0 deletions src/ActionServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
namespace Lorisleiva\Actions;

use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Lorisleiva\Actions\Console\MakeActionCommand;
use Lorisleiva\Actions\DesignPatterns\CommandDesignPattern;
use Lorisleiva\Actions\DesignPatterns\ControllerDesignPattern;
use Lorisleiva\Actions\DesignPatterns\ListenerDesignPattern;
use Lorisleiva\Actions\Macros\ActionRouteMacros;

class ActionServiceProvider extends ServiceProvider
{
Expand Down Expand Up @@ -43,6 +45,8 @@ public function boot(): void
MakeActionCommand::class,
]);
}

Route::mixin(new ActionRouteMacros);
}

protected function extendActions(): void
Expand Down
23 changes: 23 additions & 0 deletions src/Macros/ActionRouteMacros.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Lorisleiva\Actions\Macros;

use Illuminate\Routing\PendingResourceRegistration;
use Illuminate\Routing\Router;
use Lorisleiva\Actions\Routing\ActionResourceRegistrar;

class ActionRouteMacros
{
public function resourceActions(): callable
{
return function (string $name, string $namespace = 'App\Actions', array $options = []): PendingResourceRegistration {
/** @var Router $router */
$router = $this;
$registrar = new ActionResourceRegistrar($router);

return new PendingResourceRegistration(
$registrar, $name, $namespace, $options
);
};
}
}
62 changes: 62 additions & 0 deletions src/Routing/ActionResourceRegistrar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Lorisleiva\Actions\Routing;

use Closure;
use Illuminate\Routing\ResourceRegistrar;
use Illuminate\Support\Str;

class ActionResourceRegistrar extends ResourceRegistrar
{
/**
* @var array<string, Closure>
*/
private static array $actionResolver = [];

protected function getResourceAction($resource, $controller, $method, $options): array
{
$action = parent::getResourceAction($resource, $controller, $method, $options);

$resource = Str::camel(str_replace('.', '_', $resource));
$actionName = Str::singular($resource);

if (! empty(static::$actionResolver[$method])) {
$actionClass = call_user_func(static::$actionResolver[$method], $resource);
}

if (empty($actionClass)) {
$actionClass = match ($method) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can $method be a value that isn't listed in the match values?

Copy link
Author

@CWAscend CWAscend Feb 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed this to Route::resourceActions as requested :)

For this comment, I've replicated what is in the parent class:

image

So my answer your question is no - there's also no method that allows change the $resourceDefaults array, unless the developer extends this class and forces a change that way.

In this case, if they need the Action class names to be resolved in a different way to the default functionality provided, then can customise it by leveraging this in their RouteServiceProvider:

ActionResourceRegistrar::resolveActionClassNameUsing(
    function ($resource, $method): ?string {
        // Add their custom functionality here
    }
);

So lets say they extended the ResourceRegistrar and appended a 'restore' to the resource defaults:

ActionResourceRegistrar::resolveActionClassNameUsing(
    function ($resource, $method): ?string {
        return match ($method) {
            'restore' => 'Restore'.ucfirst($resource),
            default => null        
        }
    }
);

'index' => 'Get'.ucfirst($resource),
'create' => 'ShowCreate'.ucfirst($actionName),
'show' => 'Show'.ucfirst($actionName),
'edit' => 'ShowEdit'.ucfirst($actionName),
'store' => 'Create'.ucfirst($actionName),
'update' => 'Update'.ucfirst($actionName),
'destroy' => 'Delete'.ucfirst($actionName),
};
}

// Replaces the Controller@action string with the ActionClass string
$action['uses'] = str_replace('\\\\', '\\', "{$controller}\\{$actionClass}");

return $action;
}

/**
* Use this in your RouteServiceProvider to override the default action classes
*
* @example
*
* ActionResourceRegistrar::resolveResourceAction('index', function (string $resource) {
* return 'GetAll'.ucfirst($resource); // e.g. GetAllUsers
* });
*
* @param string $method
* @param Closure $resolver
* @return void
*/
public static function resolveResourceAction(string $method, Closure $resolver): void
{
static::$actionResolver[$method] = $resolver;
}
}
Loading