master

laravel/framework

Last updated at: 29/12/2023 09:25

ForwardsCalls.php

TLDR

This file is part of the Illuminate\Support\Traits namespace and includes the ForwardsCalls trait. It provides methods for forwarding method calls to another object and throwing exceptions for undefined methods.

Methods

forwardCallTo

This method takes an object, a method name, and an array of parameters. It forwards the method call to the given object and returns the result. If the method is undefined, it throws a BadMethodCallException.

forwardDecoratedCallTo

This method takes an object, a method name, and an array of parameters. It forwards the method call to the given object using the forwardCallTo method. If the result is the same as the original object, it returns $this, otherwise it returns the result.

throwBadMethodCallException

This static method takes a method name and throws a BadMethodCallException with the message "Call to undefined method [class]::method", where [class] is the class name where the method was called and [method] is the method name.

<?php

namespace Illuminate\Support\Traits;

use BadMethodCallException;
use Error;

trait ForwardsCalls
{
    /**
     * Forward a method call to the given object.
     *
     * @param  mixed  $object
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    protected function forwardCallTo($object, $method, $parameters)
    {
        try {
            return $object->{$method}(...$parameters);
        } catch (Error|BadMethodCallException $e) {
            $pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';

            if (! preg_match($pattern, $e->getMessage(), $matches)) {
                throw $e;
            }

            if ($matches['class'] != get_class($object) ||
                $matches['method'] != $method) {
                throw $e;
            }

            static::throwBadMethodCallException($method);
        }
    }

    /**
     * Forward a method call to the given object, returning $this if the forwarded call returned itself.
     *
     * @param  mixed  $object
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    protected function forwardDecoratedCallTo($object, $method, $parameters)
    {
        $result = $this->forwardCallTo($object, $method, $parameters);

        return $result === $object ? $this : $result;
    }

    /**
     * Throw a bad method call exception for the given method.
     *
     * @param  string  $method
     * @return void
     *
     * @throws \BadMethodCallException
     */
    protected static function throwBadMethodCallException($method)
    {
        throw new BadMethodCallException(sprintf(
            'Call to undefined method %s::%s()', static::class, $method
        ));
    }
}