What's the alternative to using global variables in a callback function? - php

I have used PHP for a very long time, but not really used callbacks very much until quite recently. In the following code, the callback (the example is QueryPath, in case you're wondering, but it could be anything that accepts a callback) will add some link to an array:
// parse any product links out of the html
$aProducts = array();
qp( $html, 'a' )->each(function($index, $element){
global $aProducts;
$link = qp($element)->attr('href');
$pregMatch = preg_match('#(.*)-p-(.*)\.html#i', $link, $matches);
if( $pregMatch ) {
$product_id = (int)$matches[2];
if( !in_array($product_id, $aProducts) ) {
$aProducts[] = $product_id;
}
}
});
// print out our product array
print_r( $aProducts );
What's the alternative to using global $aProducts (if there is one)?

use use:
qp( $html, 'a' )->each(function($index, $element) use(&$aProducts) {
Note the &. This is needed, for otherwise you would be using a copy of the array. You can also use multiply values, just list them separated with a ,. E.g: use(&$aProducts, $someObj, &$someInt)
PHP.net: http://www.php.net/manual/en/language.namespaces.importing.php

I Recommend you To Don't Use global variable, instead put your code on a Class and Use $this instead global variable. it must Work

Related

How to check the session variable contains some specific value

I could retrieve my session variable which represents access locations as follows,
$_SESSION['access']
This session variable contains some strings as follows,
dummy1,dummy2,dummy3,dummy4
As an example $_SESSION['access'] can be dummy1 or dummy1,dummy2 or dummy1,dummy2,dummy3 or dummy2,dummy3,dummy4 likewise. Are there any method to find contains type of function?
Ex:
if($_SESSION['access']`.contains("dummy1")){
//do somthing,
}
Or do I need to use mysql function to retrieve what I need?
Not a method but function - as string is not an object in PHP.
The function is called str_contains.
Use it like this on your example:
if (str_contains($_SESSION['access'], "dummy1")) {
//do somthing,
}
The function is part of the language only recently (needs PHP 8).
For older PHP versions strstr was often used for this purpose (it also returns a substring of the original string, but only in case it is contained - which is exactly what we need here).
One would do so like this:
if (strstr($_SESSION['access'], "dummy1")) {
//do somthing,
}
This may be a bit more verbose, but works:
if ( array_key_exists( "access", $_SESSION ) ) {
$arrVals = explode( ',', $_SESSION["access"]) ;
$key = "dummy1" ; // doesn't have to be hard-coded here, just for demo
$b = array_search( $key, $arrVals ) ;
if ( $b !== false ) {
/// do your thing
echo ( "found $key<br/>") ;
}
}

How to concatenate variable in drupal

I want to know how can I concatenate [und][0][value].
I don't want to write every time [und][0][value]. So I have do like this:
<?php
$und_value = $load->field_testimonial_location['und'][0]['value'];
$query = db_select('node','n');
$query->fields('n',array('nid'));
$query->condition('n.type','testimonial','=');
$result = $testimonial_query->execute();
while($fetch = $result->fetchObject()){
$load = node_load($fetch->nid);
// $location = $load->field_testimonial_location['und'][0]['value'];
$location = $load->field_testimonial_location.$und_value;
echo $location;
}
But its not working. It outputs Array Array So have any idia for this problem? How can I do? Full code here
Why don't you make some function which will take node field as parameter and return it's value
function field_value($field){
return $field['und'][0]['value'];
}
Something like that (not tested).
But if you don't want to use function try using curly braces like:
$location = $load->{field_testimonial_location.$und_value};
That should work...
Extending answer posted by MilanG, to make function more generic
function field_value($field, $index = 0 ){
return $field['und'][$index]['value'];
}
There are time when you have multi value fields, in that case you have to pass index of the value also. For example
$field['und'][3]['value'];
Please do not use such abbreviations, they will not suit all cases and eventually break your code.
Instead, there is already a tool do create custom code with easier syntax: Entity Metadata Wrapper.
Basically, instead of
$node = node_load($nid);
$field_value = $node->field_name['und'][0]['value'];
you can then do something like
$node = node_load($nid);
$node_wrapper = entity_metadata_wrapper('node', $node);
$field_value = $node_wrapper->field_name->value();
With the node wrapper you can also set values of a node, it's way easier and even works in multilingual environments, no need to get the language first ($node->language) or use constants (LANGUAGE_NONE).
In my custom module, I often use $node for the node object and $enode for the wrapper object. It's equally short and still know which object I am working on.

Accessing parent function scope from anonymous function in PHP

I made this awesome plugin for wordpress to easily add references to blog posts using latex-like tags. It works really well, but there's one nasty detail: I'm using global variables, as I need to change a variable in an anonymous function of which I can't change the passed parameters (it's a callback function).
I tried the use syntax and it works but the variable gets copied into the anonymous function.
Here's the code, shortened to give a quick overview of what I want to do:
// Global variables, ugh...
// I don't want to declare $reflist here!
$reflist = array();
// Implementation of reference parsing.
function parse_references( $str ) {
// Clear array
$reflist = array();
// I want to declare $reflist here!
// Replace all tags
$newstr = preg_replace_callback( "/{.*}/",
function ( $matches ) {
// Find out the tag number to substitute
$tag_number = 5;
// Add to $reflist array
global $reflist;
// I don't want to have to use a global here!
$reflist[] = $tag_number;
return "[$tag_number]";
}, $str );
return $newstr;
}
So does anyone know how to solve this elegantly?
Pass the variable by reference with the use construct. This way, modifying the value of $reflist inside the anonymous function does have an external effect, meaning the original variable's value changes.
$newstr = preg_replace_callback("/{.*}/", function($matches) use (&$reflist) {
$tag_number = 5; // important ----^
$reflist[] = $tag_number;
return "[$tag_number]";
}, $a);

passing indefinite number of arguments to function without using an array

I am having situation where i want to pass variables in php function.
The number of arguments are indefinite. I have to pass in the function without using the array.
Just like normal approach. Comma Separated.
like test(argum1,argum2,argum3.....,..,,.,.,.....);
How i will call the function? Suppose i have an array array(1,2,3,4,5) containing 5 parameters. i want to call the function like func(1,2,3,4,5) . But the question is that, How i will run the loop of arguments , When calling the function. I tried func(implode(',',array)); But it is taking all return string as a one parameters
In the definition, I also want the same format.
I can pass variable number of arguments via array but i have to pass comma separated.
I have to pass comma separated. But at the time of passing i don't know the number of arguments , They are in array.
At the calling side, use call_user_func_array.
Inside the function, use func_get_args.
Since this way you're just turning an array into arguments into an array, I doubt the wisdom of this though. Either function is fine if you have an unknown number of parameters either when calling or receiving. If it's dynamic on both ends, why not just pass the array directly?!
you can use :
$function_args = func_get_args();
inside your test() function definition .
You can just define your function as
function test ()
then use the func_get_args function in php.
Then you can deal with the arguments as an array.
Example
function reverseConcat(){
return implode (" ", array_reverse(func_get_args()));
}
echo reverseConcat("World", "Hello"); // echos Hello World
If you truely want to deal with them as though they where named parameters you could do something like this.
function getDistance(){
$params = array("x1", "y1", "x2", "y2");
$args = func_get_args();
// trim excess params
if (count($args) > count($params) {
$args = array_slice(0, count($params));
} elseif (count($args) < count($params)){
// define missing parameters as empty string
$args = array_pad($args, count($params), "");
}
extract (array_combine($params, $args));
return sqrt(pow(abs($x1-$x2),2) + pow(abs($y1-$y2),2));
}
use this function:
function test() {
$args = func_get_args();
foreach ($args as $arg) {
echo "Arg: $arg\n";
}
}
I'm not sure what you mean by "same format." Do you mean same type, like they all have to be a string? Or do you mean they need to all have to meet some criteria, like if it's a list of phone numbers they need to be (ddd) ddd-dddd?
If it's the latter, you'll have just as much trouble with pre-defined arguments, so I'll assume you mean you want them all to be the same type.
So, going off of the already suggested solution of using func_get_args(), I would also apply array_filter() to ensure the type:
function set_names() {
function string_only($arg) {
return(is_string($arg));
}
$names_provided = func_get_args();
// Now you have an array of the args provided
$names_provided_clean = array_filter($names_provided, "string_only");
// This pulls out any non-string args
$names = array_values($names_provided_clean);
// Because array_filter doesn't reindex, this will reset numbering for array.
foreach($names as $name) {
echo $name;
echo PHP_EOL;
}
}
set_names("Joe", "Bill", 45, array(1,2,3), "Jane");
Notice that I don't do any deeper sanity-checks, so there could be issues if no values are passed in, etc.
You can use array also using explode http://www.php.net/manual/en/function.explode.php.
$separator = ",";
$prepareArray = explode ( $separator , '$argum1,$argum2,$argum3');
but be careful, $argum1,$argum2, etc should not contain , in value. You can overcome this by adding any separator. $separator = "VeryUniqueSeparator";
I don't have code so can't tell exact code. But manipulating this will work as your requirements.

adding the use of multiple variables to an ob_start function

I've got the following object start code; however, right now it only uses 1 variable ( $online ) .... I need to add a second variable ( $var2 ) to the code so that I can have "var2"=> $var2 under "online"=> $online. This needs to be added to the first line of code around where use (&$online) so the code knows the use this variable.
ob_start(function($c) use (&$online){
$replacements = array(
"online"=> $online
);
return preg_replace_callback("/{(\w+)}/",function($m) use ($replacements) {
return isset($replacements[$m[1]]) ? $replacements[$m[1]] : $m[0];
},$c);
});
How do I add this? Everything I try breaks the code completely.
You can add as many variables to a use as you like, just separate them as you would parameters:
function($c) use (&$online,&$var2)
Following the php documentation on closures, you should use commas. Following the php documentation on arrays, you should also use commas there. Next time try looking it up. The php manual has lots of resources on this subject.
ob_start( function($c) use (&$online, &$var2){
$replacements = array(
"online"=> $online,
"var2" => $var2,
);
// ...

Categories