I have array of arrays - tree structure of main menu.
I try to find in this tree one node with needed slug and return this node with all it's childs.
I write little recurcive function
<?php
$tree = '[{"id":1,"structure":1,"parent":0,"slug":"medicinskaya-ge","child":{"2":{"id":2,"structure":1.1,"parent":1,"slug":"dnk-diagnostika","child":{"3":{"id":3,"structure":"1.1.1","parent":2,"slug":"dnk-diagnostika","datafile":"ssz","template":"ssz"},"4":{"id":4,"structure":"1.1.2","parent":2,"slug":"dnk-diagnostika","child":{"5":{"id":5,"structure":"1.1.2.1","parent":4,"slug":"dnk-diagnostika"},"6":{"id":6,"structure":"1.1.2.2","parent":4,"slug":"testirovanie-ge"},"7":{"id":7,"structure":"1.1.2.3","parent":4,"slug":"dnk-diagnostika"}}},"8":{"id":8,"structure":"1.1.3","parent":2,"slug":"dnk-diagnostika"},"9":{"id":9,"structure":"1.1.4","parent":2,"slug":"texnologiya-kol"}}}}}]';
$tree = json_decode($tree, true);
function getSlugData(string $slug, array $data)
{
foreach ($data as $row) {
if ($row['slug'] == $slug) {
return $row;
}
if (isset($row['child'])) {
//return $this->getSlugData($slug, $row['child']);
}
}
return [];
}
$result = getSlugData('testirovanie-ge', $tree);
print_r($result);
But as a result I have an empty array. If I print_r($row) when $row['slug'] == $slug - It appears on screen.
if ($row['slug'] == $slug) {
exit(print_r($row));
return $row;
}
What's my mistake?
In programming, recursion is a useful and powerful mechanism that allows a function to call itself directly or indirectly, that is, a function is said to be recursive if it contains at least one explicit or implicit call to itself.
I modified your code a bit and got the solution below.
$tree = '[{"id":1,"structure":1,"parent":0,"slug":"medicinskaya-ge","child":{"2":{"id":2,"structure":1.1,"parent":1,"slug":"dnk-diagnostika","child":{"3":{"id":3,"structure":"1.1.1","parent":2,"slug":"dnk-diagnostika","datafile":"ssz","template":"ssz"},"4":{"id":4,"structure":"1.1.2","parent":2,"slug":"dnk-diagnostika","child":{"5":{"id":5,"structure":"1.1.2.1","parent":4,"slug":"dnk-diagnostika"},"6":{"id":6,"structure":"1.1.2.2","parent":4,"slug":"testirovanie-ge"},"7":{"id":7,"structure":"1.1.2.3","parent":4,"slug":"dnk-diagnostika"}}},"8":{"id":8,"structure":"1.1.3","parent":2,"slug":"dnk-diagnostika"},"9":{"id":9,"structure":"1.1.4","parent":2,"slug":"texnologiya-kol"}}}}}]';
$tree = json_decode($tree, true);
//print_r($tree);
//die();
function getSlugData(string $slug, array $data, string $key = 'slug')
{
$result = [];
foreach ($data as $row) {
// Checks if the key exists and is the desired value for that key in the array
if (isset($row[$key]) && $row[$key] === $slug) {
return $row;
}
// If it is an array, apply recursion by calling getSlugData again
if (is_array($row)) {
$result = getSlugData($slug, $row, $key);
if ($result !== []) {
return $result;
}
}
}
return $result;
}
print_r(getSlugData('testirovanie-ge', $tree));
print_r(getSlugData('texnologiya-kol', $tree));
print_r(getSlugData('nothing-here', $tree));
die();
In the recursive function, you must not break the loop early unless you find your slug match. If a non-slug-match has a child element, you must iterate it and potentially pass up a match in subsequent recursive calls.
Code: (Demo)
function getSlugData(string $slug, array $data): array
{
foreach ($data as $row) {
if ($row['slug'] === $slug) {
return $row;
}
if (isset($row['child'])) {
$deeper = getSlugData($slug, $row['child']);
if ($deeper) {
return $deeper;
}
}
}
return [];
}
P.s. you aren't calling a class method, so $this-> is inappropriate.
I have a function which contains a foreach loop that loops through an array and brings back each value using $row['COLORS']. The goal is to pass the value into a function that is called. Here is my problem. I cannot use the 'return' to pass the value. Due to the foreach loop, I cannot use a return in order to keep the loop going. Below code works for 1 record only.
function __construct() {
parent::__construct();
$this->myColors = $this->getColors();
}
public function getColors() {
sql = $this->buildSQL();
$query = $this->db->query($sql)->result_array();
foreach ($query as $row) {
$theColor = $row['COLOR'];
return $theColor;
}
}
I need to do the same for each of the colors in the array, not just one value. I have tried passing the value to another function with a return but it doesn't return where I need it in the __construct.
...
foreach ($query as $row) {
$theColor = $row['COLOR'];
$this->returnColor($passColor);
}
public function returnColor($passColor) {
return $passColor;
}
I also tried a function with a switch statement (which is not a viable solution due to hundreds of values) but again the return does not work in this situation. Any help would be very much appreciated.
Here is my php code, the test method not giving wanted output, and the other weird thing is var_dump('a') print 3 times;
my wanted output is array('qtggccc','qtff23sdf');
public function main()
{
$serverIds = array('ff23sdf','ggccc');
$res = $this->test($serverIds);
var_dump($res);
}
public function test($serverIds,$imgArray = array())
{
if(count($serverIds) > 0){
$media_id = array_pop($serverIds);
$imgUrl= $this->hh($media_id);
array_push($imgArray,$imgUrl);
var_dump($serverIds);
var_dump($imgArray);
$this->test($serverIds,$imgArray);
}
var_dump('a');
return $imgArray;
}
public function hh($m)
{
return 'qt'.$m;
}
Try this:
class MyClass{
private $imgArray = array();
public function main(){
$serverIds = array('ff23sdf','ggccc');
$res = $this->test($serverIds);
print_r($this->imgArray);
}
public function test($serverIds){
if(count($serverIds) > 0){
$media_id = end($serverIds);
$imgUrl= $this->hh($media_id);
array_push($this->imgArray,$imgUrl);
//remove last element
array_pop($serverIds);
$this->test($serverIds);
}
return;
}
public function hh($m){
return 'qt'.$m;
}
}
$obj = new MyClass();
echo '<pre>';
$obj->main();
Why use recursion? You are using a complicated solution for a simple problem.
public function main()
{
$serverIds = array('ff23sdf','ggccc');
$res = array();
//These three lines replace an entire recursive function, making the code easier and saving a chunk of memory once you start using real arrays
foreach ($serverIds as $media_id){
array_unshift($res, $this->hh($media_id));
}
var_dump($res);
}
public function hh($m)
{
return 'qt'.$m;
}
So I am building a helper class that would store all get variables from a url, remove trailing spaces and return it so that other methods can use them.
The problem is that only the first value gets stored.
The url looks like:
https://pay.paymentgateway.com/index.php?name=xyz&amount=10.30&checksum=abcd
My code outputs:
Array
(
[name] => xyz
)
My code:
class helperboy
{
protected $cleanvariables = array();
public function store_get_variables($_GET)
{
foreach ($_GET as $key => $value)
{
return $this->cleanvalues[$key] = trim($value);
}
}
protected function display_variables()
{
echo "<pre>";
print_r($this->cleanvalues);
}
}
I know I am doing something silly and I would appreciate any help.
Also, how can I access specific variables like this in my other methods.:
$this->cleanvalues['name'];
$this->cleanvalues['amount'];
$this->cleanvalues['checksum'];
your return statement is the problem....
class helperboy
{
protected $cleanvariables = array();
public function store_get_variables($_GET)
{
foreach ($_GET as $key => $value)
{
$this->cleanvalues[$key] = trim($value);
}
return $this->cleanvalues;
}
protected function display_variables()
{
echo "<pre>";
print_r($this->cleanvalues);
}
}
Well, the problem is that...
public function store_get_variables($_GET)
{
foreach ($_GET as $key => $value)
{
return $this->cleanvalues[$key] = trim($value);
}
}
... the loop here will be executed just once. As soon as function hits return statement, it will abort this loop - and return immediately.
Yet I think there are some bigger problems here. First, I don't buy the idea of some omnipotent helper class that knows everything about everyone. If you intend to work with some cleaner request params, why don't just 'objectize' this instead:
class My_Http_Request
{
private $request;
protected function fillGetParams() {
$this->request['get'] = array_map('trim', $_GET);
}
public function getTrimmedParam($name) {
return $this->request['get'][$name];
}
public function __construct() {
$this->fillGetParams();
}
}
That's just an idea, not ready-made implementation (no checks for missing elements, no returning all params if 'getTrimmedParam' method is called without any arguments, etc.
i am having one key list
for example
$key_list=array("list"=>array("task","duration"));
function array_key_fun($key_list,$test_input){
//(is_array($test_input)){
return array_map('myfunction',$test_input,$key_list);
//}
}
//$va=array_map("myfunction",$test_input);
//print_r(array_key_fun($key_list,$test_input));
function myfunction($arr)
{
if(is_array($arr))
{
$get_array= get_childs($arr);
return $get_array;
}
}
function get_childs($arr){
$newarr=array();
$newarr_en='';
foreach($arr as $key=>$value)
{
if(is_array($value)){
$newarr[$key]=get_childs($value);
}else{
if (in_array($key,$key_list)) //here im facing the problem with key_list
{
..............
}
else
{
...............
}
}
}
return $newarr;
}
Either pass in function or declare as global
function abc($a,$key_list){
OR
function abc($a){
global $key_list;
//rest of code
EDIT:
When you pass the array as parameter of function you have to pass the value in call as well
when you call this function this should be
//array should be declared before calling function
$key_list=array("list"=>array("task","duration"));
abc($a,$key_list); //pass this array
http://php.net/manual/en/function.array-walk.php
array_walk
try this
You have to bring the variable into scope, within your code you have ......... if you replace that with global $key_list this will allow the function to Read / Write to that stack.