redbastie / larawire

Laravel + Livewire + Bootstrap auth UI & CRUD scaffolding.
21 stars 4 forks source link

Idea: Routing improvement #4

Closed marispro closed 3 years ago

marispro commented 3 years ago

Hi there! I was inspired by migrations and routing, that is genius!

Problem: I have Livewire components which are used in multiple routes.

Idea: Add possibility to set list of routes in component as array.

class SomeLivewireComponent extends Component
{
    public array $routes = [
        'properties/create' => [
            'name' => 'properties.create',
            'middleware' => 'auth'
        ],
        'properties/edit/{property:id}' => [
            'name' => 'properties.edit',
            'middleware' => 'auth'
        ]
    ];
    ...

Quick workaround web.php:

Route::middleware('web')->group(function () {
    $filesystem = new Filesystem;
    $dir = app_path('Http/Livewire');
    if($filesystem->exists($dir)){
        foreach($filesystem->allFiles($dir) as $file){
            $namespace = 'App\\Http\\Livewire\\' . str_replace(['/', '.php'], ['\\', ''], $file->getRelativePathname());
            $class = app($namespace);

            if(property_exists($class, 'routes')){
                foreach($class->routes as $route => $data){
                    $route = Route::get($route, $namespace);

                    if(!empty($data['middleware'])){
                        $route->middleware($data['middleware']);
                    }

                    if(!empty($data['name'])){
                        $route->name($data['name']);
                    }
                }
            }
            elseif(property_exists($class, 'routeUri')){

                $route = Route::get($class->routeUri, $namespace);

                if(property_exists($class, 'routeDomain')){
                    $route->domain($class->routeDomain);
                }

                if(property_exists($class, 'routeMiddleware')){
                    $route->middleware($class->routeMiddleware);
                }

                if(property_exists($class, 'routeName')){
                    $route->name($class->routeName);
                }
            }
        }
    }
});
redbastie commented 3 years ago

Can you give an example of why you're using the same component in multiple routes?

From what you posted, it looks like you want to use the same component for both CREATE and UPDATE operations, is that correct?

If that is the case, why not just use 1 route with a CONDITIONAL route parameter, which is detected in the component?

marispro commented 3 years ago

@redbastie exactly, for create and update. Also I want to keep named routes with that.

redbastie commented 3 years ago

@redbastie exactly, for create and update. Also I want to keep named routes with that.

Bu why? You can use 1 route with a conditional parameter and detect it inside the component.

For example,

class CreateOrUpdateProperty extends Component
{
    public $routeUri = '/properties/cou/{property?}';
    public $routeName = 'properties.cou';
    public $routeMiddleware = 'auth';
    public $property;

    public function mount(Property $property = null)
    {
        $this->property = $property;
    }

    // if $this->property is null, then it is create, otherwise update
}

Then you can just pass the property ID to the route for update, or no parameter at all for create.

marispro commented 3 years ago

Ok thanks! Will check how good named routes can handle with this.

redbastie commented 3 years ago

OK great, let me know if you have any more issues with this.

redbastie commented 3 years ago

I'm going to push some changes today that uses the same component for update & create.

marispro commented 3 years ago

@redbastie Yes this works, only route name "properties.cou" becomes less beautiful, but it is still good solution.

redbastie commented 3 years ago

You could use save instead of cou :)

Once the changes are pushed to the make:crud command today, you'll be able to see a clear example.

marispro commented 3 years ago

@redbastie I just remembered that Laravel 8 have new feature called "upsert". That name might be something meaningful. https://laravel.com/docs/8.x/eloquent#upserts

redbastie commented 3 years ago

Upsert won't work because it relies on using the same data as the first parameter.

I just pushed version 1.7.0. Please run composer update, and you can see the make:crud command now uses a shared Save component for create & update :)

I think its much nicer this way. Thanks again for your feedback.