Skip to content

Bug: Missing argument in route when using url_to or route_to with regex routes #9250

Open
@bgeneto

Description

@bgeneto

PHP Version

8.3

CodeIgniter4 Version

CodeIgniter 4.5.5

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Debian 12

Which server did you use?

fpm-fcgi

Database

N/A

What happened?

The following route definition works fine as long as you don't use url_to or route_to to refer to it:

$routes->get('/test(/(:any))?', 'Test::direct/$1', ['as' => 'test']);

Linking as below works:

<a href="/test">No parameter</a>
<a href="/test/param1">1 parameter</a>
<a href="/test/param1/param2">2 parameters</a>

But using both url_to or route_to fails:

<a href="<?= url_to('test') ?>">No parameter</a>
<a href="<?= url_to('test', 'param1') ?>">1 parameter</a>
<a href="<?= url_to('test', 'param1', 'param2') ?>">2 parameters</a>

Steps to Reproduce

  1. Add the new routes in Routes.php:
$routes->get('/test(/(:any))?', 'Test::direct/$1', ['as' => 'test']);
$routes->get('/test_urlto(/(:any))?', 'Test::urlto/$1', ['as' => 'urlto']);
$routes->get('/test_routeto(/(:any))?', 'Test::routeto/$1', ['as' => 'routeto']);
  1. Create the Test controller:
<?php

namespace App\Controllers;

class Test extends BaseController
{
    public function direct(...$params): string
    {
        return view('test', ['params' => $params]);
    }

    public function urlto(...$params): string
    {
        return view('test_urlto', ['params' => $params]);
    }

    public function routeto(...$params): string
    {
        return view('test_routeto', ['params' => $params]);
    }
}
  1. Create the respective views:

A) direct view

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Test</title>
</head>
<body>
	<h1>Testing CI4 Routing with Parameters</h1>

	<h2>Test using string directly</h2>
	<ul>
		<li>
			<a href="/test">No parameter</a>
		</li>
		<li>
			<a href="/test/param1">1 parameter</a>
		</li>
		<li>
			<a href="/test/param1/param2">2 parameters</a>
		</li>
		<li>
			<a href="/test/param1/param2/param3">3 parameters</a>
		</li>
	</ul>
	<h3>Passed Parameters</h3>
	<ul>
		<?php foreach ($params as $param) : ?>
			<li><?= $param ?></li>
		<?php endforeach; ?>
</body>
</html>

B) view using url_to

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<title>Test</title>
</head>

<body>
	<h1>Testing CI4 Routing with Parameters</h1>
	<h2>Test using <code>url_to</code></h2>
	<ul>
		<li>
			<a href="<?= url_to('urlto') ?>">No parameter</a>
		</li>
		<li>
			<a href="<?= url_to('urlto', 'param1') ?>">1 parameter</a>
		</li>
		<li>
			<a href="<?= url_to('urlto', 'param1', 'param2') ?>">2 parameters</a>
		</li>
		<li>
			<a href="<?= url_to('urlto', 'param1', 'param2', 'param3') ?>">3 parameters</a>
		</li>
	</ul>

	<h3>Passed Parameters</h3>
	<ul>
		<?php foreach ($params as $param) : ?>
			<li><?= $param ?></li>
		<?php endforeach; ?>
</body>
</html>
  1. Access those views at: /test and /test_urlto

Expected Output

No InvalidArgumentException, Missing argument for "(/(:any)" in route "test_urlto(/(:any))?" while using both url_to and route_to .

Anything else?

  • One can try it with public bool $multipleSegmentsOneParam = true; or public bool $multipleSegmentsOneParam = false; in Routing.php. The error is the same in both situations (just the parameters are treated differently, as expected).

  • One can also use a regex like '(/(.+))?' instead of (/(:any))? . The error remains.

Activity

added
bugVerified issues on the current code behavior or pull requests that will fix them
on Nov 2, 2024
changed the title [-]Bug: Missing argument in route[/-] [+]Bug: Missing argument in route when using `url_to` or `route_to` with regex routes[/+] on Nov 2, 2024
michalsn

michalsn commented on Nov 4, 2024

@michalsn
Member

Using the (:any) placeholder in the route does not mean that the parameter value is optional. You must always put a value.

You can use: url_to('urlto', ''), although in general I don't think it will behave as you expect - the route will not be found.

In any case, this is not a bug.

removed
bugVerified issues on the current code behavior or pull requests that will fix them
on Nov 4, 2024
neznaika0

neznaika0 commented on Nov 4, 2024

@neznaika0
Contributor

I've been trying to use regex in routes for a long time. It failed.
Try to create several routes to get rid of the "?".

$routes->get('/test/(:any)', 'Test::direct/$1', ['as' => 'test_ext']);
$routes->get('/test', 'Test::direct/$1', ['as' => 'test']);

To work, you need to specify a string for :any and not an array
url_to('urlto', 'param1/param2/param3') not url_to('urlto', 'param1', 'param2', 'param3')

bgeneto

bgeneto commented on Nov 4, 2024

@bgeneto
Author

Using the (:any) placeholder in the route does not mean that the parameter value is optional. You must always put a value.

You can use: url_to('urlto', ''), although in general I don't think it will behave as you expect - the route will not be found.

In any case, this is not a bug.

I couldn't disagree more... Because I'm using regular expressions (note the ? char) with (:any). And it also fails for '(/(.+))?' as mentioned in this carefully written bug report.

And, by running the examples, one can see that routing mechanism is working flawlessly with or without arguments. Problem arises when using url_to. For me this is, at least, a framework inconsistency or missing feature (if not a bug). 😥

bgeneto

bgeneto commented on Nov 4, 2024

@bgeneto
Author

I've been trying to use regex in routes for a long time. It failed. Try to create several routes to get rid of the "?".

$routes->get('/test/(:any)', 'Test::direct/$1', ['as' => 'test_ext']);
$routes->get('/test', 'Test::direct/$1', ['as' => 'test']);

To work, you need to specify a string for :any and not an array url_to('urlto', 'param1/param2/param3') not url_to('urlto', 'param1', 'param2', 'param3')

Yeah! Unfortunately every time this subject comes up it is treated as a feature, read the docs etc....

So I kindly suggest to remove the partial regex support from routes (a great loss since routing works fine with regex, only additional framework related functions like url_to or route_to do not support it).

We could also explicitly says in the docs not to use the special '?' char in routes because of missing support.

As I carefully showed in this bug report examples, regex with '?' works with or without arguments. Problem is framework support from related helper functions.

crustamet

crustamet commented on Jan 10, 2025

@crustamet
Contributor

Well i have tested out your wanting functionality i manage to make it work with the following:

your routes are wrong in the first place and how you use the url_to() is wrong also.

Try it like this in routes file

$routes->get('/test/(:any)', 'Test::direct/$1', ['as' => 'test_ext']);
$routes->get('/test', 'Test::direct', ['as' => 'test']);

And this for the controller

use CodeIgniter\Controller;

class Test extends Controller
{
	public function direct(...$params): string
	{
		echo url_to('test_ext', ...$params);
		echo '<br />';
		echo url_to('test');
		echo '<br />';
		print_r($params);die();
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @michalsn@bgeneto@neznaika0@crustamet

        Issue actions

          Bug: Missing argument in route when using `url_to` or `route_to` with regex routes · Issue #9250 · codeigniter4/CodeIgniter4