The code:
public function couts_complets($chantier,$ponderation=100){
function ponderation($n)
{
return($n*$ponderation/100); //this is line 86
}
...
}
What I'm trying to do: to declare a function B inside a function A in order to use it as a parameter in
array_map().
My problem: I get an error:
Undefined variable: ponderation [APP\Model\Application.php, line 86]
Try this:
public function couts_complets($chantier,$ponderation=100){
$ponderationfunc = function($n) use ($ponderation)
{
return($n*$ponderation/100);
}
...
$ponderationfunc(123);
}
As of php 5.3 you can use anonymous functions. Your code would look like this (untested code warning):
public function couts_complets($chantier,$ponderation=100) {
array_map($chantier, function ($n) use ($ponderation) {
return($n*$ponderation/100); //this is line 86
}
}
In your current code, $ponderation is not covered by the scope of the function, hence the "undefined" error.
To pass a variable to an "internal" function, use the use statement.
function ponderation($n) use($ponderation) {
Using a callback function:
In order to use a function as a parameter in PHP it is enough to pass the function's name as a string as such:
array_map('my_function_name', $my_array);
If the function is actually a static method in a class you can pass it as a parameter as such:
array_map(array('my_class_name', 'my_method_name'), $my_array);
If the function is actually a non-static method in a class you can pass it as a parameter as such:
array_map(array($my_object, 'my_method_name'), $my_array);
Declaring a callback function:
If you declare in the global space all is good and clear in the world - for everybody.
If you declare it inside another function it will be global but it won't be defined until the parent function runs for the first time and it will trigger an error Cannot redefine function my_callback_function if you run the parent function again.
If you declare it as a lambda function / anonymous function you will need to specify which of the upper level scope variables it is allowed to see/use.
Calling a callback:
function my_api_function($callback_function) {
// PHP 5.4:
$callback_function($parameter1, $parameter2);
// PHP < 5.3:
if(is_string($callback_function)) {
$callback_function($parameter1, $parameter2);
}
if(is_array($callback_function)) {
call_user_func_array($callback_function, array($parameter1, $parameter2));
}
}
Related
How can we declare the function name dynamically?
For example :
$function = 'test'
public $function(){
}
You could use a callback for this:
https://stackoverflow.com/a/2523807/3887342
function doIt($callback) { $callback(); }
doIt(function() {
// this will be done
});
Declaring a function with a variable but arbitrary name like this is not possible without getting your hands dirty with eval() or include().
I think based on what you're trying to do, you'll want to store an anonymous function in that variable instead (use create_function() if you're not on PHP 5.3+):
$variableA = function() {
// Do stuff
};
You can still call it as you would any variable function, like so:
$variableA();
Say I'm here:
class Foo
{
public function test()
{
// I'm here!
}
private function pow() {}
}
I want to declare a local variable that references the method $this->pow. I try:
$pow = $this->pow;
This doesn't work:
Notice: Undefined property: Foo::$pow
How do I reference a class instance method in PHP?
I need this because I need to pass the function to an anonymous function inside test. I can't pass $this to the anonymous function because I'm using PHP 5.3, and that only became possible in PHP 5.4. Also, the function pow is not public, so I can't assign $this to an intermediary variable and pass that to the anonymous function.
If pow is public as it is in your example, then you can simply do this:
$self = $this;
$invokePow = function() use ($self) { $self->pow(); };
// ... some time later ...
$invokePow(); // calls pow()
You can also do the same by passing around array($this, 'pow') as a callable and invoking it with call_user_func.
If pow is not public, you are simply out of luck.
However, if you are able to upgrade to 5.4 then it all becomes much easier:
$invokePow = function() { $this->pow(); };
You don't need to capture $this explicitly, and you can invoke $invokePow from any context (even outside the class).
Consider the following code, which is a scheme of storing a callback function as a member, and then using it:
class MyClass {
function __construct($callback) {
$this->callback = $callback;
}
function makeCall() {
return $this->callback();
}
}
function myFunc() {
return 'myFunc was here';
}
$o = new MyClass(myFunc);
echo $o->makeCall();
I would expect myFunc was here to be echoed, but instead I get:
Call to undefined method MyClass::callback()
Can anyone explain what's wrong here, and what I can do in order to get the desired behaviour?
In case it matters, I am using PHP 5.3.13.
You can change your makeCall method to this:
function makeCall() {
$func = $this->callback;
return $func();
}
Pass it as a string and call it by call_user_func.
class MyClass {
function __construct($callback) {
$this->callback = $callback;
}
function makeCall() {
return call_user_func($this->callback);
}
}
function myFunc() {
return 'myFunc was here';
}
$o = new MyClass("myFunc");
echo $o->makeCall();
One important thing about PHP is that it recognises the type of a symbol with the syntax rather than the contents of it, so you need to state explicitly what you refer to.
In many languages you just write:
myVariable
myFunction
myConstant
myClass
myClass.myStaticMethod
myObject.myMethod
And the parser/compiler knows what each of the symbols means, because it's aware of what they refer to simply by knowing what's assigned to them.
In PHP, however, you need to use the syntax to let the parser know what "symbol namespace" you refer to, so normally you write:
$myVariable
myFunction()
myConstant
new myClass
myClass::myStaticMethod()
$myObject->method()
However, as you can see these are calls rather than references. To pass a reference to a function, class or method in PHP, combined string and array syntax is used:
'myFunction'
array('myClass', 'myStaticMethod')
array($myObject, 'myMethod')
In your case, you need to use 'myFunc' in place of myFunc to let PHP know that you're passing a reference to a function and not retrieving the value the myFunc constant.
Another ramification is that when you write $myObject->callback(), PHP assumes callback is a method because of the parentheses and it does not attempt to loop up a property.
To achieve the expected result, you need to either store a copy of/reference to the property callback in a local variable and use the following syntax:
$callback = $this->callback;
return $callback();
which identifies it as a closure, because of the dollar sign and the parentheses; or call it with the call_user_func function:
call_user_func($this->callback);
which, on the other hand, is a built-in function that expects callback.
here is an example class:
public class example
{
private $foof;
public function __construct()
{
$this->foof = $this->foo;
}
public function foo($val=0)
{
// do something...
}
}
So basically, in the constructer of the sample code, is it possible to assign a class method to a variable?
Ultimately what i want is to have an associative array with all the class methods aliased in it...that possible in php?
In PHP5.3+ (which you should be using anyway!) you can simply create an anonymous function which calls your method:
$this->foof = function() {
$this->foo(1);
};
However, you cannot call it using $this->foof() - you have to assign it to a variable first: $foof = $this->foof; $foof();
In older PHP versions you cannot easily do this - create_function() does not create a closure so $this is not available there.
You don't need to use anonymous functions. Just use the Callable pseudo type.
$this->foof = array($this, 'foo');
...
call_user_func($this->foof);
I'm trying to pass a parameter from a parent function to a child function while keeping the child function parameterless. I tried the following but it doesn't seem to work.
public static function parent($param)
{
function child()
{
global $param;
print($param) // prints nothing
}
}
You can use lambda functions from PHP 5.3 and on:
public static function parent($param) {
$child = function($param) {
print($param);
}
$child($param);
}
If you need to do it with earlier versions of PHP try create_function.
I think that the global you call in child() does not refer to that scope. Try running it with really global variable.
The right way to do this there would be to create an anonymous function inside your parent function, and then use the ''use'' keyword.
public static function parent($params) {
function() use ($params) {
print($params);
}
}
https://www.php.net/manual/en/functions.anonymous.php