Почему создание класса динамических объектов php не работает?

Я пытаюсь создать класс (работающий как фабричный класс) в моем приложении Zend Expressive следующим образом:

declare(strict_types=1);

namespace App\Install\Factory;

use App\Install\Model as Models;
use App\Install\Abstracts\AttributeInterface;

class AttributeEntityFactory{

    public static function create($type1 ='Attribute') : AttributeInterface
    {
        $resolvedClass = "Models\\$type1";
        $resolvedClass1 = 'Models\\'.$type1;
        //return new $resolvedClass();
        //return new $resolvedClass1();
        return new Models\Attribute();
    }
}

Приведенный выше код отлично работает для меня. Однако, если попытаться использовать любой из двух других операторов возврата, он показывает

Класс 'Models\Attribute' не найден

Как я могу достичь динамической реализации?

Код класса атрибута выглядит следующим образом:

namespace App\Install\Model;
use App\Install\Abstracts\AttributeInterface;

class Attribute implements AttributeInterface
{
    protected $attribute;

    public function setAttribute($attribute)
    {
        $this->attribute = $attribute;
    }

    public function getAttribute()
    {
        return $this->attribute;   
    }  
}

Моя версия PHP:

PHP 7.2.13 (cli) (построено: 14 декабря 2018 04:20:16) ( NTS)

1 ответ

Лично я бы избегал такой заводской реализации по нескольким причинам:

  1. Это связано с магией.
  2. Менее предсказуемый код.
  3. Труднее читать как для людей, так и для IDE (например, PHPStorm не нашел бы использования Attribute класс в таком коде, когда нужно его найти)
  4. Сложнее анализировать с помощью статических анализаторов

Вместо этого я бы переписал это на более явную фабрику, даже если бы у меня были десятки разных классов в App\Install\Model Пространство имен:

<?php declare(strict_types=1);

namespace App\Install\Factory;

use App\Install\Model as Models;

class AttributeEntityFactory
{
    public static function create($type = 'Attribute') : AttributeInterface
    {
        switch ($type) {
            case 'Attribute':
                return new Models\Attribute();
            case 'SomethingElse':
                return new Models\SomethingElse();
            default:
                throw new \InvalidArgumentException(
                    sprintf('An unknown type %s requested from %s', $type, __METHOD__)
                );
        }
    }
}

Как правило большого пальца:

  • Никогда не сочиняйте имена классов / пространства имен, используя строки, связанные с переменными / параметрами / константами.
  • Никогда не вызывайте методы таким способом тоже.

Вы будете благодарить меня, когда ваше приложение / бизнес / кодовая база вырастет достаточно.

Вам может понадобиться пройти в полном пространстве имен?

"App\Install\Model\" . $type1;

и больше...

Атрибут модели у вас есть в пространстве имен App\Install\Modelи объект, который вы пытаетесь создать, Models\\ . $type1

может быть, вам нужно изменить Models в Model

Другие вопросы по тегам