PHP’s __call magic method and named arguments

Whilst working on a little library recently, I discovered some interesting behavior with PHP’s __call magic method. Specifically around using named arguments in methods that are caught by the __call method.

Given the following class:

<?php
class EmptyClass
{
    public function __call(string $name, array $args)
    {
        var_dump($args); die;
    }
}

Calling a non-existing method without named parameters would result in the arguments being given to __call as an indexed array:

$myClass = new EmptyClass;

$myClass->method(
    'Argument A',
    'Argument B',
);

// This var dumps: [0 => 'Argument A', 1 => 'Argument B']

However, passing those values with named parameters, will cause them to be given to __call as an associative array:

$myClass = new EmptyClass;

$myClass->method(
    firstArg: 'Argument A',
    secondArg: 'Argument B',
);

// This var dumps: ['firstArg' => 'Argument A', 'secondArg' => 'Argument B']

I’m not sure if this is helpful to anyone but I thought it was quite interesting so thought I’d share. 🙂

What is the PHP __call magic method?

Consider this PHP class:

<?php
class FooClass
{
    public function bar(): string
    {
        return 'Bar';
    }
}

We could call the bar method as follows:

<?php
$fooClass = new FooClass;

$fooClass->bar();

// returns the string 'Bar'

However, in PHP, we have the ability to call methods that don’t actually exist on a class. They can instead be caught by a “magic method” named __call, which you can define on your class.

<?php
class BazClass
{
    public function __call(string $name, array $args)
    {
        // $name will be given the value of the method
        // that you are trying to call

        // $args will be given all of the values that
        // you have passed into the method you are
        // trying to call
    }
}

So if you instantiated the BazClass above and called a non-existing method on it with some arguments, you would see the following behavior:

<?php
$bazClass = new BazClass;
$bazClass->lolcats('are' 'awesome');

In this example, BazClass‘s __call method would catch this method call, as there is no method on it named lolcats.

The $name value in __call would then be set to the string “lolcats”, and the $args value would be set to the array [0 => 'are', 1 => 'awesome'].

You may not end up using the __call method much in your day to day work, but it is used by frameworks that you possibly will be using, such as Laravel.