PHP:检查反射类是否有构造函数?

PHP: Checking if a reflection class has a constructor?

提问人:async life 提问时间:9/7/2020 最后编辑:async life 更新时间:9/7/2020 访问量:466

问:

我为我的应用程序编写了一个依赖项提供程序(基本上是 IOC 容器)。我添加了自动布线功能,尽管当它尝试自动布线的类没有构造函数时,它遇到了障碍。

Uncaught Error: Call to a member function getParameters() on null in C:\xampp\htdocs\src\app\Providers\DependencyProvider.php:68

我相当确定它正在尝试在没有构造函数的类上解析方法中的构造函数参数,这就是问题发生的原因。resolveArguments

因此,只有当类需要解析其参数(自动连接)时才应调用,并且通常只有当它具有构造函数时才应调用。resolveArguments

上面的错误消息正在发生,因为返回 null。我在问检查反射类是否具有需要自动布线的构造函数的最佳做法是什么?getConstructor

全班:

<?php

namespace App\Providers;

class DependencyProvider {
    private static $objects = [];

    /**
     * Register an instantiated object to the container.
     *
     * @param object $object
     */
    public static function register(object $object) : void {
        self::$objects[get_class($object)] = $object;
    }

    /**
     * Fetch a cached object from the container.
     *
     * @param string $objectName
     * @return object
     */
    public static function fetch(string $objectName) : object {
        if (array_key_exists($objectName, self::$objects)) {
            return self::$objects[$objectName];
        }

        $object = self::make($objectName);

        self::$objects[$objectName] = $object;

        return $object;
    }

    /**
     * Creates an object from its name and auto-wires constructor arguments.
     *
     * @param string $objectName
     * @return object
     * @throws \ReflectionException
     */
    private static function make(string $objectName) : object {
        $reflection = new \ReflectionClass($objectName);

        if (!$reflection->isInstantiable()) {
            throw new RuntimeException($reflection->getName() . ' can\'t be instantiated.');
        }

        $arguments = self::resolveArguments($reflection);

        if (count($arguments) < 1) {
            return $reflection->newInstance();
        }
        else {
            return $reflection->newInstanceArgs($arguments);
        }
    }

    /**
     * Creates an array of arguments from a reflection class.
     * Uses default value if there is one, auto-wires the object if not.
     *
     * @param $reflection
     * @return array
     */
    private static function resolveArguments($reflection) : array {
        $constructor = $reflection->getConstructor();
        $parameters = $constructor->getParameters();

        if (!$parameters) {
            return $reflection->newInstance();
        }

        $arguments = [];

        foreach ($parameters as $parameter) {
            if ($parameter->isDefaultValueAvailable()) {
                $arguments[] = $parameter->getDefaultValue();
                continue;
            }

            if ($parameter->getClass() == null) {
                exit($parameter->name . ' on ' . $reflection->getName() . ' needs a default value');
            }

            $arguments[] = self::fetch($parameter->getClass()->getName());
        }

        return $arguments;
    }
}
PHP的

评论

0赞 Fels 9/7/2020
我认为没有比 $reflection->getConstructor() 更好的方法了 !== null

答:

1赞 AndreiXwe 9/7/2020 #1

编辑(误读问题):

只需在调用该方法之前检查构造函数是否确实存在:

if (! is_null($reflection->getConstructor())) { ... }