opHasNoName
opHasNoName

Reputation: 20736

Stuck with Laravel Routing

Goal: Use Subdomain as a param and a unlimited amount of GET Params in "normal .. ?param=style" and "/param/style".

Current "web.php"

Route::group(array('domain' => "{bucketIdentifier}.$domainToUse"), function () {   
    Route::get('/{bucketIdentifier?}', 'BucketController@receive');
    Route::post('/{bucketIdentifier?}', 'BucketController@receive');
    Route::put('/{bucketIdentifier?}', 'BucketController@receive');
    Route::delete('/{bucketIdentifier?}', 'BucketController@receive');
    Route::patch('/{bucketIdentifier?}', 'BucketController@receive');
});

If you send a request to xyz.mydomain.com, i get the bucketIdentifier to query the DB. Works as designed.

If you send a GET Request with "?myparam=12&other=42" i can get the Param, works like designed.

But how can i also use "/myparam/12/other/42" for routed. With this setup i will get 404 as response.

Other aporoach (does not work)

Route::group(array('domain' => "{bucketIdentifier}.$domainToUse"), function () {   
    Route::get('/{query}', 'BucketController@receive')->where('query','.+');
    Route::post('/{query}', 'BucketController@receive')->where('query','.+');
    Route::put('/{query}', 'BucketController@receive')->where('query','.+');
    Route::delete('/{query}', 'BucketController@receive')->where('query','.+');
    Route::patch('/{query}', 'BucketController@receive')->where('query','.+');
});

Now i have the bucketIdentifier als "query" param (;

Upvotes: 0

Views: 272

Answers (4)

Quezler
Quezler

Reputation: 2435

To have a route that catches any path (including just /) you can use:

Route::get('/{any}', 'BucketController@receive')->where('any', '.*');
Route::post('/{any}', 'BucketController@receive')->where('any', '.*');
Route::put('/{any}', 'BucketController@receive')->where('any', '.*');
Route::delete('/{any}', 'BucketController@receive')->where('any', '.*');
Route::patch('/{any}', 'BucketController@receive')->where('any', '.*');

Or since you send all methods to the same controller:

(::any registeres the routes for all methods: [get post put patch delete options])

Route::any('/{any}', 'BucketController@receive')->where('any', '.*');

Upvotes: 1

Quezler
Quezler

Reputation: 2435

Here is a service provider you could use:

It merges the path with the query, example:

/foo/bar/hello/world?sen=pai

$request->get('foo') $request->get('hello') $request->get('sen')

Note:

current code will affect all routes, but will not activate in the console.

From the routes in your question i am "assuming" those are the only routes, but if not you should/could add a path whitelist/blacklist to this code.

(should that be the case, i have an idea for that, let me know in the comments if you'd like an example for that to)

class PathServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        if (!$this->app->runningInConsole()) {
            $request = resolve(Request::class);

            foreach ($this->path($request) as $key => $value) {
                $request->query->set($key, $value);
            }
        }
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Yield key values derived from the path,
     * if the last has no value it is skipped.
     *
     * @param Request $request
     * @return Generator
     */
    protected function path(Request $request): Generator {
        $path = explode('/', $request->decodedPath());

        $i = 0;

        while (count($path) - $i >= 2) {
            yield $path[$i++] => $path[$i++];
        }
    }
}

Upvotes: 1

The simplest way to do it is to grab all the parameters that follows a route like this:

// Grab all routes and following routes that start with "infiniteParams"
Route::any('infiniteParams/{all}', function($page){
    // Create an array separating them with "/"
    $params = explode('/', $page);

    // Formatted parameters array
    $params_array = [];

    // Take the first parameter as the key and the second as the value. 
    for($i = 0; $i < count($params); $i+=2) {
        $params_array[$params[$i]] = @$params[$i+1];
    }
    var_dump($params_array);
})->where('all', '.*');

This will convert infiniteParams/myparam/12/other/42 into an array like this

$params_array = [
    "myparam" => 12,
    "other" => 42
]

PD:

I don't know if this respond your question entirely, but at least gives you the idea of how to do it.

Upvotes: 1

sam
sam

Reputation: 5599

You could make use of the fallback routing method instead, which functions as a catch-all. This method is new, so it's undocumented but you can find the Pull Request here.

Route::group(array('domain' => "{bucketIdentifier}.$domainToUse"), function () {   
    Route::fallback('BucketController@receive');
});

The fallback route will match anything that hasn't already been matched in the group.

Upvotes: 1

Related Questions