Welcome Guest, Not a member yet? Register   Sign In
How to setup a single route with optional argument
#1

Hi! 
I'm trying to setup a single route that allows a second optional argument like this:
Code:
$routes->get('user_details/(:num)/(:any)?', 'MyClass::userDetails/$1/$2');

It works with two parameters/args. The problem is that I've got a 404 if I use it with a single argument. 
Additionally, if the second parameter is a string containing a forward slash (/), the routing mechnism considers only the characters before the slash. 
I thought that was the case only with (Confusedegment) and not with (:any). Is this a bug? 
Any suggestions on how do I accomplish what I want, meaning: 
  • two parameters
  • the last parameter is optional (the class method has a default value in its second parameter)
  • the last parameter can contain a forward slash.
Any help is welcome. 
Regards.
Reply
#2

See https://codeigniter4.github.io/CodeIgnit...aceholders for the behavior of (:any).
Reply
#3

> the last parameter is optional (the class method has a default value in its second parameter)

There is no such feature now.

PHP Code:
$routes->get('user_details/(:num)''MyClass::userDetails/$1'); 
Reply
#4

(This post was last modified: 12-08-2023, 11:45 PM by ozornick.)

Create 2 routes: 

user_details/(:num)/(:any)
user_details/(:num)

for one controller MyClass->userDetails($a, $b=null) ?

EDIT: Its work fine


PHP Code:
// Routes
$routes->get('/products/(:num)/(:any)''Product::oneSegment/$1/$2');
$routes->get('/products/(:num)''Product::oneSegment/$1');

// Controller
class Product extends BaseController
{
    /**
    * @see http://localhost:8080/products/111
    * @see http://localhost:8080/products/111/adaw/adawd/awdawdeg/
    */
    public function oneSegment($segment1, ...$segments)
    {
        return response()->setBody('Product::oneSegment with ' $segment1 ' and ' implode(', '$segments) . ' loaded');
    }
}

// Output
Product::oneSegment with 111 and loaded
Product
::oneSegment with 111 and awdawadawd loaded 
Reply
#5

(This post was last modified: 12-13-2023, 03:39 PM by bgeneto.)

(12-08-2023, 05:25 PM)kenjis Wrote: > the last parameter is optional (the class method has a default value in its second parameter)

There is no such feature now.

PHP Code:
$routes->get('user_details/(:num)''MyClass::userDetails/$1'); 

That's unfortunate. We frequently run across routes that require this last optinal argument. As far as I can recall, this was a feature of the CI v3.

Thanks for your detailed reply! It works indeed... 
But I insist that, according to the docs (at least to my understanding of the documentation), the (:any) placeholder should "match all characters from that point to the end of the URI. This may include multiple URI segments."
And this is not the case, as you can see in this minimal example: 

PHP Code:
$routes->get('/anyplaceholder/(:num)/(:any)''Test::placeholderAny/$1/$2');
$routes->get('/anyplaceholder/(:num)''Test::placeholderAny/$1');

/**
* @see http://localhost:8080/anyplaceholder/1
* @see http://localhost:8080/anyplaceholder/1/path/to/some/folder
*/
public function anyplaceholder($arg1$arg2 null)
{
    return response()->setBody('arg1=' $arg1 ' and arg2=' $arg2);

In the second get request (see method comments) $arg2 will not store the full path passed, it will only contains the string "path".
The same holds true for regex placeholders, from the docs: "With regular expressions, you can also catch a segment containing a forward slash (/), which would usually represent the delimiter between multiple segments."

PHP Code:
/**
* @see http://localhost:8080/regexplaceholder/path/to/some/folder
*/
public function regexPlaceholder($arg1)
{
    return response()->setBody('arg1=' $arg1);

PHP Code:
$routes->get('/regexplaceholder/(.+)''Test::regexPlaceholder/$1'); 

But also in this case only the value "path" will be outputed. At least from me (using CI v4.4.3).
Is this supposed to be the right behaviour? 
Best regards!
Reply
#6

(12-13-2023, 03:15 PM)bgeneto Wrote: That's unfortunate. We frequently run across routes that require this last optinal argument. As far as I can recall, this was a feature of the CI v3.

If I remember correctly, there is no such feature in v3.
I believe all the features in v3 routing are also in v4.
Reply
#7

(This post was last modified: 12-13-2023, 04:46 PM by kenjis.)

The relationship between multiple segments and parameters with (:any) is odd to me, but it is a specification.
See https://codeigniter4.github.io/CodeIgnit...ior-of-any

If you want to catch all segments, use the syntax ...$params

If I could fix it, I would, but changing the behavior would be a breaking change,
so it is not easy to change.
Reply
#8

Why is the two route option not suitable for you? It's 100% working. You need to determine the required parameter based on the request
Reply
#9

(12-13-2023, 10:51 PM)ozornick Wrote: Why is the two route option not suitable for you? It's 100% working. You need to determine the required parameter based on the request

It's not that the solutions presented don't work for me. My problem is solved, thanks to you! My question is that the implementation does not comply with the documentation. From the docs


Quote:With regular expressions, you can also catch a segment containing a forward slash (/), which would usually represent the delimiter between multiple segments.

For example, if a user accesses a password protected area of your web application and you wish to be able to redirect them back to the same page after they log in, you may find this example useful:


PHP Code:
<?php

$routes
->get('login/(.+)''Auth::login/$1'); 

But that's not the case, unless you rely on variable-length argument lists, i.e., multiple arguments. 
Maybe we need to add this info/tip to the docs (or your example using "..."), otherwise that '$1' could lead the user to use only one method argument thinking one could catch all segments containing a forward slash in this single variable. 
It's just a suggestion since I find it very hard to figure it out that we had to use variable-length arguments.
Reply
#10

Out of curiosity, why don't you send a pull request to update the docs?
Reply




Theme © iAndrew 2016 - Forum software by © MyBB