I have a PHP function:
function unserialize_recursive($data, $i = 0) {
$unserialized = unserialize($data);
if ($unserialized) {
$i++;
}
if (!is_string($unserialized) || unserialize($unserialized) === FALSE) {
/* placeholder - see explanation below */
return array($i, $unserialized);
} elseif (unserialize($unserialized) !== FALSE) {
unserialize_recursive($unserialized, $i);
}
return FALSE;
}
I call this function with:
$data = unserialize_recursive($serialized_string);
var_dump($data);
But the output of var_dump($data) is bool(false).
However, if I add var_dump($unserialized) in the position of the text /* placeholder - see explanation below */, I get the expected output.
So why can I not return that variable ($unserialized)? If I use gettype() on it at that point in the function, it returns array.
I'm using Netbeans and all the syntax highlighting indicates the code is properly formed with no typos. I'm baffled. Have I missed something really obvious?
My guess is that you forgot a return:
function unserialize_recursive($data, $i = 0) {
$unserialized = unserialize($data);
if ($unserialized) {
$i++;
}
if (!is_string($unserialized) || unserialize($unserialized) === FALSE) {
/* placeholder - see explanation below */
return array($i, $unserialized);
} elseif (unserialize($unserialized) !== FALSE) {
return unserialize_recursive($unserialized, $i);
}
return FALSE;
}
You use recursion in your function.
So your var_dump($unserialized) is called from a recursed invocation, but main invocation returns false.
You probably need to change "unserialize_recursive($unserialized, $i);" to
return unserialize_recursive($unserialized, $i);
You are missing return in front of
unserialize_recursive($unserialized, $i);
So it should be like this
return unserialize_recursive($unserialized, $i);
Without return function would run itself but then leave if condition and execute return FALSE. By placing return in front you end the current function and start another one.
Related
I'm having a trouble. I was trying to make it work for a long time, so I decided to ask for help here.
I have an with some arrays inside it:
$myarray = [
['string1','string2'],
['string3','string4'],
['string5',['string6','string7','string99']],
['string8','string9']
];
I am making a function that search for a s
function searchArray($array,$chave,$id) {
foreach ($array as $key) {
if (is_array($key)) {
if (($key[0] == $chave) && ($key[1] == $id)) {
break;
}
else {
searchArray($key,$chave,$id);
}
}
}
return $key;
}
$result = searchArray($myarray,'string6','string7');
print_r($result);
It was supposed to print ['string6','string7','string99']]
But it it printing the last "key" of the array: ['string8','string9']
The break is not working. After the break, it continue checking the next arrays.
with these modification it returns the expected values:
<?php
$myarray = [
['string1','string2'],
['string3','string4'],
['string5',['string6','string7','string99']],
['string8','string9']
];
function searchArray($array,$chave,$id) {
foreach ($array as $key) {
if (is_array($key)) {
if (($key[0] == $chave) && ($key[1] == $id)) {
return $key;
} else {
$res = searchArray($key,$chave,$id);
if($res !== false) {
return $res;
}
}
}
}
return false;
}
$result = searchArray($myarray,'string6','string7');
print_r($result);
the failure was to break on success. That makes no sense.
You need to return the value on success. If no success return false. Imagine it may happen that the searched values will not been found so it should return false.
I've been looking for a way to check if any of an array of values exists in a string, but it seems that PHP has no native way of doing this, so I've come up with the below.
My question - is there a better way of doing this, as this seems pretty inefficient? Thanks.
$match_found = false;
$referer = wp_get_referer();
$valid_referers = array(
'dd-options',
'dd-options-footer',
'dd-options-offices'
);
/** Loop through all referers looking for a match */
foreach($valid_referers as $string) :
$referer_valid = strstr($referer, $string);
if($referer_valid !== false) :
$match_found = true;
continue;
endif;
endforeach;
/** If there were no matches, exit the function */
if(!$match_found) :
return false;
endif;
Try with following function:
function contains($input, array $referers)
{
foreach($referers as $referer) {
if (stripos($input,$referer) !== false) {
return true;
}
}
return false;
}
if ( contains($referer, $valid_referers) ) {
// contains
}
What about this:
$exists = true;
array_walk($my_array, function($item, $key) {
$exists &= (strpos($my_string, $item) !== FALSE);
});
var_dump($exists);
This will check if any of the array values exists in the string. If only one is missing, You are given a false response. Should You need to find out which one are not present in the string, try this:
$exists = true;
$not_present = array();
array_walk($my_array, function($item, $key) {
if(strpos($my_string, $item) === FALSE) {
$not_present[] = $item;
$exists &= false;
} else {
$exists &= true;
}
});
var_dump($exists);
var_dump($not_present);
First of, alternate syntax is nice to use, but historically it's used in template files. Since it's structure is easily readable while coupling/decouping the PHP interpreter to interpolate HTML data.
Second, it's generally wise if all your code does is to check something, to immediately return if that condition is met:
$match_found = false;
$referer = wp_get_referer();
$valid_referers = array(
'dd-options',
'dd-options-footer',
'dd-options-offices'
);
/** Loop through all referers looking for a match */
foreach($valid_referers as $string) :
$referer_valid = strstr($referer, $string);
if($referer_valid !== false) :
$match_found = true;
break; // break here. You already know other values will not change the outcome
endif;
endforeach;
/** If there were no matches, exit the function */
if(!$match_found) :
return false;
endif;
// if you don't do anything after this return, it's identical to doing return $match_found
Now as specified by some of the other posts in this thread. PHP has a number of functions that can help. Here's a couple more:
in_array($referer, $valid_referers);// returns true/false on match
$valid_referers = array(
'dd-options' => true,
'dd-options-footer' => true,
'dd-options-offices' => true
);// remapped to a dictionary instead of a standard array
isset($valid_referers[$referer]);// returns true/false on match
Ask if you have any questions.
I'm sure this is an easy solution - I wrote found this endswith function and thought I'd try the array_walk function instead of testing each string separately. I'd assumed that the result of the array_walk function would be false but it returns 1...How do I get it to test all the strings and return false if it didn't find a match? Thanks
class {
function endsWith($value,$key,$haystack)
{
$length = strlen($value);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $value);
}
function thing()
{
$email = "should#returnfalse.info";
$arr = array("#test.net","#test.org.uk","#test.co.uk","#test.com");
echo array_walk($arr,array($this,"endsWith"),$email);
}
}
The return value of array_walk is not determined by whatever the callback does; it only informs you if walking the entire array was completed successfully.
You may want to look into a few alternatives.
This will return the number of matching elements and will also serve as a boolean test, but it will evaluate every element no matter what:
echo count(array_filter($arr,array($this,"endsWith")));
This will stop evaluating elements with endsWith as soon as a match is detected and will return true if there is a match, false otherwise:
$self = $this;
// cast to int because false is printed as the empty string
echo (int)array_reduce($arr,
function($result, $v) use ($email, $self) {
return $result || $self->endsWith($v, null, $email);
},
false);
Try this
class {
function thing()
{
$email = "should#returnfalse.info";
$arr = array("#test.net","#test.org.uk","#test.co.uk","#test.com");
foreach ($arr as $domain) {
$length = strlen($value);
if ($length != 0) {
if (substr($email, -$length) === $domain) { echo $domain; break; }
}
}
}
}
array_walk() just iterates over the elements of an array and returns true, if it was able to do it. (echo casts boolea true to a string '1') Have a look at array_recude()
$that = $this; // Cannot access $this directly before PHP 5.4
var_dump(
array_reduce (
$arr,
function($result, item) use ($email, $that) { return $result || $that->endsWith($item, null /* not used anyway */, $email);},
false
)
);
Additional $key is not used and useless in endsWith().
If you want to apply a function to all values and return a single result you should use array_reduce.
As of PHP 5.3, you can use anonymous functions:
class {
function thing()
{
$email = "should#returnfalse.info";
$arr = array("#test.net","#test.org.uk","#test.co.uk","#test.com");
$match = '';
$found = false;
array_walk($arr,function($value) use (&$match, &$found, $email) {
$length = strlen($value);
if ($length == 0) {
$found = true;
return;
}
if (substr($email, -$length) === $value) {
$match = $value;
$found = true;
}
});
if ($found) {
echo 'Found match: ' . $match;
} else {
echo 'No match found :(';
}
}
}
When using chained functions, is there a way to determine if the current call is the last in the chain?
For example:
$oObject->first()->second()->third();
I want to check in first, second and third if the call is the last in the chain so it saves me to write a result-like function to always add to the chain. In this example the check should result true in third.
No, not in any way that's sane or maintainable.
You'll have to add a done() method or similar.
As far as i know it's impossible, i'd suggest to use finishing method like this:
$oObject->first()
->second()
->third()
->end(); // like this
If you want to execute a function on the last chain (without addional exec or done on the chain).
The code below will obtain the full chain from the source code and return the data after the last chain.
<?php
$abc = new Methods;
echo($abc->minus(12)->plus(32)); // output: -12+32
echo(
$abc->plus(84)
->minus(63)
); // output: +84-63
class Methods{
private $data = '';
private $chains = false;
public function minus($val){
$this->data .= '-'.$val;
return $this->exec('minus');
}
public function plus($val){
$this->data .= '+'.$val;
return $this->exec('plus');
}
private function exec($from){
// Check if this is the first chain
if($this->chains === false){
$this->getChains();
}
// Remove the first chain as it's
// already being called
if($this->chains[0] === $from){
array_shift($this->chains);
}
else
die("Can't parse your chain");
// Check if this is the last chain
if(count($this->chains) === 0){
$copy = $this->data;
// Clear data
$this->chains = false;
$this->data = '';
return $copy;
}
// If not then continue the chain
return $this;
}
private function getChains(){
$temp = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// Find out who called the function
for ($i=0; $i < count($temp); $i++) {
if($temp[$i]['function'] === 'exec'){
$temp = $temp[$i + 1];
break;
}
}
// Prepare variable
$obtained = '';
$current = 1;
// Open that source and find the chain
$handle = fopen($temp['file'], "r");
if(!$handle) return false;
while(($text = fgets($handle)) !== false){
if($current >= $temp['line']){
$obtained .= $text;
// Find break
if(strrpos($text, ';') !== false)
break;
}
$current++;
}
fclose($handle);
preg_match_all('/>(\w.*?)\(/', $obtained, $matches);
$this->chains = $matches[1];
return true;
}
}
I have an issue here with filter_array.
below is my code:
$array = array("0","0","1");
function returnzero($d){
if($d=='0'){
return $d;
}
}
$all_zeros = array_filter($array, "returnzero");
echo count($all_zeros);
I would like to filter out all values that none other than zero.
Above is my code. However, the count result returned is always 0.
may I know what is my mistake?
Thanks.
See the documentation on array_filter
You need to be returning true or false, not the number... So your function becomes:
function returnzero($d) { return $d == 0; }
You need to check $d != 0 and it will return all the non-zero values. Trying to return 0 is the same as returning false, so it fails.
Function must returns TRUE.
$array = array(0, 0, 1);
function returnzero($d){
if($d=='0'){
return true;
}
}
$all_zeros = array_filter($array, "returnzero");
echo count ($all_zeros);
Modify the return value to reflect the purpose:
function iszero($d) { return $d == '0'; }
$all_zeros = array_filter($array, 'iszero');
Regards
rbo
The function you pass into array_filter() must return TRUE or FALSE to tell PHP whether the current value being checked matches what you're filtering for. You're returning the number that was passed in. Since you're checking for zeroes, you're returning zero, which PHP interprets as FALSE. You could rewrite the function as follows:
if ($d == 0) {
return TRUE;
} else {
return FALSE;
}
or more concisely
return ($d == 0);