บันทึกอาร์เรย์ PHP ไปยัง MySQL หรือไม่


88

วิธีที่ดีในการบันทึกอาร์เรย์ของข้อมูลลงในฟิลด์ mysql เดียวคืออะไร?

นอกจากนี้เมื่อฉันค้นหาอาร์เรย์นั้นในตาราง mysql วิธีที่ดีในการทำให้อาร์เรย์กลับมาอยู่ในรูปแบบอาร์เรย์คืออะไร?

เป็นซีเรียลไลซ์และยกเลิกการเข้ารหัสคำตอบหรือไม่

คำตอบ:


88

ไม่มีวิธีที่ดีในการจัดเก็บอาร์เรย์ลงในฟิลด์เดียว

คุณต้องตรวจสอบข้อมูลเชิงสัมพันธ์ของคุณและทำการเปลี่ยนแปลงที่เหมาะสมกับสคีมาของคุณ ดูตัวอย่างด้านล่างสำหรับการอ้างอิงถึงแนวทางนี้

หากคุณต้องบันทึกอาร์เรย์ลงในช่องเดียวฟังก์ชันserialize()and unserialize()จะทำเคล็ดลับ แต่คุณไม่สามารถดำเนินการสอบถามเกี่ยวกับเนื้อหาจริงได้

ในฐานะที่เป็นทางเลือกให้กับฟังก์ชั่นเป็นอันดับที่ยังมี และjson_encode()json_decode()

พิจารณาอาร์เรย์ต่อไปนี้

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

หากต้องการบันทึกลงในฐานข้อมูลคุณต้องสร้างตารางเช่นนี้

$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)
    )');

ในการทำงานกับเรกคอร์ดคุณสามารถดำเนินการค้นหาเช่นนี้ได้ (และใช่นี่คือตัวอย่างระวัง!)

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();

connect()ฟังก์ชันส่งกลับเป็นทรัพยากรที่เชื่อมต่อ MySQL

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

26

โดยทั่วไปแล้วการทำให้เป็นซีเรียลไลซ์และการยกเลิกการเข้ารหัสเป็นวิธีที่จะไป

หากข้อมูลของคุณเป็นแบบธรรมดาการบันทึกเป็นสตริงที่คั่นด้วยจุลภาคน่าจะดีกว่าสำหรับพื้นที่จัดเก็บ หากคุณรู้ว่าอาร์เรย์ของคุณจะเป็นเพียงรายการตัวเลขคุณควรใช้การระเบิด / ระเบิด มันคือความแตกต่างระหว่าง1,2,3และa:3:{i:0;i:1;i:1;i:2;i:2;i:3;}และ

ถ้าไม่เช่นนั้นให้ทำให้เป็นอนุกรมและยกเลิกการเข้ารหัสสำหรับทุกกรณี


24
เนื่องจากคุณอยู่ที่นี่ผู้อ่านฉันจะใช้เวลาในการประกาศว่าฉันได้ค้นพบจากประสบการณ์หลายปีแล้วว่านี่ไม่ใช่ทางที่จะไปจริงๆ คำตอบที่ได้รับการยอมรับคือแนวทางที่แข็งแกร่งกว่ามาก
Matchu

4
ไซน์คุณอยู่ที่นี่ผู้อ่านฉันจะแบ่งปันกับคุณว่ามันขึ้นอยู่กับความต้องการของคุณ หากคุณไม่จำเป็นต้องค้นหาด้วยค่าอาร์เรย์ของคุณและต้องการสิ่งที่เร็วมากคุณสามารถจัดเก็บข้อมูลของคุณแบบนี้ได้อย่างปลอดภัยในช่องเดียว (ซึ่งเป็นสิ่งที่คำถามระบุไว้อย่างชัดเจน) ให้ตบคีย์หลักลงไป . หากคุณสงสัยว่าแอปพลิเคชันคืออะไร: การส่งข้อมูลไปยังคิวที่ได้รับ cron ทุก 5 นาที cron อีกตัวสร้างอาร์เรย์ซึ่งใช้เวลามากกว่า คิวจะดึงข้อมูลที่คำนวณแล้วและส่งต่อไปยัง API ของบุคคลที่สาม ไม่มีวิธีที่ดีกว่าในการทำ
Rid Iculous

1
@RidIculous ฉันสับสนคุณกำลังพูดถึงแอปพลิเคชันส่วนตัวของคุณเองหรือแอปพลิเคชันที่นำไปสู่คำถามที่ถูกถาม?
Peter Lindqvist

1
ในขณะที่ไม่เกี่ยวข้องกับหลักฐานของคำพูดของฉันคำนำหน้า "หากคุณสงสัยว่าแอปพลิเคชันคืออะไร" ควรให้ความชัดเจน
Rid Iculous

10

เพียงใช้ฟังก์ชัน PHP แบบอนุกรม:

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

อย่างไรก็ตามหากคุณใช้อาร์เรย์แบบธรรมดาเช่นนั้นคุณอาจใช้การระเบิดและการระเบิดได้เช่นกันใช้อาร์เรย์ว่างแทนใหม่


9

Serialize / Unserialize array สำหรับการจัดเก็บใน DB

ไปที่http://php.net/manual/en/function.serialize.php

จากคู่มือ PHP:

ดูใต้ "Return" บนหน้า

ส่งคืนสตริงที่มีการแสดงค่าไบต์สตรีมที่สามารถเก็บไว้ที่ใดก็ได้

โปรดทราบว่านี่เป็นสตริงไบนารีซึ่งอาจมีไบต์ว่างและจำเป็นต้องจัดเก็บและจัดการเช่นนี้ ตัวอย่างเช่นโดยทั่วไปเอาต์พุต serialize () ควรถูกเก็บไว้ในฟิลด์ BLOB ในฐานข้อมูลแทนที่จะเป็นฟิลด์ CHAR หรือ TEXT

หมายเหตุ: หากคุณต้องการจัดเก็บ html ลงในหยดตรวจสอบให้แน่ใจว่าได้เข้ารหัส base64 ไม่เช่นนั้นอาจทำให้ฟังก์ชันซีเรียลไลซ์เสียหายได้

ตัวอย่างการเข้ารหัส:

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

$YourSerializedData ตอนนี้พร้อมที่จะเก็บไว้ในหยดแล้ว

หลังจากรับข้อมูลจาก blob แล้วคุณต้อง base64_decode จากนั้นยกเลิกการเข้ารหัสตัวอย่างการถอดรหัส:

$theHTML = unserialize(base64_decode($YourSerializedData));

8

วิธีที่ดีที่สุดที่ฉันพบกับตัวเองคือบันทึกอาร์เรย์เป็นสตริงข้อมูลที่มีอักขระคั่น

$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 . "');";

จากนั้นคุณสามารถค้นหาข้อมูลที่จัดเก็บไว้ในอาร์เรย์ของคุณด้วยคำค้นหาง่ายๆ

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

ใช้ฟังก์ชัน Explode () เพื่อแปลงสตริง "array_data" เป็นอาร์เรย์

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

โปรดทราบว่าสิ่งนี้ใช้ไม่ได้กับอาร์เรย์หลายมิติและตรวจสอบให้แน่ใจว่า "array_separator" ของคุณไม่ซ้ำกันและไม่มีอยู่ในค่าอาร์เรย์

ระวัง !!! หากคุณจะใช้ข้อมูลฟอร์มและวางในฐานข้อมูลคุณจะตกอยู่ในกับดักเนื่องจากข้อมูลแบบฟอร์มไม่ปลอดภัยต่อ SQL! คุณต้องจัดการค่าฟอร์มของคุณด้วยmysql_real_escape_stringหรือถ้าคุณใช้ MySQLi mysqli :: real_escape_string หรือถ้าค่าเป็นจำนวนเต็มหรือบูลีน cast (int) (บูลีน)

$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']);

ในกรณีของฉันฉันคิดว่านี่เป็นตัวเลือกที่ดีที่สุดสำหรับฉัน
Imtiaz

6

การทำให้เป็นอนุกรมและการยกเลิกการเข้ารหัสเป็นเรื่องปกติสำหรับสิ่งนั้น คุณยังสามารถใช้ JSON ผ่าน json_encode และ json_decode สำหรับรูปแบบเฉพาะ PHP ที่น้อยลง


5

ดังที่กล่าวไว้ก่อนหน้านี้ - หากคุณไม่ต้องการค้นหาข้อมูลภายในอาร์เรย์คุณสามารถใช้ serialize ได้ แต่เป็น "php เท่านั้น" ดังนั้นฉันขอแนะนำให้ใช้json_decode / json_encode - ไม่เพียง แต่เพื่อประสิทธิภาพเท่านั้น แต่ยังรวมถึงความสามารถในการอ่านและการพกพา (ภาษาอื่น ๆ เช่น javascript สามารถจัดการข้อมูล json_encoded)


3

เอ่อฉันไม่รู้ว่าทำไมทุกคนถึงแนะนำให้เรียงลำดับอาร์เรย์

ฉันบอกว่าวิธีที่ดีที่สุดคือใส่ลงในสคีมาฐานข้อมูลของคุณ ฉันไม่รู้ (และคุณไม่ได้ให้เบาะแส) เกี่ยวกับความหมายเชิงความหมายที่แท้จริงของข้อมูลในอาร์เรย์ของคุณ แต่โดยทั่วไปมีสองวิธีในการจัดเก็บลำดับเช่นนั้น

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

ด้วยวิธีนี้คุณจะจัดเก็บอาร์เรย์ของคุณในแถวเดียว

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
)

ข้อเสียของวิธีแรกคือเห็นได้ชัดว่าหากคุณมีหลายรายการในอาร์เรย์การทำงานกับตารางนั้นจะไม่ใช่สิ่งที่หรูหราที่สุด นอกจากนี้ยังทำไม่ได้ (เป็นไปได้ แต่ก็ค่อนข้างไม่ดีเช่นกัน - เพียงแค่ทำให้คอลัมน์เป็นโมฆะ) เพื่อทำงานกับลำดับความยาวตัวแปร

สำหรับวิธีที่สองคุณสามารถมีลำดับความยาวเท่าใดก็ได้ แต่จะมีเพียงประเภทเดียวเท่านั้น แน่นอนคุณสามารถสร้าง varchar ประเภทหนึ่งหรืออะไรก็ได้และทำให้เป็นลำดับรายการของอาร์เรย์ของคุณ ไม่ใช่สิ่งที่ดีที่สุดที่จะทำ แต่ดีกว่าการจัดลำดับอาร์เรย์ทั้งหมดใช่ไหม?

ไม่ว่าจะด้วยวิธีใดวิธีการใดก็ได้รับประโยชน์อย่างชัดเจนในการเข้าถึงองค์ประกอบของลำดับโดยพลการและคุณไม่ต้องกังวลเกี่ยวกับการจัดลำดับอาร์เรย์และสิ่งที่น่าเกลียดเช่นนั้น

สำหรับการกลับมา เอาแถว / ลำดับของแถวที่เหมาะสมพร้อมคิวรีและใช้ลูป .. ใช่ไหม?


บางครั้งอาร์เรย์ก็เหมาะสมจริงๆ หากคุณแค่จะเข้าถึงมันเป็นแอตทริบิวต์ของวัตถุชิ้นแรกก็สมเหตุสมผลดี
Matchu

1
ฉันต้องไม่เห็นด้วยในแง่ที่รุนแรงที่สุด - ดูเหมือนว่าค่อนข้างไม่เหมาะสมสำหรับผมที่จะเก็บสุ่มที่ไม่มีโครงสร้าง (PHP "อาร์เรย์" ไม่ได้จริงอาร์เรย์ที่ทุกคนใช่มั้ย?) blobs untyped ของข้อมูลในฐานข้อมูลเชิงสัมพันธ์ คุณจะใช้อะไรเป็นตัวคั่นถ้าอาร์เรย์ของคุณอาจมีสตริงใด ๆ อยู่ นี่เป็นเพียงการถามปัญหาในรูปแบบต่างๆ ใน 99,9% ของกรณีมีวิธีอื่นที่เป็นธรรมชาติกว่า ฉันจะเดาอย่างดุเดือดที่นี่และแนะนำว่ากรณีของผู้ถามจะไม่ตกอยู่ใน 0.1% ที่เหลือ
shylent

2
ที่จริงแล้วบางครั้งการจัดเก็บอาร์เรย์ในช่องในฐานข้อมูลก็เหมาะสมมาก ตัวอย่างจะเป็นข้อมูลเมตาเช่นตาราง 'ตัวแปร' ส่วนกลางซึ่งปลั๊กอินและโมดูลของระบบสามารถจัดเก็บการตั้งค่าต่างๆได้ ตารางที่เก็บข้อมูล 'เซสชัน' ตามอำเภอใจอาจนำไปใช้งานได้ดีที่สุดโดยใช้ฟิลด์ที่มีอาร์เรย์ของคีย์ / ค่าที่เชื่อมโยงกัน ทำให้เป็นอนุกรมและยกเลิกการเรียงลำดับ (ซึ่งเป็นคำตอบที่ถูกต้อง) ดูแลตัวคั่น ตรวจสอบโครงการโอเพ่นซอร์สที่ประสบความสำเร็จและเป็นที่นิยมหลายโครงการเช่น WordPress หรือ Drupal และคุณจะเห็นว่าบางครั้งอาร์เรย์จะถูกเก็บไว้ในฐานข้อมูลเช่นนี้
Scott Evernden

@Scott Evernden: ฉันเดาว่าคุณพูดถูก php ไม่ใช่ภาษา "หลัก" ของฉันดังนั้นฉันจึงตัดสินโซลูชันจากมุมมองการออกแบบฐานข้อมูล หากสิ่งที่คุณอธิบายเป็นวิธีการทั่วไปในการทำสิ่งต่างๆ (ใน php) ก็เป็นเช่นนั้น ไม่ทำให้ฉันชอบเลย :)
shylent

5
ไม่เหมาะสมที่จะจัดเก็บอาร์เรย์ในฟิลด์ในฐานข้อมูล มันเป็นการละเมิดที่ไม่ใช่รูปแบบปกติที่สี่รูปแบบปกติที่สามหรือแม้แต่รูปแบบปกติที่สอง: เป็นการละเมิดรูปแบบปกติครั้งแรก หากคุณไม่สามารถปฏิบัติตามแม้กระทั่งรูปแบบปกติครั้งแรกมีบางอย่างผิดปกติกับใบสมัครของคุณ สำหรับ Drupal และ Wordpress ถ้าพวกเขาทำเช่นนี้แน่นอนว่าไม่ใช่เพราะแง่มุมของแอปของพวกเขาได้รับการออกแบบมาอย่างดี .. ฉันมีข้อโต้แย้งนี้ในงานสุดท้ายของฉันและเนื่องจาก XCart ทำเรื่องไร้สาระนี้จึงทำให้บางสิ่งที่ควรจะเป็นไปได้ยากมาก
Dexygen

2

คุณสามารถบันทึกอาร์เรย์ของคุณเป็น json
มีเอกสารสำหรับประเภทข้อมูล json: https://dev.mysql.com/doc/refman/5.7/en/json.html
ฉันคิดว่านี่เป็นทางออกที่ดีที่สุดและจะช่วยให้คุณรักษาโค้ดให้อ่านง่ายขึ้นโดยหลีกเลี่ยงฟังก์ชั่นที่บ้าคลั่ง .
ฉันคาดว่านี่จะเป็นประโยชน์สำหรับคุณ


0

ใช่ซีเรียลไลซ์ / ยกเลิกการเข้ารหัสเป็นสิ่งที่ฉันเห็นมากที่สุดในโครงการโอเพ่นซอร์สมากมาย


0

ฉันขอแนะนำให้ใช้การระเบิด / ระเบิดด้วยอักขระที่คุณรู้ว่าจะไม่มีอยู่ในรายการอาร์เรย์ใด ๆ จากนั้นเก็บไว้ใน SQL เป็นสตริง


3
คำถามนี้ถูกถามเมื่อ 3 ปีก่อนและมีคำตอบที่เป็นที่ยอมรับ คุณอาจพบว่าการตอบคำถามใหม่ ๆ หรือคำถามที่ไม่มีคำตอบนั้นมีประโยชน์มากกว่า
MDrollette

0

ตรวจสอบฟังก์ชั่นการระเบิดเนื่องจากค่าอยู่ในอาร์เรย์คุณต้องการใส่ค่าของอาร์เรย์ลงในแบบสอบถาม mysql ที่แทรกค่าลงในตาราง

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

หากค่าในอาร์เรย์เป็นค่าข้อความคุณจะต้องเพิ่มเครื่องหมายคำพูด

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

mysql_query($query);

นอกจากนี้หากคุณไม่ต้องการให้ค่าซ้ำกันให้เปลี่ยน "INto" เป็น "IGNORE" และจะมีการแทรกเฉพาะค่าที่ไม่ซ้ำกันลงในตาราง


หากคุณมีคีย์หลักคุณจะไม่ซ้ำกับ INSERT INTO อีกต่อไป หากคุณไม่มีคีย์หลักหรือดัชนี IGNORE จะไม่สร้างความแตกต่างใด ๆ
Peter Lindqvist

0

คุณสามารถแทรกอ็อบเจ็กต์ซีเรียลserialize($object)ไลซ์(อาร์เรย์) ไปยัง mysql ตัวอย่างและคุณสามารถยกเลิกการกำหนดขนาดอ็อบเจกต์ได้unserialize($object)


-5

แทนที่จะบันทึกลงในฐานข้อมูลให้บันทึกลงในไฟล์แล้วเรียกใช้ในภายหลัง

แอป php จำนวนมากทำอะไร (เช่น sugarcrm) คือใช้ var_export เพื่อสะท้อนข้อมูลทั้งหมดของอาร์เรย์ไปยังไฟล์ นี่คือสิ่งที่ฉันใช้เพื่อบันทึกข้อมูลการกำหนดค่าของฉัน:

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

ฉันคิดว่านี่เป็นวิธีที่ดีกว่าในการบันทึกข้อมูลของคุณ!


เป็นวิธีอื่นไม่จำเป็นต้องดีกว่า
Peter Lindqvist

แน่นอน. ฉันแค่คิดว่าการเข้าถึงไฟล์นั้นง่ายกว่าการสืบค้นฐานข้อมูลเพื่อดึงข้อมูลอาร์เรย์แล้วเริ่มต้นอาร์เรย์ วิธีนี้คุณเพียงแค่รวมไฟล์และเสร็จสิ้น
AntonioCS
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.