1

I've seen questions like this and this, but neither addresses how to create a class instance from a string name if you already have a namespace and the class is in an aliased namespace:

<?php
namespace my\project;

require 'vendor/autoload.php';

//Example aliased classes, more may be defined elsewhere
use League\OAuth2\Client\Provider\Google;
use Stevenmaguire\OAuth2\Client\Provider\Microsoft;

//This is mapped from a submitted form value
$provider = 'Google';

$g = new $provider;

This throws PHP Fatal error: Class 'Google' not found. In those questions, it says you should prefix with __NAMESPACE__, but the problem is that these classes are not in the my\project namespace so that doesn't work either, because it results in a class name of my\project\Google which doesn't exist.

A dumb fix for this specific code would be to use an array to store all the namespaces and class names, but that can't work if I don't know all possible class names in advance.

I can't even see how to use reflection to solve this because I can't create a reflection object for the aliased class for the same reason - new \ReflectionClass($provider); throws the same error.

How can I get the namespace of an aliased class name dynamically?

2
  • Try use League\OAuth2\Client\Provider\Google as Google Commented Apr 5, 2016 at 16:46
  • @Xorifelse, nope, that's the same as what I have Commented Apr 5, 2016 at 16:56

2 Answers 2

1

You will simply have to use:

$provider = 'League\OAuth2\Client\Provider\Google';

There is no other solution, class name variables need to contain the fully qualified class name; aliasing doesn't apply to string class names, and introspection can't help you either.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, this is clear. But if the class file is loaded, OP can (try to) retrieve his complete name. +1 for your clarity/concision
And the "(try to)" is exactly the reason that approach is rather... suboptimal. :) Explicitly name the class by its full(ly qualified) name, period.
0

Namespaces are introduced to allow same names in different contexts, so the answer is: no, it is not possible.

You can have a class \League\OAuth2\Client\Provider\Google and another class \League\OAuth1\Client\Provider\Google: in this case, how you can determine what class to instantiate?

Assuming you know that there are only unique class names, you can use this code:

$provider = 'Google';
$found = False;
foreach( get_declared_classes() as $class )
{
    if( preg_match( "~(.*\\\)?($provider)$~", $class ) )
    {
        $found = $class;
        break;
    }
}

if( $found )
{
    $g = new '\\'.$found;
}
else
{
    echo "No '$provider' class found";
}

demo with DateTime class

but this routine is only a simplification of your idea “to use an array to store all the namespaces and class names”, because — even with above code — if you don't know all declared classes, you can obtain unwanted results.

9 Comments

Thanks. There are further twists to this - autoloaded classes won't be in the get_declared_classes list yet, and having a use statement does not necessarily imply that a class exists - that only matters when you try to instantiate it.
If you use autoload I think you don't have chances: how can php know what do you want?
It does know what I want! If I use the aliased class name explicitly, $a = new Google;, it works fine. I think this is possibly a PHP bug - class name resolution seems to be not quite in the right order.
autoload is stock composer.
do you call require something/vendor/autoload.php; require something/vendor/autoload.php; ect... ?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.