The variable $id isn't in the scope of the function. You need to use the use clause to make external variables accessible:
$foo = array_filter($bar, function(
id) {
if (isset($obj->foo)) {
var_dump(
obj->foo == $id) return true;
}
return false;
});
See documentation for Anonymous functions (Example #3 "Inheriting variables from the parent scope").
Answer from Barmar on Stack OverflowThe variable $id isn't in the scope of the function. You need to use the use clause to make external variables accessible:
$foo = array_filter($bar, function(
id) {
if (isset($obj->foo)) {
var_dump(
obj->foo == $id) return true;
}
return false;
});
See documentation for Anonymous functions (Example #3 "Inheriting variables from the parent scope").
Variable scope issue!
Simple fix would be :
$id = '1';
var_dump(
foo = array_filter($bar, function($obj){
global $id;
if (isset($obj->foo)) {
var_dump(
obj->foo == $id) return true;
}
return false;
});
or, since PHP 5.3
$id = '1';
var_dump(
foo = array_filter($bar, function(
id) {
if (isset($obj->foo)) {
var_dump(
obj->foo == $id) return true;
}
return false;
});
Hope it helps
The scope of the variables inside an anonymous function is ONLY within the anonymous function.
You need to inherit the variable from the parent scope. You can find more details about it in the PHP Documentation about anonymous functions (Example #3)
which would transform this line:
$filtered = array_filter($json, function (
q) {
into this:
$filtered = array_filter($json, function (
q, $val) {
Add another variable in use:
$filtered = array_filter($json, function (
q, $key) {
if (stripos(
val], $q) !== false) {
return true;
} else {
return false;
}
});
EDIT:
One of good explanations can be found here: https://teamtreehouse.com/community/variable-functions-vs-php-closures
...the benefit of a lambda is that it exists only as long as the variable it is assigned to has a reference. So the way PHP manages memory is by reference counting. Essentially, the PHP engine reads all the files it needs in order to execute the program, and while doing so it finds all the variables used and keeps a tally of how many times they are used( reference count). While the script is being executed each time the variable is used it subtracts one from the reference count. Once the reference count hits zero, the variable is deleted (more or less). Normally, a function is loaded into memory and stays there for the entire execution of the script. However, a lambda can be deleted from memory once the reference count of its variable hits zero.
A closure on the other hand is an anonymous function that encapsulates a part of the global scope at the time it is created. In other words, you can pass a variable to a closure using the "use" keyword and that variable's value will be the same as it was when the closure was created regardless of what happen's outside the closure...
Basically use keyword is needed in order to created isolated scope for variables. Without it You wouldn't be able to inject any additional variable to the function.
Your $leagueKey variable is outside the scope of the anonymous function (closure). Luckily, PHP provides a very simple way to bring variables into scope - the use keyword. Try:
$leagueKey = 'NFL';
$response['response'] = array_filter($response['response'], function($tier) use ($leagueKey) {
return $tier['LeagueKey'] === $leagueKey;
});
This is just telling your anonymous function to "use" the $leagueKey variable from the current scope.
Edit
Exciting PHP 7.4 update - we can now use "short closures" to write functions that don't have their own scope. The example can now be written like this (in PHP 7.4):
$response['response'] = array_filter(
$response['response'],
fn($tier) => $tier['LeagueKey'] === $leagueKey
);
try this
$response['response'] = array_filter($response['response'], function($tier) use ($leagueKey) {
return ($tier['LeagueKey'] === $leagueKey ? true : false);
});
You have at least two options:
- Globalize the desired variable, and then reference it inside the callback
- Wrap the score calculation logic with a function, then reference it inside the callback
Globalize the Variable
<?php
global $score;
$score = 42; //Some crazy calculation I don't want to repeat.
function add_score_to_title($title) {
global $score;
return 'Quiz Results (' . $score . '/') - ' . $title;
}
add_filter( 'aioseop_title_single', 'add_score_to_title');
?>
Wrap the Score Calculation
If you only ever need the score calculation inside the filter, pull the logic into the callback itself:
<?php
function add_score_to_title($title) {
$score = 0;
$questions = get_quiz_result_questions();
$total_questions = 0;
foreach( $questions as $question ) {
$order = $question->order;
if( $order >= 100 ) {
break;
}
if( $question->correct == $_POST['Q'][$order] ) {
$score++;
}
$total_questions++;
return 'Quiz Results (' . $score . '/') - ' . $title;
}
add_filter( 'aioseop_title_single', 'add_score_to_title');
?>
Better yet, you could wrap your score calculation in a function of its own, and then call that function inside your callback:
<?php
function wpse48677_get_score() {
$score = 0;
$questions = get_quiz_result_questions();
$total_questions = 0;
foreach( $questions as $question ) {
$order = $question->order;
if( $order >= 100 ) {
break;
}
if( $question->correct == $_POST['Q'][$order] ) {
$score++;
}
$total_questions++;
$output['score'] = $score;
$output['total_questions'] = $total_questions;
return $output;
}
function add_score_to_title($title) {
$score_results = wpse48677_get_score();
$score = $score_results['score'];
return 'Quiz Results (' . $score . '/') - ' . $title;
}
add_filter( 'aioseop_title_single', 'add_score_to_title');
?>
If you find you have problems referencing the $_POST object, you can also register your query variable and then use get_query_var() internally to get data:
function add_score_query_vars( $query_vars ) {
$query_vars[] = 'Q';
return $query_vars;
}
add_filter( 'query_vars', 'add_score_query_vars' );
With this in place, $_POST['Q'] can be replaced with get_query_var('Q').
function add_score_to_title($title = false) {
static $score = false;
if($score === false){
// do calc
}
// plugin call (filter)
if($title !== false)
return 'Quiz Results (' . $score . ') - ' . $title;
// your call
return $score;
}
Call the function anywhere in your script to get the score, it will only be calculated once.
Another way, using anonymous functions:
// do the calc
$score = 'xxx';
add_filter('aioseop_title_single', function($title) use($score){
return 'Quiz Results (' . $score . ') - ' . $title;
});
Let's use array_map() to explain what's going on.
We want to duplicate the input of an array: so if the input is aa, the output would be aaaa.
So the normal way, would be to create a function and then pass it to array_map():
$array = range('a', 'e');
$new_array = array_map('duplicate', $array);
print_r($new_array);
function duplicate($string){
return $string.$string;
}
Online demo
But what if you want to use this function only once ? Since PHP 5.3, there is something called anonymous functions, we use it like the following:
$array = range('a', 'e');
$new_array = array_map(function($string){
return $string.$string;
}, $array);
print_r($new_array);
Online demo
Now, let's say for example you want to add a standard value from another variable. That's easy with global variables. But as we know, global variables are evil and should be avoided. We may use use():
$array = range('a', 'e');
$standard_value = ',';
$new_array = array_map(function($string)use($standard_value){
// $standard_value becomes available inside the function
return $string.$standard_value.$string;
}, $array);
print_r($new_array);
Online demo
use() can be become also useful if we use a reference to write to an external variable while looping:
$array = range('a', 'e');
$another_string = '';
$new_array = array_map(function($string)use(&$another_string){// note &
$another_string .= $string.$string; // overwrite $another_string
return $string.$string;
}, $array);
print_r($new_array);
echo PHP_EOL . $another_string;
Online demo
the $e variable acts as a normal function parameter, and will thus be passed by the code calling the function, see the documentation for the value of $e when using array_filter.
The use statement imports variables from the local scope into the anonymous' function's scope.
$myvar = 'world';
$myFunc = function ($test) use ($myvar) {
return $test . ' ' . $myvar;
};
echo $myFunc('hello'); // echoes 'hello world';
If you did not include the use ($myvar) part, then isset($myvar) would return false from inside the anonymous function, since it has a separate scope.