Use keyword and dynamic class names - php

use my\Project\FooClass;
$obj = new FooClass(); // ok
$name = 'FooClass';
$obj2 = new $name(); // throws an error that the class wasn't found
Well, I believe the title and the example were pretty enough explanation of my question, so just - why does this throws an error, and how should I deal with this?

Sadly, this is not possible due to the way PHP imports/aliases from namespaces. This can be remedied by using literal namespace definitions, though it no doubt sucks.
As follows:
$r = "my\\Project\\FooClass";
$k = new $r();
There is a patch in the works, or at the very least, it was on PHP's bug report a couple of months back. They will hopefully do something about it.
If it bothers you, you can use class_alias() to remedy it, by the way.

try:
$obj2 = new $name;
Remove the parenthesis
Alternatively:
$obj2 = new {$name}();

Can't explain why this doesn't work. But for how to deal with it:
$name = 'FooClass';
$name = "my\\Project\\FooClass\\" . $name; // prepend namespace
$obj2 = new $name();

Related

Why dont create Object so?

Before I could create an object in this way in PHP:
use myFolder\models\Document;
$nameClass = 'Document';
$model = new $nameClass;
This used to work without problems.
But now it gives me a error
Is it for the PHP version or configuration?
What is the problem?
Why it sentence works fine?
$model = new Document;
and the previous one fails?
Thanks
The problem was the namespace; it should have been
use myFolder\models\Document;
$nameClass = 'myFolder\models\Document';
$model = new $nameClass;

initiate an instance from variable name and namespace in one line

$map_class_name = __NAMESPACE__.'\\'.$map_class_name;
$map = new $map_class_name;
Is it possible to do this in one line like this?
$map = new (__NAMESPACE__.'\\'.$map_class_name);
The above gives
syntax error, unexpected '('
The answer is no, you can't use new with string or expression.
But you can use
$map = new $map_class_name;
Since you use class from current namespace(__NAMESPACE__) you don't have to prefix classname, namespace will be implied.
Alternative solutions
You might use Reflection
$map = (new \ReflectionClass(__NAMESPACE__."\\$map_class_name"))->newInstance();
Another way is to not break line, but I guess this misses the point.
$map_class_name = __NAMESPACE__.'\\'.$map_class_name; $map = new $map_class_name;
IIFE is also possible
$map = (function($n){return new $n;})(__NAMESPACE__."\\$map_class_name");

Unknown PHP obfuscation technique

I've come accross a piece of code using various techniques of obfuscation and, mostly driven by curiosity, have been trying to understand the techniques it uses.
I've done some work on it, but i'm at a point where I don't understand fully what it's doing :
public $x1528 = null;
public $x153c = null;
function __construct()
{
$this->x1528 = new \StdClass();
$this->x153c = new \StdClass();
$this->x1528->x21a9 = "getSingleton";
$this->x1528->x1569 = "x1565";
$this->x1528->x1e45 = "x1e40";
$this->x153c->x3b3b = "x3b38";
$this->x1528->x16c3 = "x16c2";
$this->x1528->x1bec = "x1be8";
$this->x1528->x245a = "x2455";
$this->x1528->x1b14 = "x10d7";
$this->x153c->x36d4 = "x36d2";
$this->x1528->x24d6 = "getSingleton";
$this->x1528->x1876 = "xf0f";
$this->x1528->x2901 = "x2900";
$this->x1528->x1877 = "x1876";
$this->x153c->x335b = "x3356";
$this->x1528->x2836 = "x2833";
$this->x1528->x2119 = "x2115";
$this->x1528->x18bb = "xf3d";
$this->x153c->x349e = "x349a";
$this->x1528->x2383 = "getData";
$this->x1528->x17b1 = "x5f2";
$this->x153c->x2d06 = "xf41";
$this->x1528->x1f35 = "x1f30";
$this->x1528->x1a93 = "x1138";
$this->x1528->x1d79 = "x1d76";
$this->x1528->x1d7c = "x1d79";
$this->x153c->x3248 = "_isAllowed";
...
[it keeps going for a while...]
So it declares empty variables, generates empty objects, and then stores strings and references to other variables, but...
for example,
$this->x1528->x21a9 = "getSingleton";
What is x21a9 ? There's no reference to this anywhere, and I thought the x1528 variable was empty ? Also, is this a way of referencing the $x1528 without the $, because i've never seen this syntax before.
This is using PHP techniques I was not aware of, and this has made me very curious. Any help ?
Without seeing the entire code it's hard to tell. But basically this is just "gibberish" making it hard to read, but basic PHP nevertheless.
What is x21a9 ?
It's just a random property set on the $x1528 class. Like:
$dummyClass = new StdClass(); // Same as $this->x1528 = new \StdClass();
$dummyClass->foo = "bar"; // Same as $this->x1528->x21a9 = "getSingleton";
Now, echo $dummyClass->foo would return bar. It's just setting a property with a value, but with "cryptic" names.
I thought the x1528 variable was empty ?
It starts out empty at the beginning of the class, but then in the constructor, it's immediately set up as an instance of StdClass:
$this->x1528 = new \StdClass();
Also, is this a way of referencing the $x1528 without the $, because i've never seen this syntax before.
This is basic syntax for objects. The object itself has a $ in front of it, but the properties don't.

Can I dynamically set new object name

I want to create objects dynamically. Right now I'm creating them manually like this
$obj1 = new Prefix_Myobj();
$obj2 = new Prefix_Other();
$obj3 = new Prefix_Another();
How can I set the part after Prefix_ dynamically? I tried this but it didn't work
$name = 'Myobj';
$obj1 = new Prefix_{$name}();
You need to create a string that specifies the entire class name.
$name = 'Myobj';
$classname = 'Prefix_'.$name;
$obj1 = new $classname();
However, it might be better design to build a class registry of sorts rather than generating class names on the fly like this.
Why do you need this? Maybe there is a better solution for your problem; multiton or dependency injection etc...
It is important to say that if your class is in a specific namespace, you need to inform the full path. Example:
namespace my\path\app;
class MyClass {
$name = 'Myobj';
$classname = 'my\path\app\Prefix_' . $name;
$obj1 = new $classname();
}

Dynamic static method call in PHP?

Please could someone experienced in PHP help out with the following. Somewhere in my code, I have a call to a public static method inside a non-instantiated class:
$result = myClassName::myFunctionName();
However, I would like to have many such classes and determine the correct class name on the fly according to the user's language. In other words, I have:
$language = 'EN';
... and I need to do something like:
$result = myClassName_EN::myFunctionName();
I know I could pass the language as a parameter to the function and deal with it inside just one common class but for various reasons, I would prefer a different solution.
Does this make any sense, anyone? Thanks.
Use the call_user_func function:
http://php.net/manual/en/function.call-user-func.php
Example:
call_user_func('myClassName_' . $language . '::myFunctionName');
I think you could do:
$classname = 'myClassName_' . $language;
$result = $classname::myFunctionName();
This is called Variable Functions
I would encapsulate the creation of the class you need in a factory.
This way you will have a single entry point when you need to change your base name or the rules for mapping the language to the right class.
class YourClassFactory {
private $_language;
private $_basename = 'yourclass';
public YourClassFactory($language) {
$this->_language = $language;
}
public function getYourClass() {
return $this->_basename . '_' . $this->_language;
}
}
and then, when you have to use it:
$yourClass = $yourClassFactoryInstance->getYourClass();
$yourClass::myFunctionName();
As temuri said, parse error is produced, when trying '$className::functionName' :
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM ...
In my case (static method with 2 arguments), best solutions is to use call_user_func_array with 2 arrays (as suggested by nikc.org):
$result = call_user_func_array(array($className, $methodName), array($ard1, $arg2));
BR
although i think the way you deal is a very bad idea, i think i may have a solution
$className = 'myClassName_'.$language;
$result = $className::myFunctionName();
i think this is what you want
You can easily do next:
<?php
class B {
public static $t = 5;
public static function t($h) {
return "Works!" . $h;
}
}
$g = 't';
$class = 'B';
echo $class::$g('yes'); //Works! Yes
And it will works fine, tested on PHP 5.2 >=
As far as i could understand your question, you need to get the class name which can be done using get_class function. On the other hand, the Reflection class can help you here which is great when it comes to methods, arguments, etc in OOP way.
Solutions like:
$yourClass::myFunctionName();
will not work. PHP will produce parse error.
Unfortunately, the only way is to use very slow call_user_func().
I know it's an old thread, but as of PHP 5.3.0 you should be using forward_static_call
$result = forward_static_call(array('myClassName_EN', 'myFunctionName'));
Using your $language variable, it might look like:
$result = forward_static_call(array('myClassName_' . $language, 'myFunctionName'));

Categories