2014-01-10 4 views
0

У меня возникают проблемы с рекурсивной функцией, которую я пытаюсь написать. Здесь вы можете увидеть мой код:Рекурсивная функция не возвращает ожидаемое значение в PHP

function getParents($individualInfo) { 

     $individualid = ''; 

     if(is_array($individualInfo)) { 
      foreach($individualInfo as $key => $value) { 
       if(is_array($individualInfo[$key])) { 
        return $this->getParents($individualInfo[$key]); 
       } 
       else { 
        if ($key == 'individual_id') { 
         $individualid = $individualInfo[$key]; 
        } 
       } 
      } 
     } 
     else { 
      $individualid = $individualInfo; 
     } 
     $q = "SELECT i.individual_id, i.fname, i.lname, i.birth_date, i.death_date, i.gender, 
       i.biography, i.avatar, i.individual_username, r.relationship_individual 
       FROM ".TBL_RELATIONSHIPS." AS r, ".TBL_INDIVIDUALS." AS i 
       WHERE r.relationship_individual = '$individualid' 
       AND r.individual = i.individual_id 
       AND (r.role = '2') 
       LIMIT 2"; 

     $result = $this->database->query($q); 

     if ($result === false) { 
      $result .= die(mysql_error()); 
      return; 
     } 

     $num_rows = mysql_num_rows($result); 
     $tmp_array = array(); 


     if ($num_rows > 0) { 
      while ($row = mysql_fetch_assoc($result)) { 
       $tmp_array[] = $row; 
      } 
      foreach ($tmp_array as $tmp_parents) { 
       $tmp_parents['individual_id'] = $this->database->cleanOutput($tmp_parents['individual_id']); 
       $tmp_parents['fname'] = $this->database->cleanOutput($tmp_parents['fname']); 
       $tmp_parents['lname'] = $this->database->cleanOutput($tmp_parents['lname']); 
       $tmp_parents['birth_date'] = $this->database->cleanOutput($tmp_parents['birth_date']); 
       $tmp_parents['death_date'] = $this->database->cleanOutput($tmp_parents['death_date']); 
       $tmp_parents['gender'] = $this->database->cleanOutput($tmp_parents['gender']); 
       $tmp_parents['biography'] = $this->database->cleanOutput($tmp_parents['biography']); 
       $tmp_parents['avatar'] = $this->database->cleanOutput($tmp_parents['avatar']); 
       $tmp_parents['individual_username'] = $this->database->cleanOutput($tmp_parents['individual_username']); 
       $tmp_parents['relationship_individual'] = $this->database->cleanOutput($tmp_parents['relationship_individual']); 
       // father 
       if (!isset($parents[0]) && $tmp_parents['gender'] == 'Male') { 
        $parents[0] = $tmp_parents; 
       } 
       // mother 
       else { 
        $parents[1] = $tmp_parents; 
       } 
      } 
      return $parents; 
     } 

    } 

$this->getParents($this->getParents($individualid));

Вывод выглядит следующим образом, если только идентификатор передается, например, 160:

Array ([0] => Array ([individual_id] => 161 [fname] => John [lname] => Doe [birth_date] => [death_date] => [gender] => Male [biography] => [avatar] => [individual_username] => [relationship_individual] => 160) [1] => Array ([individual_id] => 162 [fname] => Jane [lname] => Doe [birth_date] => [death_date] => [gender] => Female [biography] => [avatar] => [individual_username] => [relationship_individual] => 160)) 

Я хочу, чтобы получить эти результаты, если я пройти массив, который я написал выше, чтобы функционировать:

Array ([0] => Array ([individual_id] => 163 [fname] => Sr. John [lname] => Doe [birth_date] => [death_date] => [gender] => Male [biography] => [avatar] => [individual_username] => [relationship_individual] => 161) [1] => Array ([individual_id] => 164 [fname] => Sr. Jane [lname] => Doe [birth_date] => [death_date] => [gender] => Female [biography] => [avatar] => [individual_username] => [relationship_individual] => 161)) 
Array ([0] => Array ([individual_id] => 165 [fname] => Sr. John [lname] => Roe [birth_date] => [death_date] => [gender] => Male [biography] => [avatar] => [individual_username] => [relationship_individual] => 162) [1] => Array ([individual_id] => 166 [fname] => Sr. Jane [lname] => Roe [birth_date] => [death_date] => [gender] => Female [biography] => [avatar] => [individual_username] => [relationship_individual] => 162)) 

Функция выше должна помочь мне найти родителей любого конкретного человека или группы лиц. Например, если массив с обоими родителями передан, тогда возвращаются все данные бабушки и дедушки. Теперь функция не возвращает все результаты, потому что я использовал оператор return в первом цикле foreach, и функция может возвращаться только один раз. Однако, если я не использую return, возвращается null, потому что $ individualid является пустой строкой в ​​тот момент. Функция, которая отображает информацию выглядеть следующим образом:

function displayParents($parentsInfo) { 

     foreach ($parentsInfo as $parents) { 
      // father 
      if (isset($parents[0])) { 
       $type = 'father'; 
       $individualid = $parents[0]['individual_id']; 
       $name = $parents[0]['fname'].' '.$parents[0]['lname']; 
       $bdate = $parents[0]['birth_date']; 
       $ddate = $parents[0]['death_date']; 
       $gender = $parents[0]['gender']; 
       $bio = $parents[0]['biography']; 
       $avatar = $parents[0]['avatar']; 
       $username = $parents[0]['individual_username']; 
       $relationshipid = $parents[0]['relationship_individual']; 
       $this->displayLeaf($type, $individualid, $name, $gender, $bdate, $ddate, $bio, $avatar, $username, $relationshipid); 
      } 
      else { 
       $type = 'emptyFather'; 
       $this->displayLeaf($type, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 
      } 
      // mother 
      if (isset($parents[1])) { 
       $type = 'mother'; 
       $individualid = $parents[1]['individual_id']; 
       $name = $parents[1]['fname'].' '.$parents[1]['lname']; 
       $bdate = $parents[1]['birth_date']; 
       $ddate = $parents[1]['death_date']; 
       $gender = $parents[1]['gender']; 
       $bio = $parents[1]['biography']; 
       $avatar = $parents[1]['avatar']; 
       $username = $parents[1]['individual_username']; 
       $relationshipid = (isset($parents[0]) ? $parents[0]['individual_id'] : $parents[1]['relationship_individual']); 
       $this->displayLeaf($type, $individualid, $name, $gender, $bdate, $ddate, $bio, $avatar, $username, $relationshipid); 
      } 
      else { 
       $type = 'emptyMother'; 
       $this->displayLeaf($type, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 
      } 
     } 
    } 

Я пытался искать ответы на мой вопрос, но я не могу найти какое-либо решение, потому что я действительно новым для него. Любые советы о том, как изменить функцию, чтобы она выполняла именно то, что мне нужно?

ответ

0

Вам действительно нужна рекурсия?

Я на самом деле не на 100% понятен, какой результат вы ожидаете, если это всего лишь плоский массив всех родителей людей на входе, то вы можете легко обойтись без него.

function getParents($individualInfo) { 
    if (is_integer($individualInfo)) { $individualInfo = array('individual_id' => $individualInfo); } 
    if (isset($individualInfo['individual_id'])) { $individualInfo = array($individualInfo); } 
    /* input is now consistently an array of associative arrays that should have a key 'individual_id' */ 

    $ids = array(); 
    foreach ($individualInfo as $individual) 
    { 
     if (!empty($individual['individual_id']) && is_integer($individual['individual_id'])) 
     { 
      $ids[$individual['individual_id']] = true; 
      /* I'm doing this instead of simply adding the id to the array 
       so I can get just the unique ids from the array_keys later*/ 
     } 
    } 

    $idsstring = implode(',', array_keys($ids)); 
    $maxparents = 2*count($ids); /* Well, assuming nuclear families */ 

    /* there might not be any ids for some reason (like bad input) */ 
    if (empty($idsstring)) 
    { 
     return array(); 
    } 

    /* we've checked that all ids are integers, so there is little risk of SQL-injection 
    * With `r.relationship_individual IN ($idsstring)` we can search for all parents of 
    * all individuals at once. 
    */ 
    $q = "SELECT i.individual_id, i.fname, i.lname, i.birth_date, i.death_date, i.gender, 
      i.biography, i.avatar, i.individual_username, r.relationship_individual 
      FROM ".TBL_RELATIONSHIPS." AS r, ".TBL_INDIVIDUALS." AS i 
      WHERE r.relationship_individual IN ($idsstring) 
      AND r.individual = i.individual_id 
      AND (r.role = '2') 
      LIMIT $maxparents"; 

    $result = $this->database->query($q); 

    if ($result === false) { 
     $result .= die(mysql_error()); 
     return; 
    } 

    $num_rows = mysql_num_rows($result); 
    $tmp_array = array(); 
    $parents = array(); 
    if ($num_rows > 0) { 
     while ($row = mysql_fetch_assoc($result)) { 
      $tmp_array[] = $row; 
     } 
     foreach ($tmp_array as $tmp_parents) { 
      foreach($tmp_parents as $key => $value){ 
       $tmp_parents[$key] = $this->database->cleanOutput($value); 
      } 
      $parents[] = $tmp_parents; 
     } 
    } 
    return $parents; 
} 

Если с другой стороны, вы хотите, чтобы построить дерево родителей родителей родителей, то рекурсия может быть в порядке. (Хотя по-прежнему лучше избегать получения информации о родителях из базы данных. Более эффективно запрашивать базу данных один раз.) Позвольте мне теперь, если это так.

+0

Спасибо за ответ. Я попытался использовать вашу функцию, и она вернула информацию отца отца и матери матери, а не всех четырех бабушек и дедушек. Я не уверен, почему это произошло, но я отредактирую свой вопрос и объясню, какие результаты я бы хотел получить. – user3182654

+0

Хм, ну, это немного сложно отлаживать без базы данных (я не думаю, что вы установили лимит на 2?). Может быть, вам лучше помочь, если я предложу несколько небольших исправлений о том, как работает ваш исходный код: change 'return $ this-> getParents ($ individualInfo [$ key]);' to '$ returns [] = $ this- > getParents ($ individualInfo [$ key]); '(для сбора всех возвращаемых значений из рекурсии в массиве) и перед запросом' if ($ return) {return $ return; } '(чтобы вернуть значения из рекурсии, если они были после того, как мы их собрали) – towr

+0

Обе функции работают нормально. Я понял, что первый из них не работает правильно, потому что идентификаторы не были уникальными, поэтому он вернул только двух бабушек и дедушек. Мой оригинальный код с исправлениями работает очень хорошо. Но я решил не использовать рекурсию в конце концов и запросить мой db только один раз. Мне пришлось внести несколько изменений в функцию displayParents и db, но теперь я полностью доволен результатами. Спасибо за помощь. – user3182654

Смежные вопросы