2013-03-25 53 views
5

我已經創建類似物的一個簡單的表:如何從文章中遞歸獲取表格中的所有類似物?

+----+-------+-------+ 
| id | sku_1 | sku_2 | 
+----+-------+-------+ 
| 1 | a1 | abcd | 
| 2 | a2 | a3 | 
| 3 | a3 | a1 | 
+----+-------+-------+ 
3 rows in set (0.00 sec) 

是什麼意思?它的意思是與文章abcd有文章a1模擬該產品,否則例如與文章a3產品有文章a1模擬。

如何通過遞歸單篇文章得到所有從這個表中的產品?

我的解決方案是錯誤的:

// Small Class to get analogs of products 
class Analogs { 

    public function get_analogs($sku) 
    { 
     if (!$sku) return false; 

     $link = mysql_connect('localhost','',''); 
     mysql_select_db('test'); 

     $sku = mysql_real_escape_string($sku,$link); 

     $query = mysql_query("SELECT * FROM analogs WHERE sku_1='".$sku."' OR sku_2='".$sku."'"); 

     while($analogs[]=mysql_fetch_assoc($query)) 
     continue; 

     return $analogs;  
    } 


    public function MixedAnalogs($sku) 
    { 
     if (!$sku) return false; 

     $link = mysql_connect('localhost','',''); 
     mysql_select_db('test'); 

     $sku = mysql_real_escape_string($sku,$link); 

     $query = mysql_query("select sku_1 sku from analogs where sku_2 = '$sku' UNION 
           select sku_2 sku from analogs where sku_1 = '$sku'"); 

     while($analogs[]=mysql_fetch_assoc($query)) 
     continue; 

     return $analogs; 
    } 


} 

$mixed_analogs = AnalogsMix('abcd',$ids=array()); 

echo "<pre>"; 
print_r($mixed_analogs); 
echo "</pre>"; 

// Recursive function to get analogs of analog 
function AnalogsMix($sku,$ids=array()) 
{ 
    $class_analogs = new Analogs(); 
    $analogs = $class_analogs->get_analogs($sku); 

    foreach ($analogs as $analog) 
    { 
     $cross = null; 

     if ($analog['sku_1']==$sku) 
     { 
      $cross->sku = $analog['sku_2']; 
     } 
     else 
     { 
      $cross->sku = $analog['sku_1']; 
     } 

     $cross->id = $analog['id']; 

     if (!in_array($analog['id'],$ids)) 
     { 
      $ids[] = $analog['id']; 
      $mixed[] = AnalogsMix($cross->sku,$ids); 
     } 
    } 

    if (isset($mixed)) 
    { 
     return $mixed; 
    } 
    else 
    { 
     return false; 
    } 
} 
+2

1.您不使用'mysql_real_escape_string'來正確轉義'$ sku'。 2.請注意,不推薦使用'mysql_ *'函數(請參閱[red box](http://php.net/mysql_query))。 3.怎麼了?它目前輸出什麼,它應該輸出什麼? – 2013-03-25 14:35:14

+0

爲了確保我理解了這個問題,您期望您提供的示例有什麼結果? – Fabien 2013-03-25 14:36:04

+0

@Marcel Korpel。我不打算在我的真實服務器上使用它,它只是一個抽象的例子。和@Fabien,如果我把'abcd'放到這裏,我必須得到所有的類似物,因爲'abcd'有模擬信號作爲'a1','a1'有'a3'的模擬信號,'a3'有模擬信號作爲'a2'。 ,所以函數必須返回所有的類比。 – Smash 2013-03-25 14:40:11

回答

1

SQL UNION

select sku_1 sku from analogs where sku_2 = $yourid 
union 
select sku_2 sku from analogs where sku_1 = $yourid 

然後你會在結果只能類似物的IDS得到。

+0

並看看其他同志告訴你有關正確的轉義和depcrecated功能:) – gaRex 2013-03-25 14:42:49

+0

我已經爲此添加了一種方法。我得到這個:$ class_analogs = new Analogs(); $ mixed_analogs = $ class_analogs-> MixedAnalogs('abcd'); echo「

"; print_r($mixed_analogs); echo "
」; – Smash 2013-03-25 15:10:19

+0

陣列 ( [0] =>數組 ( [SKU] => A1 ) [1] => ) – Smash 2013-03-25 15:10:40

1

在這裏,我想你有數組中的所有的對。例如,對於您的示例,您可以撥打analogsOf(array(array("a1", "abcd"), array("a2", "a3"), array("a3", "a1")), "abcd")

的想法是,你構建一個包含最初只是你正在尋找串並,每次都發現模擬時間類似物的列表,你將它添加到類似物的名單,並重申。你這樣做直到你迭代了整個數組而沒有發現任何新東西。

function analogsOf(array $pairs, $key) { 
    $res = array($key); // The result, with only the given key 
    $i = 0;    // Index of the current item 
    $changed = false; // Have we added an item to $res during that iteration ? 

    while ($i < count($pairs)) { 
     $current = $pairs[$i]; 

     foreach ($res as $item) { 
      if (($current[0] === $item) && (!in_array($current[1], $res)) { 
       $res[] = $current[1]; 
       $i = 0; // Reiterate as $res changed 
      } 
      else if (($current[1] === $item) && (!in_array($current[0], $res)) { 
       $res[] = $current[0]; 
       $i = 0; // Reiterate as $res changed 
      } 
      else { 
       $i++; // Nothing found here, go to next item 
      } 
     } 
    } 

    return $res; 
} 

請注意,此代碼未經過測試,所以可能會出現一些錯誤,但您已經明白了。另外請注意,我認爲你可以將整個數據庫內容放在一個數組中,但是由於顯而易見的原因,這可能是不可能的,所以你可能需要修改上面的代碼。

+0

這是否真的可擴展?將所有的mysql數據加載到數組中,會導致mysql不存在。你失去了數據庫的速度和效率。 – Husman 2013-03-25 15:02:36

+0

我知道,一定是一個等級,而且會是。現在它只是一個測試。 – Smash 2013-03-25 15:09:19

+0

@Husman,就像我說的那樣,不,這樣做的可擴展性不是很好,如果數據越來越大,你必須找到緩存策略。如果縮放成爲一個問題,無論如何,我認爲在數據庫中明確地存儲類比鏈接將是最好的選擇。 – Fabien 2013-03-25 15:19:19

1

,我發現這個問題的解決方案,但在這種方法的主要問題是。 它可以製作一個像abcd->a1,a1->a3,a3->a2,a2->abcd這樣的循環。它使遞歸函數無窮無盡,並且PHP拋出一個錯誤。所以你必須檢查它是否是一個大項目。

在我的解決方案,我認爲這是父 - >子關係。並且如果發現孩子使其成爲家長並再次檢查等,直到沒有結果。

abcd是父母和第一次執行後a1是小孩和關係是abcd->a1。但在接下來的電話a1是父母,並從表的第一行給出一個新的關係,即a1->abcd和循環是無止境的。 爲了防止檢查同一行我使用ID從數據庫的最後一行,它現在檢查行ID = ID(總是檢查其他行)

這是我寫的函數,根據你的類轉換它,並存儲只要你喜歡數組的值。我只使用一個字符串。 我知道這不是一個好的解決方案,但我工作得很好。

<?php 

mysql_connect('localhost','',''); 
mysql_select_db('test'); 

function getSku($sku, $id, $rel = '') { 
    $query = mysql_query("SELECT * FROM analogs WHERE sku_1 = '$sku' AND id != '$id'"); 
    if (mysql_num_rows($query)) { 
     $row = mysql_fetch_assoc($query); 
     $sku = $row['sku_2']; //PARENT SKU 
     $id = $row['id']; //LAST ID 
     $rel .= $row['sku_1']. '-->' . $row['sku_2']. "<br>"; 

    } else { 
     $query = mysql_query("SELECT * FROM analogs WHERE sku_2 = '$sku' AND id != '$id'"); 
     if (mysql_num_rows($query)) { 
      $row = mysql_fetch_assoc($query); 
      $sku = $row['sku_1']; //PARENT SKU 
      $id = $row['id']; //LAST ID 
      $rel .=$row['sku_2']. '-->' . $row['sku_1']. '<br>'; 
     } else { 

      return (string)$rel; //NOTHING FOUND 
     } 
    } 
    return getSku($sku,$id,$rel);  

} 

echo $new = getSku('abcd','-1'); 
相關問題