0

As expected the example below does not work but how can i tell php that my classname-string should be an uninstantiated class ? I know that i could work around with some tricks but is there a proper way?

thanks to magnus i like to add that in use I don't want to hard code the class name in the function it could be anything but taking care that it exists etc is not part of the question.

(for php>7.1)

The other direction works with get_class.

Interface iFoo {
    static function getBar(): string;
}
class Foo implements  iFoo {
    private static $bar = "`My test value`";
    static function getBar(): string {
        return self::$bar;
    }
}

function getMyClass() : iFoo {
    $classes = array('Foo');
    print "this works: ".$classes[0]::getBar();
    // return failes
    print "this does not:";
    return $classes[0];
}

Output:

this works: `My test value`this does not:

Fatal error:  Uncaught TypeError: Return value of getMyClass() must implement interface iFoo, string returned

I know that it works with : iFoo | string but then the typehinting is obsolete. I am missing something like a make-class-of-string() function.

Thank you for your help in advance :)

Erik255
  • 1,463
  • 1
  • 11
  • 13
  • If `: iFoo` could mean either a string or a class instance, it would be useless as a type. Types are used to make sure that you'll always get what you expect from a function/method. If it could return either a string or an object, it would be ambiguous and you wouldn't know if you should use `getMyClass()->foo()` or `getMyClass()::foo()`. Explain what problem you're really trying to solve here and we might be able to help with that. Currently, this sounds like a [XY problem](https://xyproblem.info/). You can't return an un-instantiated class. – M. Eriksson May 23 '21 at 13:24
  • exactly but i want to force it to be a class object (not an instance of a class) of that type. I would use it to route to a specific implementation of iFoo depending on conditions. – Erik255 May 23 '21 at 13:26
  • An object _is_ an instance of a class, so the statement _"force it to be a class object (not an instance of a class) "_ makes no sense. You can either return an _instance_ of a class which either is called iFoo, extends iFoo or implements iFoo. If you want to return a string, use `: string`. If you want to make sure that the string you return is a valid class name that implements a specific interface, you need to validate that in your function before returning the string. You can use [class_implements()](https://www.php.net/manual/en/function.class-implements.php) for that. – M. Eriksson May 23 '21 at 13:35
  • `new className()` would be an instance className is a `class`. I am well aware of what happens here i want to know if there is a syntactic way oŕ a php function making sure that it can only be the `class` so that typehinting works properly – Erik255 May 23 '21 at 13:39
  • It's not possible to type hint that a function/method should return a string that refers to a class name, let alone any attributes it should have. – M. Eriksson May 23 '21 at 13:48
  • Ok but is there a solution like casting or some php function to transform the string -> class (thats my question in one sentence) – Erik255 May 23 '21 at 13:54
  • 1
    If you just want to return an actual object, you can dynamically instantiate the class by doing: `return new $classes[0];`. But since you explicitly say that you don't want to _"force it as an instance of a class"_, I'm not sure that's what you want (unless you actually just mean that you don't want to _hard code_ the class name in the function?) If not, I have no idea what you actually want. – M. Eriksson May 23 '21 at 13:56

1 Answers1

1

There is no way to do it.

The return type is a type of an instance (be it a complex or a primitive type). Something that exists in memory.

The ::class keyword is a simple helper that resolves to a fully qualified name of a class, which is a string (a primitive type).

A return type is a type of an object and not something that would be of a specific type upon instantiation. And there are no tricks to say "upon instantiation, this string will be of type Foo".

The $classes[0]::getBar() construct works because it's a syntactic sugar. PHP resolves it to something like Foo::getBar() which syntactically is a call to a static function. And as you noticed - that works perfectly fine.

Aleksander Wons
  • 3,611
  • 18
  • 29