instantiate a class from a variable in PHP? - php

I know this question sounds rather vague so I will make it more clear with an example:
$var = 'bar';
$bar = new {$var}Class('var for __construct()'); //$bar = new barClass('var for __construct()');
This is what I want to do. How would you do it? I could off course use eval() like this:
$var = 'bar';
eval('$bar = new '.$var.'Class(\'var for __construct()\');');
But I'd rather stay away from eval(). Is there any way to do this without eval()?

Put the classname into a variable first:
$classname=$var.'Class';
$bar=new $classname("xyz");
This is often the sort of thing you'll see wrapped up in a Factory pattern.
See Namespaces and dynamic language features for further details.

If You Use Namespaces
In my own findings, I think it's good to mention that you (as far as I can tell) must declare the full namespace path of a class.
MyClass.php
namespace com\company\lib;
class MyClass {
}
index.php
namespace com\company\lib;
//Works fine
$i = new MyClass();
$cname = 'MyClass';
//Errors
//$i = new $cname;
//Works fine
$cname = "com\\company\\lib\\".$cname;
$i = new $cname;

How to pass dynamic constructor parameters too
If you want to pass dynamic constructor parameters to the class, you can use this code:
$reflectionClass = new ReflectionClass($className);
$module = $reflectionClass->newInstanceArgs($arrayOfConstructorParameters);
More information on dynamic classes and parameters
PHP >= 5.6
As of PHP 5.6 you can simplify this even more by using Argument Unpacking:
// The "..." is part of the language and indicates an argument array to unpack.
$module = new $className(...$arrayOfConstructorParameters);
Thanks to DisgruntledGoat for pointing that out.

class Test {
public function yo() {
return 'yoes';
}
}
$var = 'Test';
$obj = new $var();
echo $obj->yo(); //yoes

I would recommend the call_user_func() or call_user_func_arrayphp methods.
You can check them out here (call_user_func_array , call_user_func).
example
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func('Foo::test');//FOO is the class, test is the method both separated by ::
//or
call_user_func(array('Foo', 'test'));//alternatively you can pass the class and method as an array
If you have arguments you are passing to the method , then use the call_user_func_array() function.
example.
class foo {
function bar($arg, $arg2) {
echo __METHOD__, " got $arg and $arg2\n";
}
}
// Call the $foo->bar() method with 2 arguments
call_user_func_array(array("foo", "bar"), array("three", "four"));
//or
//FOO is the class, bar is the method both separated by ::
call_user_func_array("foo::bar"), array("three", "four"));

Related

How to access the constant in the class? [duplicate]

I'm trying to access a class constant in one of my classes:
const MY_CONST = "value";
If I have a variable which holds the name of this constant like this:
$myVar = "MY_CONST";
Can I access the value of MY_CONST somehow?
self::$myVar
does not work obviously because it is for static properties.
Variable variables does not work either.
There are two ways to do this: using the constant function or using reflection.
Constant Function
The constant function works with constants declared through define as well as class constants:
class A
{
const MY_CONST = 'myval';
static function test()
{
$c = 'MY_CONST';
return constant('self::'. $c);
}
}
echo A::test(); // output: myval
Reflection Class
A second, more laborious way, would be through reflection:
$ref = new ReflectionClass('A');
$constName = 'MY_CONST';
echo $ref->getConstant($constName); // output: myval
There is no syntax for that, but you can use an explicit lookup:
print constant("classname::$myConst");
I believe it also works with self::.
Can I access the value of MY_CONST somehow?
self::MY_CONST
If you want to access is dynamically, you can use the reflection API Docs:
$myvar = 'MY_CONST';
$class = new ReflectionClass(self);
$const = $class->getConstant($myVar);
The benefit with the reflection API can be that you can get all constants at once (getConstants).
If you dislike the reflection API because you don't wanna use it, an alternative is the constant function (Demo):
$myvar = 'MY_CONST';
class foo {const MY_CONST = 'bar';}
define('self', 'foo');
echo constant(self.'::'.$myvar);
Just a note for Reflection: the constructor for ReflectionClass must receive the full path of the class for its parameter.
This means that just setting the string 'A' as a constructor parameter may not work in some cases.
To avoid this problem, when using ReflectionClass you will be better if you do this:
$classA = new A();
$name_classA = get_class($classA);
$ref = new ReflectionClass(get_class($name_classA));
$constName = 'MY_CONST';
echo $ref->getConstant($constName);
Function get_class will give you the full path of a class whenever you are in the code. Missing the full path may result in a "Class not found" PHP error.
have you tried
$myVar = MY_CONST or $myVar = $MY_CONST

How to access static constants with a string variable [duplicate]

I'm trying to access a class constant in one of my classes:
const MY_CONST = "value";
If I have a variable which holds the name of this constant like this:
$myVar = "MY_CONST";
Can I access the value of MY_CONST somehow?
self::$myVar
does not work obviously because it is for static properties.
Variable variables does not work either.
There are two ways to do this: using the constant function or using reflection.
Constant Function
The constant function works with constants declared through define as well as class constants:
class A
{
const MY_CONST = 'myval';
static function test()
{
$c = 'MY_CONST';
return constant('self::'. $c);
}
}
echo A::test(); // output: myval
Reflection Class
A second, more laborious way, would be through reflection:
$ref = new ReflectionClass('A');
$constName = 'MY_CONST';
echo $ref->getConstant($constName); // output: myval
There is no syntax for that, but you can use an explicit lookup:
print constant("classname::$myConst");
I believe it also works with self::.
Can I access the value of MY_CONST somehow?
self::MY_CONST
If you want to access is dynamically, you can use the reflection API Docs:
$myvar = 'MY_CONST';
$class = new ReflectionClass(self);
$const = $class->getConstant($myVar);
The benefit with the reflection API can be that you can get all constants at once (getConstants).
If you dislike the reflection API because you don't wanna use it, an alternative is the constant function (Demo):
$myvar = 'MY_CONST';
class foo {const MY_CONST = 'bar';}
define('self', 'foo');
echo constant(self.'::'.$myvar);
Just a note for Reflection: the constructor for ReflectionClass must receive the full path of the class for its parameter.
This means that just setting the string 'A' as a constructor parameter may not work in some cases.
To avoid this problem, when using ReflectionClass you will be better if you do this:
$classA = new A();
$name_classA = get_class($classA);
$ref = new ReflectionClass(get_class($name_classA));
$constName = 'MY_CONST';
echo $ref->getConstant($constName);
Function get_class will give you the full path of a class whenever you are in the code. Missing the full path may result in a "Class not found" PHP error.
have you tried
$myVar = MY_CONST or $myVar = $MY_CONST

Use variable's string into class names or other

I want to use variables inside class names.
For example, let's set a variable named $var to "index2".
Now I want to print index2 inside a class name like this:
controller_index2, but instead of doing it manually, I can just print the var name there like this:
controller_$var;
but I assume that's a syntax error.
How can I do this?
function __construct()
{
$this->_section = self::path();
new Controller_{$this->_section};
}
It's a hideous hack, but:
php > class foo { function x_1() { echo 'success'; } };
php > $x = new foo;
php > $one = 1;
php > $x->{"x_$one"}();
^^^^^^^^^^^^
success
Instead of trying to build a method name on-the-fly as a string, an array of methods may be more suitable. Then you just use your variables as the array's key.
Echo it as a string in double quotes.
echo "controller_{$var}";
Try this (based on your code in the OP):
function __construct()
{
$this->_section = self::path();
$controller_name = "Controller_{$this->_section}";
$controller = new $controller_name;
}
You can do this.... follow this syntax
function __construct()
{
$this->_section = self::path();
$classname = "Controller_".$this->_section;
$instance = new $classname();
}
Another way to create an object from a string definition is to use ReflectionClass
$classname = "Controller_".$this->_section;
$reflector = new ReflectionClass($classname);
and if your class name has no constructor arguments
$obj = $reflector->newInstance();
of if you need to pass arguments to the constructor you can use either
$obj = $reflector->newInstance($arg1, $arg2);
or if you have your arguments in an array
$obj = $reflector->newInstanceArgs($argArray);
try this:
$name = "controller_$var";
echo $this->$name;
just to add on the previous answers, if you're trying to declare new classes with variable names but all the construction parameters are the same and you are treating the instanced object all alike maybe you don't need different classes but just different instances of the same.

Cannot access class constant from an instance using the :: scope operator

I hit a strange problem today and even as a PHP engineer i'm stumped at this:
It seems you can access a class constant from an object instance such as:
class a {
const abc = 1;
}
$a = new a();
var_dump($a->abc);
This will output null instead of the expected 1. I was able to do the following:
class a {
const abc = 1;
}
$a = new a();
var_dump(a::abc);
But in the context of a sub object that doesn't really know who the parent is exactly, i find it extremely annoying to do:
class a {
const abc = 1;
}
$a = new a();
$c = get_class($a);
var_dump($c::abc);
Is it me or this is completly stupid, if not, please enlighten me why its working that way.
EDIT
Another way of doing it but it's not really better:
class a {
const abc = 1;
}
class b {
public function getA(){
return new a();
}
}
$b = new b();
$c = $b->getA();
var_dump($c::abc);
This last example works more like what i am doing and experiencing...
Just use the instance variable with the scope resolution operator:
$a = new a();
var_dump($a::abc);
This prints 1.
I found a relatively nice and clean way to make my problem easier to live with. Here is the solution i've applied. It is not necessarely the best but for my uses it does exactly what i need.
By creating a magic __get method, i intercept the request for the constant name from and instance point of view and i use a quick reflection to see if that constant exists and return it's value.
This allows me to actually use all in one line a pattern that looks like this:
class a {
const abc = 1;
public function __get($key){
$r = new ReflectionObject($this);
if($r->hasConstant($key)){ return $r->getConstant($key); }
}
}
class b {
public function getA(){
return new a();
}
}
$b = new b();
var_dump($b->getA()->abc);
var_dump($b->getA()->def);
Althought i'd have liked to do:
var_dump($b->getA()::abc);
var_dump($b->getA()::def);
I guess this could be possible later in 5.4+ considering we finaly have array dereferencing, we could probably ask them to add static dereferencing soon.
The PHP documentation indicates that class constants are accessed via SRO (::) rather than ->.
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . "\n";
}
}
echo MyClass::constant . "\n";
ike I mentioned, in php constants are tied to the class definition, they are static by definition and cannot be accessed using the -> operator.
If you really want to use it with your coding paradigm, you can try the reflection class in php5.
class MyClass
{
const A = "I am A";
}
$o = new ReflectionClass( "MyClass" );
echo $o->getconstant("A"); //will print "I am A"
Also, I think the example in your EDIT might not work..I did not run it, but I am not sure if the SRO(::) can be invoked on anything that is not a class reference..
I know this is an old thread, but for people who want to know the best way to do this have a look at the PHP function constant().
With constant() you can simply do this:
$a = new a();
$value = constant(get_class($a)."::abc");
// $value === 1
this has been available since PHP 4, and still works perfectly in PHP 5.5
When trying to use const defined in a class inside a different namespace, the Scope Resolution Operator (::) can be used without problems as stated by the docs prefixing the namespace before the class in which the const was declared with this format:
(<namespace>"\")*<className>::<const>
With the next namespace, class and const definitions:
models/OperationModel.php
<?php
namespace models;
class OperationModel {
const OPERATION_INITIALIZING = 1;
}
You can use the const from another namespace\class like this:
controllers/MobileController.php
<?php
namespace controllers;
use models\OpertionModel;
class MobileController {
private function thingy() {
$operation_status = models\OperationModel::OPERATION_INITIALIZING;
}
}

accessing static methods using a variable class name (PHP)

I am trying to access a static method, but using a variable as the class name. Is this possible? I seem to be having issues with it. I want to be able to do something like this:
class foo {
public static function bar() {
echo 'test';
}
}
$variable_class_name = 'foo';
$variable_class_name::bar();
And I want to be able to do similar using static variables as well.
That syntax is only supported in PHP 5.3 and later. Previous versions don't understand that syntax, hence your parse error (T_PAAMAYIM_NEKUDOTAYIM refers to the :: operator).
In previous versions you can try call_user_func(), passing it an array containing the class name and its method name:
$variable_class_name = 'foo';
call_user_func(array($variable_class_name, 'bar'));
You can use reflection for PHP 5.1 and above:
class foo {
public static $bar = 'foobar';
}
$class = 'foo';
$reflector = new ReflectionClass($class);
echo $reflector->getStaticPropertyValue('bar');
> foobar

Categories