I am working on a simple router program in PHP.
Here is my function
private function dispatch($dest)
{
$goto = explode("#", $dest);
$controller = $goto[0];
$action = $goto[1];
$clocation = require_once("../app/controllers/$controller.php");
$c = new $controller;
}
Everything works to that point. But, I want to return the results of the action (a method within the class that is instantiated as $c.
I tried :
return $c->$action
but that doesn't work.
Is there a way to do this, or do I need to try a different approach all together?
thanks
Try this
return $c->$action();
With the () for a method/function call. Otherwise PHP thinks it's a dynamic property of $c
You can test this like so:
class foo{
public $bar = 'bar';
function test(){ return 'test'; }
}
$foo = new foo();
$bar = 'bar';
$test = 'test';
echo $foo->$bar . PHP_EOL;
echo $foo->$test() . PHP_EOL;
Outputs
bar
test
Try it online
And $foo->$test would give you this notice
<br />
<b>Notice</b>: Undefined property: foo::$test in <b>[...][...]</b> on line <b>16</b><br />
Which means you either didn't mention it, don't have error reporting on, or your class has a property with the same name as that method.
Related
I need to call an function that is part of an object. The following call works as one would expect:
$someobject = getobject();
$result = $someobject->somefunction->value();
However, I need the "somefunction" component to be a variable.
I have tried to do it like this:
$var = 'somefunction';
$result = '$someobject->' . $var '->value'();
This does not work, but I hope it conveys what I am looking for. I've also tried a lot of variations based upon call_user_func() – without finding a syntax that works.
I am running: PHP 7.2.24-0ubuntu0.18.04.3. Vanilla version for Ubuntu 18.04 LTS.
To access a property or method dynamically based on its name, you simply use one more $ sign than you would normally.
For example, if we have this object:
class Foo {
public $someproperty = 'Hello!';
public function somefunction() {
return 'Hello World';
}
}
$someobject = new Foo;
Then we can access the property normally:
echo $someobject->someproperty;
Or dynamically by name:
$var = 'someproperty';
echo $someobject->$var;
Similarly, we can access the method normally:
echo $someobject->somefunction();
Or dynamically by name:
$var = 'somefunction';
$result = $someobject->$var();
Note that your example is a bit confusing, because you talk about "accessing a function where one part is a variable", but all you're actually trying to do is access a property dynamically, and you then happen to be calling a method on the object stored in that property. So the part you've called somefunction is actually the name of a property.
Here's an example that looks a bit like yours, but with the names changed:
class A {
public $foo;
}
class B {
public function value() {
return 'Hello World';
}
}
$a = new A;
$a->foo = new B;
$propertyname = 'foo';
echo $a->$propertyname->value();
class Blueprint
{
public function method()
{
return 'placeholder';
}
}
$object = new Blueprint;
$method = 'method';
// this will output `placeholder`
echo $object->{$method}();
Hooray!
The following (two alternative valid syntaxes are produced for the second line) works as expected without producing any errors:
$foobar = 'somefunction';
$result = $someobject->$foobar->value();
$result = $someobject->{$foobar}->value();
The following:
$foobar = 'somefunction';
$result = $someobject->${foobar}->value();
also works (i.e. it produces the expected result), but it also produces this warning:
Warning: Use of undefined constant foobar - assumed 'foobar' (this will throw an Error in a future version of PHP) …
Many thanks to all that commented. In particular Duc Nguyen and Swetank Poddar. I think it was the comment by Duc Nguyen in combination with the following comment by Swetank Poddar that finally cracked it.
I'am trying to call a public funtion of a class with variables(php7). Therfore I do:
$module = 'frontend\\modules\\rest\\models\\Member';
$action = 'view_profile'
$response = new $module();
$response = $response1->$action;
By calling $response1->$action I get the following error:
Undefined property: frontend\modules\rest\models\Member::$view_profile
I see that the systems try to call ...Member\$view_profile and this will not work. But why is the '$' before view_profile. I've tried several variantes, but the error with the $view_profile is always there. What is wrong with this approach?
Check out this other reply: OOP in PHP: Class-function from a variable? (cannot comment, sorry...)
Anyway, this is what you are after: http://php.net/manual/en/functions.variable-functions.php
<?php
class Foo
{
function Variable()
{
$name = 'Bar';
$this->$name(); // This calls the Bar() method
}
function Bar()
{
echo "This is Bar";
}
}
$foo = new Foo();
$funcname = "Variable";
$foo->$funcname(); // This calls $foo->Variable()
?>
So I guess the only thing missing is the "()" after
$response1->$action;
1.here's my wrong code
class classname{
function __construct(){};
public function test(){return 0;};
}
$c = new classname();
$test = $c->test;
var_dump($test); //out put NULL, I want the method $c->test
I didn't want to execute the function and store the result
there is something wrong with my code.
howto write it!
here's the code what I wanted(by Bobot):
$test = function() use ($c) { return $c->test(); };
devmyb's answer was helpful,and he/she told me why my codes not works
Bobot 、JezEmery 、devmyb ... etc
thanks for your help
You're not calling the function, you're trying to access a property (which isn't found).
$test = $c->test();
That should work.
Your question is unclear, but I guess you want to do this :
$test = function() use ($c) { return $c->test(); };
Then when you need to run your method, just run the function : $test();
I guess that some documentation about anonymous functions can help you to understand the code.
Its because you didn't have your error_reporting on else you'll get the notice, warning and fatal error too
You have typographical errors, check the updated code
class classname{
function __construct(){} // removed ;
public function test(){return 0;} // removed ;
}
$c = new classname();
$test = $c->test; // You were calling variable of your class
$test1 = $c->test(); // You were calling method of your class i.e. public function test()
var_dump($test);
var_dump($test1);
Output:
Notice: Undefined property: classname::$test in /in/HBNf9 on line 9
NULL
int(0)
This is the correct code. After a function is no ;
class classname {
function __construct(){
}
public function test() {
return 0;
}
}
$c = new classname();
$test = $c->test;
I'm trying to store anonymous functions in a static array property of my class. These functions should be invoked later by their index, but calling
self::$arr['index']()
just doesn't work, while
$a = self::$arr['index'];
$a();
does!
This doesn't work:
class A {
private static $func = array('a' => '');
public function __construct() {
self::$func['a'] = create_function('$str', 'echo "$str";');
}
public function go($str) {
self::$func['a']($str); // Call the function directly
}
}
$a = new A();
$a->go("hooray"); // Outputs "Undefined variable: func"
But this does:
class A {
private static $func = array('a' => '');
public function __construct() {
self::$func['a'] = create_function('$str', 'echo "$str";');
}
public function go($str) {
$a = self::$func['a']; // Pass the function name to a variable
$a($str); // Call the function via the variable
}
}
$a = new A();
$a->go("hooray"); // Outputs "hooray"
Why?
I'm using PHP Version 5.4.3
this is the behavior of php's parser
$functionName['a'] = "hello";
self::$functionName['a']();
calls
self::hello();
... the very sad thing is that in php you can't do this:
(self::$functionName['a'])(); // doesn't work in php :(
as you can do in javascript, for example
what you can do is... use a temporary variable like you said
$a = self::$func['a'];
$a($parameter);
or
call_user_func(self::$func['a'], $parameter);
hope this helps...
in latest phps these features were added
$a['sss'] = function(){ echo 'bla'; };
$a['sss']();
class Bla
{
private $a;
function test()
{
$this->a['sss'] = function(){ echo 'bla2'; };
$this->a['sss']();
}
}
$c = new Bla();
$c->test();
and they work properly... so for some reason, this syntax doesn't work only when using the scope resolution operator ( ClassName:: self:: etc)
Well, in php you simply can not do that, it is a php feature. But you can use call_user_func or its relatives:
return call_user_func(self::$func['$a'], $str);
This is a consequence of how the PHP parser currently works. Since the function call () is evaluated before the static operator ::, you end up with the parser attempting to reference the local variable $func instead, and then giving you the error about $func being undefined (which it is, since there is no variable named $func in the method).
As you've discovered, you can solve this by doing two separate statements.
Does PHP have something similar to C++ member pointers? I want to use a member of a PHP object, whose name (the member's, not the object's) I only know at runtime. For example:
$object = new stdClass();
$object->NewMember = "value";
$member = 'NewMember';
// I don't know whether this is valid PHP,
// but you get what I'm trying to do.
echo $object->$member;
<?php
class Test
{
public $foo = 'bar';
}
$var = 'foo';
$test = new Test();
echo $test->$var;
Edit: after your update, yes, that will work.
You can use variables in member calls.
$methodName = 'some_method';
$myObj->$methodName($param);
Not sure if this will work for what you want.
In the following code I'm setting the $memberToGet at runtime:
class Person
{
public $foo = 'default-foo';
public $bar = 'default-bar';
}
$p = new Person();
$memberToGet = 'foo';
print "The Person's $memberToGet is [" . $p->$memberToGet . "]\n";
$memberToGet = 'bar';
print "The Person's $memberToGet is [" . $p->$memberToGet . "]\n";
No, PHP doesn't support (member) pointers. However you could use Reflection API.
class MyClass {
public function doSth($arg1, $arg2) { ... }
public static function doSthElse($arg1) { ... }
}
$ref = new ReflectionMethod('MyClass', 'doSth');
$ref->invokeArgs(new MyClass(), array('arg1', 'arg2'));
$ref = new ReflectionMethod('MyClass', 'doSthElse');
$ref->invokeArgs(null, array('arg1'));
As you can see in other answers you could also write:
class MyClass { ... }
$method = 'doSth';
$obj = new MyClass();
$obj->$method('arg1', 'arg2');
But I really don't recommend that way. It's tricky, obscure and much harder to debug and maintain.
By passing $this as a variable by reference, you can access members of that class.