Simpan array PHP ke MySQL?

88

Apa cara yang baik untuk menyimpan larik data ke satu bidang mysql?

Juga setelah saya menanyakan array itu di tabel mysql, apa cara yang baik untuk mengembalikannya ke bentuk array?

Apakah serialisasi dan unserialize jawabannya?

JasonDavis
sumber

Jawaban:

88

Tidak ada gunanya cara yang untuk menyimpan larik ke dalam satu bidang.

Anda perlu memeriksa data relasional Anda dan membuat perubahan yang sesuai pada skema Anda. Lihat contoh di bawah untuk referensi tentang pendekatan ini.

Jika Anda harus menyimpan array ke dalam satu bidang maka fungsi serialize()dan unserialize()akan melakukan triknya. Tetapi Anda tidak dapat melakukan kueri pada konten yang sebenarnya.

Sebagai alternatif dari fungsi serialisasi, ada juga json_encode()dan json_decode().

Perhatikan array berikut

$a = array(
    1 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
    2 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
);

Untuk menyimpannya di database Anda perlu membuat tabel seperti ini

$c = mysql_connect($server, $username, $password);
mysql_select_db('test');
$r = mysql_query(
    'DROP TABLE IF EXISTS test');
$r = mysql_query(
    'CREATE TABLE test (
      id INTEGER UNSIGNED NOT NULL,
      a INTEGER UNSIGNED NOT NULL,
      b INTEGER UNSIGNED NOT NULL,
      c INTEGER UNSIGNED NOT NULL,
      PRIMARY KEY (id)
    )');

Untuk bekerja dengan rekaman Anda bisa melakukan kueri seperti ini (dan ya ini adalah contoh, waspadalah!)

function getTest() {
    $ret = array();
    $c = connect();
    $query = 'SELECT * FROM test';
    $r = mysql_query($query,$c);
    while ($o = mysql_fetch_array($r,MYSQL_ASSOC)) {
        $ret[array_shift($o)] = $o;
    }
    mysql_close($c);
    return $ret;
}
function putTest($t) {
    $c = connect();
    foreach ($t as $k => $v) {
        $query = "INSERT INTO test (id,".
                implode(',',array_keys($v)).
                ") VALUES ($k,".
                implode(',',$v).
            ")";
        $r = mysql_query($query,$c);
    }
    mysql_close($c);
}

putTest($a);
$b = getTest();

The connect()mengembalikan fungsi sumber daya koneksi mysql

function connect() {
    $c = mysql_connect($server, $username, $password);
    mysql_select_db('test');
    return $c;
}
Peter Lindqvist
sumber
26

Secara umum, ya, serialisasi dan unserialize adalah cara yang harus dilakukan.

Jika data Anda adalah sesuatu yang sederhana, menyimpan sebagai string yang dipisahkan koma mungkin akan lebih baik untuk ruang penyimpanan. Jika Anda mengetahui bahwa array Anda hanya berupa daftar angka, misalnya, Anda harus menggunakan implode / explode. Ini perbedaan antara 1,2,3dana:3:{i:0;i:1;i:1;i:2;i:2;i:3;} .

Jika tidak, maka buat serial dan unserialize pekerjaan untuk semua kasus.

Matchu
sumber
24
Karena Anda ada di sini, pembaca, saya hanya akan meluangkan waktu untuk mengumumkan bahwa saya telah menemukan, melalui pengalaman bertahun-tahun, bahwa ini bukanlah cara yang tepat. Jawaban yang diterima adalah pendekatan yang lebih kuat.
Matchu
4
Karena Anda ada di sini, pembaca saya akan berbagi dengan Anda bahwa itu hanya tergantung pada kebutuhan Anda. Jika Anda tidak perlu melakukan kueri dengan nilai array Anda dan membutuhkan sesuatu yang sangat CEPAT, Anda dapat dengan aman menyimpan data Anda seperti ini dalam satu bidang (yang pertanyaannya dinyatakan dengan jelas), tempelkan kunci utama di atasnya dan pergilah. . Jika Anda bertanya-tanya apa aplikasinya: mendorong data ke dalam antrian yang di-cron setiap 5 menit. Cron lain membuat array yang membutuhkan lebih banyak waktu. Que mengambil data yang dihitung dan meneruskannya ke API pihak ketiga. Tidak ada cara yang lebih baik untuk melakukannya.
Rid Iculous
1
@RidIculous Saya bingung, apakah Anda berbicara tentang aplikasi pribadi Anda atau aplikasi yang menyebabkan pertanyaan diajukan?
Peter Lindqvist
1
Sementara itu tidak relevan dengan premis pernyataan saya, awalan "Jika Anda bertanya-tanya apa aplikasinya" harus memberikan kejelasan.
Rid Iculous
10

Cukup gunakan fungsi PHP serialisasi:

<?php
$myArray = array('1', '2');
$seralizedArray = serialize($myArray);
?>

Namun, jika Anda menggunakan array sederhana seperti itu, Anda sebaiknya menggunakan implode dan meledak. Gunakan array kosong, bukan baru.

KramerC
sumber
9

Serialize / Unserialize array untuk penyimpanan di DB

Kunjungi http://php.net/manual/en/function.serialize.php

Dari Manual PHP:

Lihat di bawah "Kembali" di halaman

Mengembalikan string yang berisi representasi aliran byte dari nilai yang dapat disimpan di mana saja.

Perhatikan bahwa ini adalah string biner yang mungkin menyertakan byte nol, dan perlu disimpan serta ditangani seperti itu. Misalnya, keluaran serialize () umumnya harus disimpan dalam bidang BLOB dalam database, daripada bidang CHAR atau TEXT.

Catatan: Jika Anda ingin menyimpan html ke dalam blob, pastikan untuk menyandikannya base64 atau dapat merusak fungsi serialisasi.

Contoh pengkodean:

$YourSerializedData = base64_encode(serialize($theHTML));

$YourSerializedData sekarang siap disimpan dalam blob.

Setelah mendapatkan data dari blob Anda perlu base64_decode lalu unserialize Contoh decoding:

$theHTML = unserialize(base64_decode($YourSerializedData));
seaBass
sumber
8

Cara terbaik, yang saya temukan sendiri adalah menyimpan array sebagai string data dengan karakter pemisah

$array = array("value1", "value2", "value3", "...", "valuen");
$array_data = implode("array_separator", $array);

$query = "INSERT INTO my_tbl_name (id, array_data) VALUES(NULL,'" . $array_data . "');";

Anda kemudian dapat mencari data, disimpan dalam array Anda dengan kueri sederhana

$query = "SELECT * FROM my_tbl_name WHERE array_data LIKE '%value3%'";

gunakan fungsi explode () untuk mengubah string "array_data" menjadi array

$array = explode("array_separator", $array_data);

Perhatikan bahwa ini tidak berfungsi dengan larik multidimensi dan pastikan bahwa "pemisah_ larik" Anda unik dan tidak ada dalam nilai larik.

Hati-hati !!! jika Anda hanya akan mengambil data formulir dan memasukkannya ke dalam database, Anda akan terjebak, karena data formulir tersebut tidak aman untuk SQL! Anda harus menangani nilai formulir Anda dengan mysql_real_escape_string atau jika Anda menggunakan MySQLi mysqli :: real_escape_string atau jika nilainya adalah integer atau boolean cast (int) (boolean) pada mereka

$number = (int)$_POST['number'];
$checked = (boolean) $_POST['checked'];

$name = mysql_real_escape_string($db_pt, $_POST['name']);
$email = mysqli_obj->real_escape_string($_POST['email']);
Harry
sumber
Dalam kasus saya, saya rasa ini adalah pilihan terbaik untuk saya.
Imtiaz
6

Serialisasi dan unserialize cukup umum untuk itu. Anda juga dapat menggunakan JSON melalui json_encode dan json_decode untuk format yang tidak terlalu spesifik untuk PHP.

ceejayoz
sumber
5

Seperti disebutkan sebelumnya - Jika Anda tidak perlu mencari data di dalam array, Anda dapat menggunakan serialize - tetapi ini "hanya php". Jadi saya akan merekomendasikan untuk menggunakan json_decode / json_encode - tidak hanya untuk kinerja tetapi juga untuk keterbacaan dan portabilitas (bahasa lain seperti javascript dapat menangani data json_encoded).

Sebastian Lasse
sumber
3

Uhh, saya tidak tahu mengapa semua orang menyarankan serialisasi array.

Saya katakan, cara terbaik adalah dengan menyesuaikannya dengan skema database Anda. Saya tidak tahu (dan Anda tidak memberi petunjuk) tentang arti semantik sebenarnya dari data dalam array Anda, tetapi umumnya ada dua cara untuk menyimpan urutan seperti itu

create table mydata (
  id int not null auto_increment primary key,
  field1 int not null,
  field2 int not null,
  ...
  fieldN int not null
)

Dengan cara ini Anda menyimpan array Anda dalam satu baris.

create table mydata (
    id int not null auto_increment primary key,
    ...
)

create table myotherdata (
    id int not null auto_increment primary key,
    mydata_id int not null,
    sequence int not null,
    data int not null
)

Kerugian dari metode pertama adalah, jelas, jika Anda memiliki banyak item dalam array Anda, bekerja dengan tabel itu bukanlah hal yang paling elegan. Ini juga tidak praktis (mungkin, tetapi juga cukup tidak elegan - cukup buat kolom menjadi nullable) untuk bekerja dengan urutan dengan panjang variabel.

Untuk metode kedua, Anda dapat memiliki urutan dengan panjang berapa pun, tetapi hanya satu jenis. Anda dapat, tentu saja, membuat satu jenis varchar atau sesuatu dan membuat serial item dari array Anda. Bukan hal terbaik untuk dilakukan, tetapi tentu saja lebih baik, daripada membuat serial seluruh array, bukan?

Apa pun itu, salah satu metode ini mendapatkan keuntungan yang jelas karena dapat mengakses elemen urutan yang sewenang-wenang dan Anda tidak perlu khawatir tentang serialisasi array dan hal-hal buruk seperti itu.

Adapun mendapatkannya kembali. Nah, dapatkan baris / urutan baris yang sesuai dengan kueri dan, baik, gunakan loop .. bukan?

shylent
sumber
Terkadang sebuah array benar-benar sesuai. Jika Anda hanya akan mengaksesnya sebagai atribut dari objek pertama, maka itu masuk akal.
Matchu
1
Saya harus tidak setuju dalam istilah yang paling parah - tampaknya agak tidak tepat bagi saya untuk menyimpan acak, tidak terstruktur (php "array" sebenarnya bukan array, kan?), Gumpalan data yang tidak diketik dalam database relasional . Apa yang akan Anda gunakan untuk pemisah, jika array Anda mungkin memiliki string di dalamnya? Ini hanya mencari masalah dengan berbagai cara. Dalam 99,9% kasus, ada cara lain yang lebih alami. Saya akan membuat tebakan liar di sini dan menyarankan, bahwa kasus penanya tidak termasuk dalam 0,1% sisanya.
shylent
2
Sebenarnya, terkadang sangat tepat untuk menyimpan array dalam sebuah field di DB. Contohnya adalah metadata seperti tabel 'variabel' global di mana plugin & modul sistem dapat menyimpan berbagai macam pengaturannya. tabel yang menyimpan data 'sesi' arbitrer mungkin paling baik diterapkan menggunakan bidang yang menampung larik asosiatif kunci / nilai. serialize dan unserialize (yang merupakan jawaban yang benar) urus pemisah. periksa beberapa dari beberapa proyek open source yang sukses & populer, seperti WordPress atau Drupal - dan Anda akan melihat bahwa array terkadang disimpan di DB seperti ini
Scott Evernden
@ Scott Evernden: Saya rasa Anda benar. php bukanlah bahasa "utama" saya, jadi saya menilai solusi dari perspektif desain database. Jika yang Anda gambarkan benar-benar cara yang umum untuk melakukan hal-hal seperti itu (di php), biarlah. Namun tidak membuat saya menyukainya :)
shylent
5
TIDAK PERNAH tepat untuk menyimpan larik dalam bidang di DB. Ini adalah pelanggaran bukan bentuk normal keempat, bentuk normal ketiga atau bahkan bentuk normal kedua: itu adalah PELANGGARAN BENTUK NORMAL PERTAMA. Jika Anda tidak dapat mengikuti bahkan pada bentuk normal pertama, ada sesuatu yang sangat salah dengan aplikasi Anda. Itu berlaku untuk Drupal dan Wordpress; jika mereka melakukan ini tentu saja bukan karena aspek aplikasi mereka dirancang dengan baik .. Saya memiliki argumen ini di pekerjaan terakhir saya, dan karena XCart melakukan omong kosong ini, hal itu membuat sesuatu yang seharusnya mungkin, malah sangat sulit.
Dexygen
2

Anda dapat menyimpan array Anda sebagai json.
ada dokumentasi untuk tipe data json: https://dev.mysql.com/doc/refman/5.7/en/json.html
Saya pikir ini adalah solusi terbaik, dan akan membantu Anda menjaga kode Anda lebih mudah dibaca dengan menghindari fungsi gila .
Saya berharap ini bermanfaat untuk Anda.

Roberto Murguia
sumber
0

Yup, serialize / unserialize adalah hal yang paling sering saya lihat di banyak proyek open source.

Eduardo
sumber
0

Saya akan menyarankan menggunakan implode / meledak dengan karakter yang Anda tahu tidak akan terkandung dalam salah satu item array individu. Kemudian simpan dalam SQL sebagai string.

pengguna1478500
sumber
3
Pertanyaan ini diajukan 3 tahun yang lalu dan memiliki jawaban yang diterima. Anda mungkin akan lebih terbantu jika menjawab pertanyaan baru atau pertanyaan tanpa jawaban.
MDrollette
0

periksa fungsi implode, karena nilainya ada dalam array, Anda ingin memasukkan nilai array ke dalam kueri mysql yang memasukkan nilai ke dalam tabel.

$query = "INSERT INto hardware (specifications) VALUES (".implode(",",$specifications).")";

Jika nilai dalam larik adalah nilai teks, Anda perlu menambahkan tanda kutip

$query = "INSERT INto hardware (specifications) VALUES ("'.implode("','",$specifications)."')";

mysql_query($query);

Selain itu, jika Anda tidak ingin nilai duplikat, alihkan "IN ke" menjadi "IGNORE" dan hanya nilai unik yang akan dimasukkan ke dalam tabel.

j0k
sumber
Jika Anda memiliki kunci utama, Anda tidak akan mendapatkan duplikat dengan MASUKKAN KE DALAM. Jika Anda tidak memiliki kunci utama atau indeks, ABAIKAN tidak ada bedanya.
Peter Lindqvist
0

Anda dapat memasukkan objek berseri (array) ke mysql, contoh serialize($object)dan Anda dapat menghapus contoh objekunserialize($object)

Vildan Bina
sumber
-5

Daripada menyimpannya ke database, simpan ke file lalu panggil nanti.

Apa yang dilakukan banyak aplikasi php (seperti sugarcrm) adalah menggunakan var_export untuk menggemakan semua data array ke file. Inilah yang saya gunakan untuk menyimpan data konfigurasi saya:

private function saveConfig() {
    file_put_contents($this->_data['pathtocompileddata'],'<?php' . PHP_EOL . '$acs_confdata = ' . var_export($this->_data,true) . ';');        
}

Saya pikir ini adalah cara yang lebih baik untuk menyimpan data Anda!

AntonioCS
sumber
Ini cara lain, belum tentu lebih baik.
Peter Lindqvist
Memang. Saya hanya berpikir bahwa mengakses file jauh lebih mudah daripada meminta database untuk mengambil data array dan kemudian menginisialisasi array. Dengan cara ini Anda hanya memasukkan file dan selesai.
AntonioCS