phprecursionmultidimensional-arraycurl-multi

Nested loop with recursive function?


I need to do a recursive loop on every result suggested by google up to a user-defined depth and save results in a multidimensional array, explored later on.

I want to get this result.

google
google app
google app store
google app store games
google app store games free
google maps
google maps directions
google maps directions driving
google maps directions driving canada
...

Currently, my recursive function returns replicated results from the second nesting.

google
google app
google app
google app store
google app store
google app
google app store
google app store
google app store
...

I think the problem comes from the array (parent results) that I pass as an argument to my function recursive_function() to each nested loops.

$child = recursive_function($parent[0][1], $depth, $inc+1);

Recursive function

// keywords at line or spaced
$keywords = explode("\n", trim("facebook"));

$result = recursive_function($keywords, 2);

function recursive_function($query, $depth, $inc = 1)
{
    $urls = preg_filter('/^/', 'http://suggestqueries.google.com/complete/search?client=firefox&q=', array_map('urlencode', $query));
            
    $parent = curl_multi_function($urls);

    array_multisort($parent[0][1]);
    
    if (count($parent[0][1]) === 0 || $inc >= $depth)
    {
        $out[] = $parent[0][1];
    }
    else
    {
        $child = recursive_function($parent[0][1], $depth, $inc+1);
        
        $out[] = $child;
    } 
        
    return $out;
}

Function curl

function curl_multi_function($data, $options = array()) 
{
    // array of curl handles
    $curly = array();
    
    // data to be returned
    $result = array();

    // multi handle
    $mh = curl_multi_init();

    // loop through $data and create curl handles
    // then add them to the multi-handle
    foreach ($data as $id => $d) 
    {
        $curly[$id] = curl_init();

        $url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;
        curl_setopt($curly[$id], CURLOPT_URL,            $url);
        curl_setopt($curly[$id], CURLOPT_HEADER,         0);
        curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curly[$id], CURLOPT_SSL_VERIFYPEER, 0);

        // post?
        if (is_array($d)) 
        {
            if (!empty($d['post'])) 
            {
                curl_setopt($curly[$id], CURLOPT_POST,       1);
                curl_setopt($curly[$id], CURLOPT_POSTFIELDS, $d['post']);
            }
        }

        // extra options?
        if (!empty($options)) {
          curl_setopt_array($curly[$id], $options);
        }

        curl_multi_add_handle($mh, $curly[$id]);
    }

    // execute the handles
    $running = null;
    do 
    {
        curl_multi_exec($mh, $running);
    } 
    while($running > 0);

    // get content and remove handles
    foreach($curly as $id => $c) 
    {
        $result[$id] = curl_multi_getcontent($c);
        
        // decode json result
        $result[$id] = json_decode(utf8_encode($result[$id]));
        
        curl_multi_remove_handle($mh, $c);
    }

    // all done
    curl_multi_close($mh);
    
    return $result;
}

Solution

  • I've changed your recursive_function a little bit:

    function recursive_function($query, $depth, $inc = 1)
    {
        $urls = preg_filter('/^/', 'http://suggestqueries.google.com/complete/search?client=firefox&q=', array_map('urlencode', $query));
    
        $parent = curl_multi_function($urls);
    
        foreach ($parent as $key => $value) {
          array_multisort($value[1]);
    
          $words = explode(' ', $value[0]);
          $lastWord = end($words);
    
          if (count($value[1]) === 0 || $inc >= $depth) {
              $out[$lastWord] = [];
          } else {
              unset($value[1][0]);
              $child = recursive_function($value[1], $depth, $inc+1);
              $out[$lastWord] = $child;
          } 
        }
    
        return $out;
    }
    

    It generates an array like this:

    [
       google =>
         [
           app =>
             [
               store =>
                 [
                    games =>
                      [
                        free => []
                      ]
                  ]
             ]
             ...
         ]
    ]
    

    Is that what you want?