PHP Dynamically determine fully qualified class name - php

I've found that by using ::class, I can get the fully qualified class name of a namespaced class:
namespace NameSpace {
class Foo { }
echo Foo::class;
}
// echoes 'NameSpace\Foo'
But I can't figure out a way to do this with a variable class name. Trying to treat the class keyword like a static property doesn't seem to work:
namespace NameSpace {
class Foo { }
$className = 'Foo';
echo $className::class;
}
// Parse error: syntax error, unexpected 'class'
Does anyone know if its possible to get the fully qualified class name dynamically like I'm trying to?
I want to be able to do this with classes from outside the current namespace:
namespace ReallyLongHardToWriteNameSpace {
class Foo { }
}
namespace NameSpace {
use ReallyLongHardToWriteNameSpace\Foo;
class Bar { }
echo Foo::class; // echoes 'ReallyLongHardToWriteNameSpace\Foo'
echo Bar::class; // echoes 'NameSpace\Bar'
foreach (['Foo', 'Bar'] as $className) {
echo $className::class; // Parse error: syntax error, unexpected 'class'
}
}

You can use get_class with an instance of that class:
<?php
namespace NS {
class Foo { }
$className = "\\NS\\Foo";
echo get_class(new $className);
}
// prints NS\Foo
Do note that to create an instance of the class I had to use the FQN in the string, so it might not be useful at all.

Ok, I came up with another solution. Even tho this is somewhat different.
namespace NameSpace;
class Foo {
public static function getFullName() {
return __CLASS__;
}
}
print Foo::getFullName(); // Prints NameSpace\Foo
Just create a abstract class which has getFullName() as method and inherit from it on all classes you want to be able to return full name.
Simplest approch (I almost forgot) is the use of get_class()
$className = get_class($yourClassObject); // returns NameSpace\Foo
You can also try using eval() for this.
$className = 'NameSpace\Foo::class';
eval('$fullName = ' . $className);
print $fullName; // returns NameSpace\Foo
Even tho, this might not be exactly what you want, but you should look at the Reflection library. Its very handy to use for such things.
// Lets say you have an object of your class
$object = new ReflectionObject($yourObject);
$name = $object->getName(); // will return NameSpace\Foo
// You can also give the class name to it
$class = new ReflectionClass('Foo');
$name = $class->getName(); // also returns NameSpace\Foo
Look here for more information
There are also classes for methods, properties, etc.

You can use __NAMESPACE__ to get the current namespace, then just prepend that to the string that contains the class name.
namespace NS {
class Foo {
}
$className = 'Foo';
echo __NAMESPACE__ . '\\' . $className;
}

Related

PHP return the instanceof an object [duplicate]

public class MyClass {
}
In Java, we can get class name with String className = MyClass.class.getSimpleName();
How to do this in PHP? I already know get_class(), but it works only for objects. Currently I work in Active Record. I need statement like MyClass::className.
Since PHP 5.5 you can use class name resolution via ClassName::class.
See new features of PHP5.5.
<?php
namespace Name\Space;
class ClassName {}
echo ClassName::class;
?>
If you want to use this feature in your class method use static::class:
<?php
namespace Name\Space;
class ClassName {
/**
* #return string
*/
public function getNameOfClass()
{
return static::class;
}
}
$obj = new ClassName();
echo $obj->getNameOfClass();
?>
For older versions of PHP, you can use get_class().
You can use __CLASS__ within a class to get the name.
http://php.net/manual/en/language.constants.predefined.php
It sounds like you answered your own question. get_class will get you the class name. It is procedural and maybe that is what is causing the confusion. Take a look at the php documentation for get_class
Here is their example:
<?php
class foo
{
function name()
{
echo "My name is " , get_class($this) , "\n";
}
}
// create an object
$bar = new foo();
// external call
echo "Its name is " , get_class($bar) , "\n"; // It's name is foo
// internal call
$bar->name(); // My name is foo
To make it more like your example you could do something like:
<?php
class MyClass
{
public static function getClass()
{
return get_class();
}
}
Now you can do:
$className = MyClass::getClass();
This is somewhat limited, however, because if my class is extended it will still return 'MyClass'. We can use get_called_class instead, which relies on Late Static Binding, a relatively new feature, and requires PHP >= 5.3.
<?php
class MyClass
{
public static function getClass()
{
return get_called_class();
}
public static function getDefiningClass()
{
return get_class();
}
}
class MyExtendedClass extends MyClass {}
$className = MyClass::getClass(); // 'MyClass'
$className = MyExtendedClass::getClass(); // 'MyExtendedClass'
$className = MyExtendedClass::getDefiningClass(); // 'MyClass'
It looks like ReflectionClass is a pretty productive option.
class MyClass {
public function test() {
// 'MyClass'
return (new \ReflectionClass($this))->getShortName();
}
}
Benchmark:
Method Name Iterations Average Time Ops/second
-------------- ------------ -------------- -------------
testExplode : [10,000 ] [0.0000020221710] [494,518.01547]
testSubstring : [10,000 ] [0.0000017177343] [582,162.19968]
testReflection: [10,000 ] [0.0000015984058] [625,623.34059]
To get class name you can use ReflectionClass
class MyClass {
public function myNameIs(){
return (new \ReflectionClass($this))->getShortName();
}
}
Now, I have answer for my problem. Thanks to Brad for the link, I find the answer here. And thanks to J.Money for the idea. My solution:
<?php
class Model
{
public static function getClassName() {
return get_called_class();
}
}
class Product extends Model {}
class User extends Model {}
echo Product::getClassName(); // "Product"
echo User::getClassName(); // "User"
I think it's important to mention little difference between 'self' and 'static' in PHP as 'best answer' uses 'static' which can give confusing result to some people.
<?php
class X {
function getStatic() {
// gets THIS class of instance of object
// that extends class in which is definied function
return static::class;
}
function getSelf() {
// gets THIS class of class in which function is declared
return self::class;
}
}
class Y extends X {
}
class Z extends Y {
}
$x = new X();
$y = new Y();
$z = new Z();
echo 'X:' . $x->getStatic() . ', ' . $x->getSelf() .
', Y: ' . $y->getStatic() . ', ' . $y->getSelf() .
', Z: ' . $z->getStatic() . ', ' . $z->getSelf();
Results:
X: X, X
Y: Y, X
Z: Z, X
This will return pure class name even when using namespace:
echo substr(strrchr(__CLASS__, "\\"), 1);
end(preg_split("#(\\\\|\\/)#", Class_Name::class))
Class_Name::class: return the class with the namespace. So after you only need to create an array, then get the last value of the array.
From PHP 8.0, you can use ::class even on objects:
$object = new \SplPriorityQueue();
assert($object::class === \SplPriorityQueue::class);
<?php
namespace CMS;
class Model {
const _class = __CLASS__;
}
echo Model::_class; // will return 'CMS\Model'
for older than PHP 5.5

PHP namespace Error (the name is already in use)

I'm trying to run this code on the same file:
namespace Foo1\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo1';
}
}
namespace Foo2\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo2';
}
}
use Foo1\Bar\SubBar;
$foo1 = new SubBarClass;
use Foo2\Bar\SubBar;
$foo2 = new SubBarClass;
The ideia is to change namespaces and echo the related value.
But it's returning the following error:
( ! ) Fatal error: Cannot use Foo2\Bar\SubBar as SubBar because the name is already in use in C:\wamp\www\xxx\namespaces.php on line 30
Line 30: use Foo2\Bar\SubBar;
How can I interchange namespaces on the same file?
Thks!
use keyword is used to import that namespace to be accessed in your current file scope. It does not act as a namespace "instance constructor".
You're current under Foo2\Bar\SubBar namespace. Like a directory of classes, while you're here, you should access other namespaces from the root (\):
$foo2 = new SubBarClass;
$foo1 = new \Foo1\Bar\SubBar\SubBarClass;
There is no need to use use for those namespaces (although you can, specially when they share parent namespaces), they are already declared in the same file you're using them.
For more information about this, consider reading the manual, where it describes using multiple namespaces in the same file.
This happens because the last defined namespace is the one currently active.
So, when I type:
use Foo1\Bar\SubBar;
I'm still on the last defined namespace: Foo2\Bar\SubBar.
Hence, when I type:
use Foo2\Bar\SubBar;
I'm trying to use the currently active namespace. That's why the Fatal error is returned.
On possible solution is:
namespace Foo1\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo1';
}
}
namespace Foo2\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo2';
}
}
use Foo1\Bar\SubBar;
$foo1 = new SubBar\SubBarClass;
echo '<br>';
$foo2 = new SubBarClass;
Cheers!

How to get the namespace where a function is called?

Is there a way to make this to work?
<?php
namespace Bar {
class test {
public function test($action) {
call_user_func($action); // must call \Foo\Action
}
}
}
namespace Foo {
$test = new \Bar\Test;
function action () {
echo 'it works!';
}
$test->test('action');
}
For a more detailed description: If I have a function that call user defined functions with de call_user_func, and uses that function in a Foo namespace to call a Foo namespaced function, how can I know that this passed function is on Foo namespace?
If you pass a function around by name in a string, you always need to use the fully qualified name including namespace. 'action' refers to the function \action. Even within the same namespace this won't work correctly. You need to use 'Foo\action' under all circumstances.
If you don't like hardcoding the namespace name, use __NAMESPACE__ . '\\action'.
You could use the constant __NAMESPACE__ and pass it as argument, e.g.
$test->test("\\" . __NAMESPACE__ . '\\action');

How do I get class name in PHP?

public class MyClass {
}
In Java, we can get class name with String className = MyClass.class.getSimpleName();
How to do this in PHP? I already know get_class(), but it works only for objects. Currently I work in Active Record. I need statement like MyClass::className.
Since PHP 5.5 you can use class name resolution via ClassName::class.
See new features of PHP5.5.
<?php
namespace Name\Space;
class ClassName {}
echo ClassName::class;
?>
If you want to use this feature in your class method use static::class:
<?php
namespace Name\Space;
class ClassName {
/**
* #return string
*/
public function getNameOfClass()
{
return static::class;
}
}
$obj = new ClassName();
echo $obj->getNameOfClass();
?>
For older versions of PHP, you can use get_class().
You can use __CLASS__ within a class to get the name.
http://php.net/manual/en/language.constants.predefined.php
It sounds like you answered your own question. get_class will get you the class name. It is procedural and maybe that is what is causing the confusion. Take a look at the php documentation for get_class
Here is their example:
<?php
class foo
{
function name()
{
echo "My name is " , get_class($this) , "\n";
}
}
// create an object
$bar = new foo();
// external call
echo "Its name is " , get_class($bar) , "\n"; // It's name is foo
// internal call
$bar->name(); // My name is foo
To make it more like your example you could do something like:
<?php
class MyClass
{
public static function getClass()
{
return get_class();
}
}
Now you can do:
$className = MyClass::getClass();
This is somewhat limited, however, because if my class is extended it will still return 'MyClass'. We can use get_called_class instead, which relies on Late Static Binding, a relatively new feature, and requires PHP >= 5.3.
<?php
class MyClass
{
public static function getClass()
{
return get_called_class();
}
public static function getDefiningClass()
{
return get_class();
}
}
class MyExtendedClass extends MyClass {}
$className = MyClass::getClass(); // 'MyClass'
$className = MyExtendedClass::getClass(); // 'MyExtendedClass'
$className = MyExtendedClass::getDefiningClass(); // 'MyClass'
It looks like ReflectionClass is a pretty productive option.
class MyClass {
public function test() {
// 'MyClass'
return (new \ReflectionClass($this))->getShortName();
}
}
Benchmark:
Method Name Iterations Average Time Ops/second
-------------- ------------ -------------- -------------
testExplode : [10,000 ] [0.0000020221710] [494,518.01547]
testSubstring : [10,000 ] [0.0000017177343] [582,162.19968]
testReflection: [10,000 ] [0.0000015984058] [625,623.34059]
To get class name you can use ReflectionClass
class MyClass {
public function myNameIs(){
return (new \ReflectionClass($this))->getShortName();
}
}
Now, I have answer for my problem. Thanks to Brad for the link, I find the answer here. And thanks to J.Money for the idea. My solution:
<?php
class Model
{
public static function getClassName() {
return get_called_class();
}
}
class Product extends Model {}
class User extends Model {}
echo Product::getClassName(); // "Product"
echo User::getClassName(); // "User"
I think it's important to mention little difference between 'self' and 'static' in PHP as 'best answer' uses 'static' which can give confusing result to some people.
<?php
class X {
function getStatic() {
// gets THIS class of instance of object
// that extends class in which is definied function
return static::class;
}
function getSelf() {
// gets THIS class of class in which function is declared
return self::class;
}
}
class Y extends X {
}
class Z extends Y {
}
$x = new X();
$y = new Y();
$z = new Z();
echo 'X:' . $x->getStatic() . ', ' . $x->getSelf() .
', Y: ' . $y->getStatic() . ', ' . $y->getSelf() .
', Z: ' . $z->getStatic() . ', ' . $z->getSelf();
Results:
X: X, X
Y: Y, X
Z: Z, X
This will return pure class name even when using namespace:
echo substr(strrchr(__CLASS__, "\\"), 1);
end(preg_split("#(\\\\|\\/)#", Class_Name::class))
Class_Name::class: return the class with the namespace. So after you only need to create an array, then get the last value of the array.
From PHP 8.0, you can use ::class even on objects:
$object = new \SplPriorityQueue();
assert($object::class === \SplPriorityQueue::class);
<?php
namespace CMS;
class Model {
const _class = __CLASS__;
}
echo Model::_class; // will return 'CMS\Model'
for older than PHP 5.5

Get PHP class namespace dynamically

How can I retrieve a class namespace automatically?
The magic var __NAMESPACE__ is unreliable since in subclasses it's not correctly defined.
Example:
class Foo\bar\A -> __NAMESPACE__ === Foo\bar
class Ping\pong\B extends Foo\bar\A -> __NAMESPACE__ === Foo\bar (it should be Ping\pong)
ps: I noticed the same wrong behavior using __CLASS__, but I solved using get_called_class()... is there something like get_called_class_namespace()? How can I implement such function?
UPDATE:
I think the solution is in my own question, since I realized get_called_class() returns the fully qualified class name and thus I can extract the namespace from it :D
...Anyway if there is a more effective approach let me know ;)
The namespace of class Foo\Bar\A is Foo\Bar, so the __NAMESPACE__ is working very well. What you are looking for is probably namespaced classname that you could easily get by joining echo __NAMESPACE__ . '\\' . __CLASS__;.
Consider next example:
namespace Foo\Bar\FooBar;
use Ping\Pong\HongKong;
class A extends HongKong\B {
function __construct() {
echo __NAMESPACE__;
}
}
new A;
Will print out Foo\Bar\FooBar which is very correct...
And even if you then do
namespace Ping\Pong\HongKong;
use Foo\Bar\FooBar;
class B extends FooBar\A {
function __construct() {
new A;
}
}
it will echo Foo\Bar\FooBar, which again is very correct...
EDIT: If you need to get the namespace of the nested class within the main that is nesting it, simply use:
namespace Ping\Pong\HongKong;
use Foo\Bar\FooBar;
class B extends FooBar\A {
function __construct() {
$a = new A;
echo $a_ns = substr(get_class($a), 0, strrpos(get_class($a), '\\'));
}
}
In PHP 5.5, ::class is available which makes things 10X easier. E.g.
A::class
Use Reflection class.
$class_name = get_class($this);
$reflection_class = new \ReflectionClass($class_name);
$namespace = $reflection_class->getNamespaceName();

Categories