0

I am trying to create a class (working as factory class) in my Zend Expressive APP as follows:

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();
    }
}

The above code works perfectly for me. However, if try to use any of the other two return statements it shows

Class 'Models\Attribute' not found

How can I achieve dynamic instantiation?

The attribute class code is as follows:

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;   
    }  
}

My PHP version is:

PHP 7.2.13 (cli) (built: Dec 14 2018 04:20:16) ( NTS )

Md Monjur Ul Hasan
  • 1,705
  • 1
  • 13
  • 36

2 Answers2

0

you may need to pass in the full namespace?

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

and more...

the model Attribute you have is in the namespace App\Install\Model, and the object you are trying to create is from Models\\ . $type1

maybe you need to change Models to Model

Drakulitka
  • 41
  • 6
0

Personally, I would avoid such factory implementation because of several reasons:

  1. It involves magic.
  2. Less predictable code.
  3. Harder to read for both humans and IDE's (E.g: PHPStorm would not find the usages of Attribute class in such code when you need to find it)
  4. Harder to analyze using static analyzers

Instead, I would rewrite this to a more explicit factory, even if I had dozens of different classes in App\Install\Model namespace:

<?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__)
                );
        }
    }
}

As a rule of thumb:

  • Never compose classnames / namespaces using strings concatenated with variables / parameters / constants whatever.
  • Never call methods in such way, too.

You'll thank me when your application/business/codebase grows enough.

edigu
  • 9,878
  • 5
  • 57
  • 80