Understand more magic methods: __callStatic()

Understand more magic methods: __callStatic()

As you know, magic methods are special methods which override PHP's default's action when certain actions are performed on an object. The following method names are considered magical: __construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone(), and __debugInfo(). All magic methods, with the exception of __construct(), __destruct(), and __clone(), must be declared as public, otherwise an E_WARNING is emitted.

__callStatic() is method overloading, triggered when invoking inaccessible methods in a static context.

public static __callStatic(string $name, array $arguments): mixed

The $name argument is the name of the method being called. The $arguments argument is an enumerated array containing the parameters passed to the $name'ed method.

With regard to __callStatic(), you can call a method via double colon, and rename functions to short/pretty name

class Str
{
    /**
     * Shortcut methods
     */
    private static $methods = [
        'chunk' => 'chunk_split',
        'split' => 'str_split',
        'length' => 'strlen',
        'reverse' => 'strrev',
        'countWord' => 'str_word_count',
    ];

    /**
     * Trigger when invoking inaccessible methods in a static context
     */
    public static function __callStatic(string $method, array $parameters)
    {
        if (!array_key_exists($method, self::$methods)) {
            throw new Exception('The ' . $method . ' is not supported.');
        }

        return call_user_func_array(self::$methods[$method], $parameters);
    }

    /**
     * Parse query string to varaibles
     */
    public static function parse(string $str)
    {
        parse_str($str, $output);
        return $output;
    }
}

$data = "Happy New Year!";
$countWord = Str::countWord($data, 1);
var_dump($countWord);

$queryStr = "first=value&arr[]=foo+bar&arr[]=baz";
$output = Str::parse($queryStr);
var_dump($output);
class Arr
{
    /**
     * Shortcut methods
     */
    private static $methods = [
        'search' => 'array_search',
        'chunk' => 'array_chunk',
        'combine' => 'array_combine',
        'count' => 'array_count_values'
    ];

    /**
     * Trigger when invoking inaccessible methods in a static context
     */
    public static function __callStatic(string $method, array $parameters)
    {
        if (!array_key_exists($method, self::$methods)) {
            throw new Exception('The ' . $method . ' is not supported.');
        }

        return call_user_func_array(self::$methods[$method], $parameters);
    }

    /**
     * Count all elements in an array
     */
    public static function length(array $arr)
    {
        return count($arr);
    }
}

$arr = [1,2,3,4,5];
$arr2 = [9,8,7,6,5];

$rs = Arr::combine($arr, $arr2);
var_dump($rs);

$length = Arr::length($arr);
var_dump($length);

Another way uses this overloading method that you can define your own function without static keyword, access using double colon. However, this way restricts you must define methods as protected

class Helper
{
    /**
     * __callStatic
     * @param  string $method
     * @param  mixed $args
     * @return void
     */
    public static function __callStatic($method, $args) {
        $called = get_called_class();
        $class = new $called();
        return $class->$method(...$args);
    }

    protected function generateToken($length)
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }
}

$result = Helper::generateToken(10);
var_dump($result);