2013-07-05 240 views
1

這是一個假設性問題。如果我有3個數組,從3個獨立的SQL數據庫查詢都與另一個有關。例如...php foreach在foreach中的foreach

//db 
schools 
id | school_name 

classes 
id | class_name | school_id 

students 
id | student_name | class_id 

而且我想在這樣一個巨大的名單,以顯示一切......

//php 
foreach(schools as school){ 

    echo '<h1>' . $school->school_name . '<h1>'; 

    foreach(classes as class){ 

     if($class->school_id == $school->id){ 

      echo '<h2>' . $class->class_name . '<h2>'; 

      foreach(students as student){ 

       if($student->class_id == $class->id){ 

        echo '<h3>' . $student->student_name . '<h3>'; 

       } 
      } 
     } 
    } 
} 

我必須做出3所數據庫調用。有沒有辦法在單個數據庫查詢中獲取所有這些信息?就像一個數組中的數組中的數組,然後以某種方式循環?或者這是做到這一點的最佳方式?

+0

爲什麼dont't使用加入[JOIN](http://dev.mysql.com/doc/refman/5.0/en/join.html) –

+0

你爲什麼不使用activeRecord ..也許與InnoDB建立關係並用PDO取得它們;或者開始使用一些支持ActiveRecords,關係等的MVC框架,例如:Yii,CodeIgniter,Kohana,Symphony – 2013-07-05 18:20:57

回答

0
<?php 

try { 
    $pdo = new PDO("mysql:host=127.0.0.1;dbname=school", "username"); 
} catch (PDOException $e) { 
    echo "PDO Connection failed: " . $e->getMessage(); 
    exit(1); 
} 

$sql = <<<SQL 

    SELECT schools.school_name, classes.class_name, students.student_name 
    FROM 
     schools INNER JOIN classes ON (schools.id = classes.school_id) 
     INNER JOIN students ON (classes.id = students.class_id) 
    ORDER BY 1, 2; 

SQL; 

$result = $pdo->query($sql); 
if ($result == false) { 
    die("query failed?!"); 
} 

$school = ""; 
$class = ""; 
while ($row = $result->fetch(PDO::FETCH_ASSOC)) { 
    if ($school != $row['school_name']) { 
     $school = $row['school_name']; 
     echo "\nSchool: $school\n\n"; 
    } 
    if ($class != $row['class_name']) { 
     $class = $row['class_name']; 
     echo " Class: $class\n\n"; 
     echo "  Student list:\n"; 
    } 
    echo "   {$row['student_name']}\n"; 
} 
+0

這是比在foreach中使用foreach時更好的做法嗎?如果是這樣,爲什麼? – Staysee

+0

這可能更有效,更快。我也發現它更易於閱讀。 – CXJ

1

你可以做一個連接,讓每個連接有1個連接。你想要什麼或任何類型的過濾器?

0

你可以做到這一切在一個SQL查詢,可能看起來像:

SELECT schools.schoolname, classes.class_name, students.student_name 
FROM 
    schools INNER JOIN classes ON (schools.id = classes.school_id) 
    INNER JOIN students ON (classes.id = students.class_id) 
ORDER BY 1, 2; 

然後,你可以走,結果在一個循環中集,但你可能會想一些邏輯加起來也只有顯示器學校名稱和班級名稱每次更改一次。

+0

我已經使用了一點點連接。邏輯看起來像是每次更改顯示學校名稱一次?我是新來的PHP。 – Staysee

+0

看到我的其他答案。這是一個快速,醜陋的黑客攻擊,但它應該告訴你你需要知道什麼。 – CXJ

1

你可以加入這些表,以獲得一個大數組與flattened數據。在循環這些數據時,您可以檢查前一條記錄的ID是否仍然與當前記錄的ID匹配。如果沒有,您可以輸出一個新的標題。但是,重要的是結果集已經過適當的排序。

SELECT 
    s.id AS school_id, 
    s.school_name, 
    c.id AS class_id, 
    c.class_name, 
    st.id AS student_id, 
    st.student_name 
FROM 
    schools s 
    INNER JOIN classes c ON c.school_id = s.id 
    INNER JOIN students st ON st.class_id = c.id 
ORDER BY 
    s.id, 
    c.id, 
    st.id 

如果你擁有這一切爲扁平的結構,你甚至可以把它做成嵌套數組結構又是這樣的:

foreach ($resultset as $row) 
{ 
    $schools[$row->school_id]->school_name = 
     $row->school_name; 
    $schools[$row->school_id]->classes[$row->class_id]->class_name = 
     $row->class_name; 
    $schools[$row->school_id]->classes[$row->class_id]->students[$row->student_id]->student_name = 
     $row->student_name; 
} 
var_dump($schools); 

之後,你仍然可以使用嵌套的for循環來處理數組,但由於數據已經被整理出來,所以它會更有效率:班級已經被添加到他們所屬的學校,並且學生已經被添加到正確的班級中。

0
$res = mysql_query('SELECT school_name, class_name, student_name, sc.id AS scid, c.id AS cid, st.id AS stid FROM schools sc LEFT JOIN classes c ON (sc.id = c.school_id) LEFT JOIN students st ON (c.id = st.class_id) '); 
$arr = array(); 
while ($v = mysql_fetch_assoc($res)) { 
$arr[$v['school_name']][$v['class_name']][$v['stid']] = $v['student_name']; 
} 

print_r($arr);