2011-12-31 81 views
6

我的問題是什麼是將大型php數組保存到mysql表的最好和最有效的方法。我知道有很多方法可以做到這一點,我嘗試了其中的一些方法,但我仍然沒有找到一種我真正感覺舒適的方法。大多數人推薦的主要方法是serialize()和unserialize()php函數。由於某種原因,這不適合我,我似乎已經嘗試了各種方法來解決這個問題,但idk。將PHP數組數據保存到mysql表的最佳方法

這裏是我的代碼:

// unserialize songs, add new song to end of array, and then re-serialize to add to db 
    $cereal = unserialize($dbsongs); 
    $pushed = array_push($cereal, $_GET['song']); 
    $songs = serialize($pushed); 

    //update playlists table 
    $stmt = $dbh->prepare("UPDATE playlists SET songs=:songs WHERE title=:title AND user=:user"); 
    $stmt->bindParam(':user', $_SESSION['username'], PDO::PARAM_STR); 
    $stmt->bindParam(':title', $_GET['title'], PDO::PARAM_STR); 
    $stmt->bindParam(':songs', $songs, PDO::PARAM_STR); 
    $stmt->execute(); 

所以首先我反序列化 $ dbsongs這是串行數據從一個MySQL表的空白列表。然後我將 $ _GET ['song'] array_push()。然後我序列化並將其存儲到數據庫。出於某種原因,這不起作用,但我也想知道是否有更好的方法。

我應該嘗試拆分php數組,並將每個項目保存到一個表格中,並用逗號分隔項目,並且當我從數據庫中檢索它時打破該字符串?

或者我應該修復這個方法嗎?或甚至添加 base64_decode() base64_encode()?這些方法似乎是從一些我看過的東西有點老... http://www.evolt.org/node/60222

我已經看到了使用 .implode的方法,但我無法弄清楚如何使用它... Link 1Link 2。這看起來像我見過的最現代的方法。這是我應該進一步研究的嗎?

不知道這個方法是什麼,但它提到CakePHP,我想是一個PHP庫。這是一個好方法嗎? Link 1

我將在這些列表中存儲大量項目(如定期超過1k個項目),所以我甚至不確定是否將這些項目保存到一個表格字段是適當的。只是爲這些項目製作表格是最好的方法,因爲列表將會變得很大(爲每個新項目添加一個新的數據庫條目,並製作一個「標題」字段以將它們鏈接在一起)?我從來沒有嘗試過這樣的事情,因爲我永遠無法找到足夠的信息,說明mysql可以在不出現問題的情況下保存多少數據。

我知道這裏有很多問題,但任何答案將不勝感激!提前致謝!

-BAH

+1

您是否反對將*歌曲*存儲在另一個表中並創建一個橋表格(* playlist_songs *)來處理關係?這是使用關係數據庫(如MySQL)的傳統方式。 – 2011-12-31 05:15:44

回答

12

首先,我要說的是serialize()是去,如果你想存儲PHP數組在DB的方式。

您的問題是您誤用了array_push()。如果正確使用它,則serialize()方法將起作用。我將立即解決如何爲此目的修復您的代碼。

使用序列化並將序列化歌曲名存儲在單個TEXT字段中實際上是理想的,因爲它使得FULLTEXT索引搜索非常簡單(我假設MySQL)。例如,當您將序列化數組存儲在單個字段中時,可以輕鬆找到包含單詞「awesome」的歌曲標題的所有列表。

另一種方法是創建三個表:一個列表,一個歌曲和一個歌曲和列表之間的聯繫。然後,您可以使用LEFT JOIN查詢將歌曲與列表進行匹配。在你的情況下,我會選擇前一種選擇。

的儲存方法完全取決於您打算如何訪問數據。如果您需要能夠快速匹配特定歌曲名稱並且經常列表,則第二個提到的規範化數據庫表單可能會更好。

爲什麼SERIALIZE工作不適合你現在...

array_push()返回一個整數,它接收到的第一個參數是按引用傳遞。這意味着行:

$pushed = array_push($cereal, $_GET['song']);

實際上是設置$pushed等於$cereal陣列加一箇中的元素的數量。

您可以糾正你的問題,像這樣:

$serial = unserialize($dbsongs); 
$song_count_in_pushed_array = array_push($serial, $_GET['song']); 
$songs = serialize($serial); 

UPDATE

在回答您的有關編碼序列化的數據的base64評論,這裏是你如何做到這一點,以防止數據數據損壞這不是8位清潔:

// For safe serializing 
$encoded_and_serialized = base64_encode(serialize($array)); 

// For unserializing 
$restored = unserialize(base64_decode($encoded_and_serialized)); 
+0

真棒,感謝修復!所以你會推薦保存列表的unserialize()和serialize()方法?怎麼樣的base64_decode()和base64_encode()函數,我需要它們(我想這取決於什麼數據即時保存,不適宜將int變量保存到列表中)?再次感謝您的幫助! – bahudso 2012-01-01 01:15:19

+1

是的,serialize/unserialize專門用於傳輸數據結構(如數組)。 base64函數避免了[8位清理](http://en.wikipedia.org/wiki/8-bit_clean)數據的麻煩。例如,假設您序列化並存儲包含UTF-16字符串的數組,但您的數據庫歸類不支持這些字符。如果您不對編碼序列化的數據進行base64編碼,則最終會導致數據損壞。我在答案的最後添加了一條註釋以說明這一點。但是,如果您只是存儲數字數據,則base64函數將不再需要。 – rdlowrey 2012-01-02 01:56:24

相關問題