How can we use variable in classes name on call?
For example i have a class That called like this:
<?php
$ig = new Instagram();
$ig->people->getIdByName("param1",array('a','b','c'),"param2");
So how can i call this method like this?:
<?php
$ig = new Instagram();
$main = 'people';
$sub = 'getIdByName';
$content = '"param1",array('a','b','c'),"param2"';
$ig->$main->$sub($content);
Methods calls would work just like you showed in the question. So this part of code is OK:
$main = 'people';
$sub = 'getIdByName';
$ig->$main->$sub();
What about last method's arguments, there 2 options:
PHP >= 5.6
Variadic parameters were introduced in PHP 5.6, so you can save your arguments as an array, and just pass them with ...:
$args = ["param1",['a','b','c'],"param2"];
$ig->$main->$sub(...$args);
PHP < 5.6
In this case you should use call_user_func_array()
$main = 'people';
$sub = 'getIdByName';
$args = ["param1",['a','b','c'],"param2"];
$main = $ig->$main;
call_user_func_array([$main, $sub], $args];
Although #Andrew is right, this approach is not flexible and must not be used as an architecture for API providers.
Related
How to extract method name and argument from a string code?
Example :
$obj->MethodA($obj->MethodB(param1,$obj->MethodX()))
I tried using this regex but not work
preg_match_all('/\$obj->(\w+)\(((\w|,| )*)\)/', $string, $matches)
The aim is to extract all the method calls as well as their arguments, so the matches should match
$obj->MethodA($obj->MethodB(param1, $obj->MethodX()))
$obj->MethodB(param1,$obj->MethodX())
$obj->MethodX()
Some people might say using regex is not ideal. Is there any alternative?
I would recommend using something that understands PHP's syntax. For example this library - https://github.com/nikic/PHP-Parser
Regex would probably get unwieldy pretty fast.
Quick example using the mentioned PHP-Parser.
use PhpParser\Node\Expr\CallLike;
use PhpParser\NodeFinder;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter\Standard;
$php = '<?php $obj->MethodA($obj->MethodB("test",$obj->MethodX()));';
$parserFactory = new ParserFactory();
$parser = $parserFactory->create(ParserFactory::PREFER_PHP7);
$statements = $parser->parse($php);
$finder = new NodeFinder();
// Or if you only want method calls, we could also find instances of MethodCall
$calls = $finder->findInstanceOf($statements, CallLike::class);
$printer = new Standard();
foreach ($calls as $call) {
echo $printer->prettyPrintExpr($call) , "\n";
}
// Output
//$obj->MethodA($obj->MethodB("test", $obj->MethodX()))
//$obj->MethodB("test", $obj->MethodX())
//$obj->MethodX()
$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");
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.
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'));
I have a rather stupid PHP question :D! I would like to simplify the following statement:
function hello_input() {
return 'Hello World';
}
$helper = 'hello';
$helper = $helper . '_input';
$data = $helperinput();
The specific part I want to simplify is the adding of the _input to the $helper so it calls the right function.
I thought of something like this but it doesn't work:
$data = $helper. 'input'();
or
$data = $helper. 'input' . ();
Any ideas?
Thanks,
Max
Use call_user_func, e.g. $data = call_user_func($helper.'input');.
$helper = 'hello_';
$data = $helper.'input';
call_user_func($data);
That should get you most of the way there. Good luck!
Docs here
Are you expecting to invoke code based on an input? You should never try to do that. That gives people the chance to execute arbitrary code. Even if you can't see quite how, it's still a potential method of attack.
What you probably want is a switch statement (or chained if statements) that match an input and dispatch the correct function.
Get the whole function name into a string first.
$helper = 'hello';
$func = $helper . '_input';
$data = $func();
PHP calls this variable functions. See also variable variables.