Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

edmarriner's avatar

Default PHP function parameters break routes

Hi,

I seem to be having an issue with having default values in my controller methods.

The route:

$app->get('/orders/{id}', "App\Http\API\Orders\Orders@get_orders");

The controller:

class Orders extends CoreApi {

    public function get_orders(Request $request, $id = "test"){
    ...
    }
}

However inside the function the parameter $id will always have the default value. After looking through the codebase it seems to be an issue with the array of parameters are are being passed to the function when it is called?

In a case where the URL is: /orders/MY_VALUE the function appears to be called with the following array:

Array (
    [0] => Illuminate\Support\Facades\Request Object ( )
    [1]  => test
    [2] => MY_VALUE
) 

From what I can gather it seems like there are two array which are merged.

The first array is all the parameters from my php function get_orders found by using reflection (Request $request, $id = "test") and a second array with any values that should overwrite the default values where needed.

From what i can tell this is the code in lumen where the array is created which is later passed my function. Line 549 of the Container.php File:

protected function getMethodDependencies($callback, $parameters = [])
    {
        $dependencies = [];

        foreach ($this->getCallReflector($callback)->getParameters() as $key => $parameter)
        {
            $this->addDependencyForCallParameter($parameter, $parameters, $dependencies);
        }

        return array_merge($dependencies, $parameters);
    }

I can see that before the array merge happens $dependencies has a value of:

array(
    [0] => Illuminate\Support\Facades\Request Object ( )
    [1]  => test
)

and $parameters has a value of:

array(
    [0]  => MY_VALUE
)

From that code I don't see how the parameters provided from the URL could ever overwrite the defaulted id parameters value? Array merge just seems to append the real value of id to the end of the array. This means the function which takes two parameters (Request $request, $id = "test") is passed three parameters with the real value not being assigned to any variable in the signature of the method.

I should note that if i take out the $id default parameter value of "test" it works all okay... For example:

public function get_orders(Request $request, $id){} // This works fine
public function get_orders(Request $request, $id = "test") {} // This does not, the value of $id is "test" no matter what

I am confused as to if I have an issue or there is a bug in the lumen codebase?

0 likes
10 replies
davorminchorov's avatar

I am not sure about this, but maybe you are not suppose to have a default value on these methods. Or it can just be a strange bug.

The only thing that comes to mind on how to fix this is: do a manual check inside the method and set the default value.

public function get_orders(Request $request, $id) {
    if(is_null($id))
    {
        $id = "test";
    }
}
edmarriner's avatar

Thanks for the reply.

Yes I could go down that route - however this throw a few PHP issues up:

Warning: get_orders() expects exactly 2 parameters, 1 given in /app/Http/API/Orders/Orders.php on line 19

Notice: Undefined variable: id in /app/Http/API/Orders/Orders.php on line 12

I guess it is possible that the framework was not designed to have functions with default values? Seems little strange if that Is the case however as it will prevent DRY code ( e.g. will have to create two functions - get_orders() and get_order($id) )

davorminchorov's avatar

Yup and I believe it's better (in this case) if you do create 2 methods, 1 for all orders and 1 for a single order.

Go to Lumen's GitHub page and report it as an issue, and see what the community members think.

pmall's avatar

@edmarriner No you are missing the point. You can totally have optional parameters with default values. But you have to put a ? in the url pattern.

Route::get('/orders/{id?}, "App\Http\API\Orders\Orders@get_orders");

UPDATE omg it is lumen. No optional parameters with lumen.

What the point here anyway. Just define a /orders route without an id.

edmarriner's avatar

@pmall

Thanks for your reply :)

Yes it does appear that Lumen is despatching the action with an array of of incorrect parameters...

Instead of merging the array of default values/injected values and the values passed in from the router it is appending them resulting in the default values always being used.

pmall's avatar

@edmarriner Optional url values are just not supported with lumen. Just create a route for /orders and it is done.

edmarriner's avatar

I'm not sure I want optional URL values? I have already have a /orders route. Here is an example of the two routes that would exist in this scenario.

Route::get('/orders', "App\Http\API\Orders\Orders@get_orders");
Route::get('/orders/{id}', "App\Http\API\Orders\Orders@get_orders");

The issue I'm having is not with creating routes that have optional parameters in the string it matches, but instead the PHP function having parameters which have default values.

Coming from other frameworks I have previously tried to keep my actions down in numbers and share logic where possible to keep the code DRY. It just made more sense for me to have two routes pointing to one php action.

Example function:

public function get_orders($id = false){
    
    $query = find()->where()......

    if($id) {
        $query->where("id" => $id);
    }

    return $query->execute();
}

Thanks!

Please or to participate in this conversation.