PHP - determine last function-call from chained function-calls - php

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;
}
}

Related

what is the best way for search in json file in php?

hi i have many data files in json format in a folder.
now i want to search a filed in them .my search word maybe not exist in some of them and may be exist in one of them files.
i have read this function and if not exits in a file i call the function to read another file.
when i echo the result show me and works fine but return not working and no data returned.
function get_shenavari_in_files($search,$type)
{
static $counter =1 ;
$darsadi = 0;
$find = false;
$file_name = get_files_in_dir(); // make an array of file names
$file_number = count($file_name)-$counter ;
$file="files/" .$file_name[$file_number];
$file_data = read_json($file);
for($i = 0 ; $i<count($file_data) ; $i++)
{
if($file_data[$i][$type] == $search )
{
$darsadi = $file_data[$i]['darsadi'] ;
$find = true;
echo $darsadi ; //this works and show the data
return $darsadi; // this is my problem no data return.
break;
}
}
if($find == false)
{
$counter ++;
get_shenavari_in_files($search,$type);
}
}
var_dump(get_shenavari_in_files('Euro','symbol')); //return null
Once you recurse into get_shenavari_in_files, any found value is never returned back to the inital caller, i.e. instead of
if($find == false)
{
...
get_shenavari_in_files($search,$type);
}
you simply need to prepend the function call with a returnstatement
if($find == false)
{
...
return get_shenavari_in_files($search,$type);
}
Having said that, I would try a much simpler (and thereby less error-prone) approach, e.g.:
function get_shenavari_in_files($search, $type) {
$files = glob("files/*.json"); // Get names of all JSON files in a given path
$matches = [];
foreach ($files as $file) {
$data = json_decode(file_get_contents($file), true);
foreach ($data as $row) {
if (array_key_exists($type, $row) && $row[$type] == $search) {
$matches[$file] = $search;
}
}
}
return $matches;
}
This way, you would be able to eliminate the need for a recursive call to get_shenavari_in_files. Also, the function itself would become more performant because it doesn't have to scan the file system over and over again.

Data Not Being Parsed Correctly

I have a simple data format that goes as follows:
stuff/stuff/stuff
An example would be:
data/test/hello/hello2
In order to retrieve a certain piece of data, one would use my parser, which tries to do the following:
In data/test/hello/hello2
You want to retrieve the data under data/test (which is hello). My parser's code is below:
function getData($data, $pattern)
{
$info = false;
$dataLineArray = explode("\n", $data);
foreach($dataLineArray as &$line)
{
if (strpos($line,$pattern) !== false) {
$lineArray = explode("/", $line);
$patternArray = explode("/", $pattern);
$iteration = 0;
foreach($lineArray as &$lineData)
{
if($patternArray[$iteration] == $lineData)
{
$iteration++;
}
else
{
$info = $lineData;
}
}
}
}
return $info;
}
However, it always seems to return the last item, which in this case is hello2:
echo getData("data/test/hello/hello2", "data/test");
Gives Me;
hello2
What am I doing wrong?
If you want the first element after the pattern, put break in the loop:
foreach($lineArray as $lineData)
{
if($patternArray[$iteration] == $lineData)
{
$iteration++;
}
elseif ($iteration == count($patternArray))
{
$info = $lineData;
break;
}
}
I also check $iteration == count($patternArray) so that it won't return intermediate elements, e.g.
/data/foo/test/hello/hello2
will return hello rather than foo.
P.S. There doesn't seem to be any reason to use references instead of ordinary variables in your loops, since you never assign to the reference variables.

Cannot return value from function

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.

Most efficient way to check if array element exists in string

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.

PHP: Trying to find a common matching text inside two separate string arrays. Main Idea: Making usergroups for a forum

The short description for this is that I have created my own forum. Everything works fantastic and I am quite impressed with it myself, being that I have been only studying PHP for 6 months. However, I am trying to make user groups function properly. Right now, I can assign one usergroup to a forum category and it all works fantastic. But again, I could only add one group to a forum. If I try and add more groups, this is where I have the trouble with my code.
First off, let me give you the working code I am using:
function checkgroupstat($group, $user) {
$findme = $group . ":";
$filestring = get_user_data($user, "groups");
$pos = strpos($filestring, $findme);
if ($pos === false) {
return "false";
} else {
return "true";
}
}
Just so you know, the "get_user_data() function will return a set of groups that the user belongs too. For instance, it will return 5:1;6:1;7:1 etc... The part that is important is the number before the colon and the colon itself, eg: 5:, but not 5:1. The one represents the priviledges the user has and is part of another coded page, so its not important here.
The "groups" string will return the group assigned to the forum. This code above works perfectly. If it returns true, the forum will be visible, otherwise it will return false.
However, I tried to make it so that it can have more than one group assigned to the forum and I used this code which does not work as intended:
function checkgroupstat($group, $user) {
$groups = explode(',', $group);
$filestring = get_user_data($user, "groups");
for ($i = 0; $i < count($groups); ++$i) {
$findme = $groups[$i] . ":";
$pos = strpos($filestring, $findme);
if ($pos === false) {
$false = "true";
}
else {
$truth = "true";
}
}
if ($truth == "true") {
return "true";
}
if ($truth == "") {
return "false";
}
}
I even tried using for each loop with break;
Any suggestions?
EDIT:
Suggestions below did not work. See my latest response which is:
The paramaters passed to checkgroupstat are: ("1,2,3", 6). The results returned from get_user_data() are 5:1;6:1;7:1;8:1;. Neither of these worked for me btw.
Are you trying the following? ;)
function checkgroupstat($group, $user) {
$groups = explode(',', $group);
$filestring = get_user_data($user, "groups");
// iterate over the group array
// return true if a group has matched
for ($i = 0; $i < count($groups); $i++) {
$findme = $groups[$i] . ":";
$pos = strpos($filestring, $findme);
if ($pos !== false) {
return "true";
}
}
// if no group has matched in the loop above
// we'll have to return false
return "false";
}
Hmmmm.... please give me the checkgroupstat() passed parameters, and the get_user_data() return string. I will write correct code.
From now I just write this:
function checkgroupstat($group, $user) {
$aUserGroups = get_user_data($user, "groups");
$aGroups = explode(',',$aUserGroups);
foreach($aGroups as $sGroup) {
list($iGroup,$iSomething) = explode(':',$sGroup);
if($group==$iGroup) {
return true;
}
}
return false;
}
Please - give me feedback if it work fine :)

Categories