PHP dizisi MySQL'e kaydedilsin mi?


88

Bir dizi veriyi tek bir mysql alanına kaydetmenin iyi bir yolu nedir?

Ayrıca mysql tablosunda bu diziyi sorguladığımda, onu dizi biçimine geri döndürmenin iyi bir yolu nedir?

Cevabı seri hale getirmek ve serileştirmek mi?

Yanıtlar:


88

İyi yokBir diziyi tek bir alanda saklamanın yolu .

İlişkisel verilerinizi incelemeniz ve şemanızda uygun değişiklikleri yapmanız gerekir. Bu yaklaşıma bir referans için aşağıdaki örneğe bakın.

Eğer varsa gereken tek alana diziyi kaydetmek sonra serialize()ve unserialize()işlevleri hile olacaktır. Ancak gerçek içerik üzerinde sorgulama yapamazsınız.

Serileştirme işlevine alternatif olarak ayrıca json_encode()ve vardır json_decode().

Aşağıdaki diziyi düşünün

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

Veritabanına kaydetmek için bunun gibi bir tablo oluşturmanız gerekir

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

Kayıtlarla çalışmak için bunun gibi sorgular yapabilirsiniz (ve evet bu bir örnek, dikkatli olun!)

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()İşlevi, bir mysql bağlantısı kaynağı döndürür

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

26

Genel olarak, evet, serileştirmek ve serileştirmek gitmenin yoludur.

Verileriniz basitse, virgülle ayrılmış bir dize olarak kaydetmek, depolama alanı için muhtemelen daha iyi olacaktır. Örneğin, dizinizin yalnızca bir sayı listesi olacağını biliyorsanız, implode / explode kullanmalısınız. Bu arasındaki fark bu 1,2,3ve a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

Değilse, tüm vakalar için işi serileştirin ve serileştirin.


24
Okuyucu, sen burada olduğuna göre, ben sadece, yıllarca edindiğim deneyim sayesinde, bunun gerçekten yapılacak yol olmadığını keşfettiğimi duyurmak için zaman ayıracağım. Kabul edilen cevap çok daha güçlü bir yaklaşımdır.
Maç

4
Buradasın, okuyucu, bunun sizin ihtiyaçlarınıza bağlı olduğunu sizinle paylaşacağım. Dizi değerlerinizle sorgulama yapmanız gerekmiyorsa ve çok HIZLI bir şeye ihtiyacınız varsa, verilerinizi tek bir alanda güvenli bir şekilde saklayabilirsiniz (soru açıkça belirtilmiştir), üzerine bir birincil anahtar yapıştırın ve gidin. . Uygulamanın ne olduğunu merak ediyorsanız: verileri her 5 dakikada bir cron'lanan bir kuyruğa itmek. Başka bir cron, çok daha fazla zaman alan dizileri oluşturur. Sıra, hesaplanan verileri alır ve üçüncü taraf bir API'ye aktarır. Bunu yapmanın daha iyi bir yolu yok.
Iculous Kurtulmak

1
@RidIculous Kafam karıştı, kendi kişisel başvurunuzdan mı yoksa sorunun sorulmasına neden olan uygulamadan mı bahsediyorsunuz?
Peter Lindqvist

1
Bu benim ifademin öncülüyle alakasız olsa da, "Uygulamanın ne olduğunu merak ediyorsanız" öneki netlik sağlamalıdır.
Iculous Kurtulmak

10

PHP serileştirme işlevini kullanın:

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

Ancak, bunun gibi basit diziler kullanıyorsanız, implode ve explode da kullanabilirsiniz. New yerine boş bir dizi kullanın.


9

Bir DB'de depolama için diziyi seri hale getir / seri hale getir

Http://php.net/manual/en/function.serialize.php adresini ziyaret edin

PHP Kılavuzundan:

Sayfadaki "Geri Dön" altına bakın

Herhangi bir yerde depolanabilen değerin bayt akışı gösterimini içeren bir dize döndürür.

Bunun, boş baytlar içerebilen ve bu şekilde depolanması ve işlenmesi gereken bir ikili dizge olduğuna dikkat edin. Örneğin, serialize () çıktısı genellikle CHAR veya TEXT alanı yerine veritabanındaki bir BLOB alanında depolanmalıdır.

Not: html'yi bir blob içinde saklamak istiyorsanız, onu base64 olarak kodladığınızdan emin olun, aksi takdirde serileştirme işlevini bozabilir.

Örnek kodlama:

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

$YourSerializedData artık blob içinde depolanmaya hazır.

Blob'dan veri aldıktan sonra base64_decode yapmanız ve ardından Örnek kod çözme işlemini kaldırmanız gerekir:

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

8

Kendi kendime bulduğum en iyi yol, diziyi ayırıcı karakterlerle veri dizesi olarak kaydetmek.

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

Daha sonra basit bir sorgu ile dizinizde depolanan verileri arayabilirsiniz.

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

"array_data" dizesini diziye dönüştürmek için explode () işlevini kullanın

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

bunun çok boyutlu dizilerle çalışmadığını unutmayın ve "dizi_ ayırıcınızın" benzersiz olduğundan ve dizi değerlerinde bulunmadığından emin olun.

Dikkatli ol !!! Sadece bir form verisi alıp veri tabanına koyarsanız, tuzağa düşersiniz, çünkü form verileri SQL için güvenli değildir! form değerinizi mysql_real_escape_string ile veya MySQLi mysqli :: real_escape_string kullanıyorsanız veya değer tamsayı veya boolean cast (int) (boolean) ise bunlarla işlemelisiniz

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

Benim durumumda, sanırım bu benim için en iyi seçenek.
Imtiaz

6

Seri hale getirmek ve serileştirmek bunun için oldukça yaygındır. Daha az PHP'ye özgü bir biçim için JSON'u json_encode ve json_decode aracılığıyla da kullanabilirsiniz.


5

Daha önce belirtildiği gibi - Dizi içinde veri aramanız gerekmiyorsa, serileştirmeyi kullanabilirsiniz - ancak bu "yalnızca php" dir. Bu yüzden json_decode / json_encode kullanmanızı tavsiye ederim - sadece performans için değil, aynı zamanda okunabilirlik ve taşınabilirlik için de (javascript gibi diğer diller json_encoded verileri işleyebilir).


3

Uhh, neden herkesin diziyi seri hale getirmeyi önerdiğini bilmiyorum.

Diyorum ki, en iyi yol onu veritabanı şemanıza sığdırmaktır. Dizinizdeki verilerin gerçek anlamsal anlamı hakkında hiçbir fikrim yok (ve hiçbir ipucu vermediniz), ancak genellikle bunun gibi dizileri depolamanın iki yolu vardır.

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

Bu şekilde dizinizi tek bir satırda depolamış olursunuz.

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
)

İlk yöntemin dezavantajı, açıkçası, dizinizde çok sayıda öğe varsa, bu tabloyla çalışmanın en zarif şey olmayacağıdır. Değişken uzunluktaki dizilerle çalışmak da pratik değildir (mümkün, ancak oldukça uygun değildir - sadece sütunları null yapılabilir yapın).

İkinci yöntem için, herhangi bir uzunlukta, ancak yalnızca bir türden dizilere sahip olabilirsiniz. Tabii ki, o bir türü varchar veya başka bir şey yapabilir ve dizinizin öğelerini serileştirebilirsiniz. Yapılacak en iyi şey değil, ama kesinlikle tüm diziyi serileştirmekten daha iyi, değil mi?

Her iki durumda da, bu yöntemlerden herhangi biri, dizinin rastgele bir öğesine erişebilme avantajına sahip olur ve dizileri serileştirme ve bunun gibi çirkin şeyler konusunda endişelenmenize gerek kalmaz.

Geri almaya gelince. Peki, bir sorgu ile uygun satır / satır sırasını alın ve bir döngü kullanın .. değil mi?


Bazen bir dizi gerçekten uygundur. Ona yalnızca ilk nesnenin bir niteliği olarak erişecekseniz, bu mantıklıdır.
Maç

1
En ciddi terimlerle aynı fikirde değilim - ilişkisel bir veritabanında rastgele, yapılandırılmamış (php "dizileri" aslında diziler değil, değil mi?), Türsüz veri bloblarını depolamak benim için oldukça uygunsuz görünüyor . Dizinizde herhangi bir dizge varsa, yine de bir ayırıcı için ne kullanacaksınız? Bu sadece birçok farklı şekilde sorun istemektir. Vakaların% 99,9'unda başka, daha doğal bir yol var. Burada çılgınca bir tahminde bulunacağım ve soruyu soranın durumunun kalan% 0.1'e düşmediğini önereceğim.
shylent

2
Aslında, bazen DB'deki bir alanda bir dizi depolamak çok uygundur. Örnek, bir sistem eklentilerinin ve modüllerinin çeşitli ayarlarını saklayabileceği küresel bir 'değişkenler' tablosu gibi meta veriler olabilir. rastgele 'oturum' verilerini depolayan bir tablo, en iyi bir ilişkisel anahtar / değer dizisini tutan bir alan kullanılarak uygulanabilir. serileştirin ve serileştirmeyin (doğru cevap budur) ayırıcılarla ilgilenin. WordPress veya Drupal gibi birkaç başarılı ve popüler açık kaynaklı projeden bazılarını kontrol edin - ve dizilerin bazen bu şekilde
DB'de

@Scott Evernden: Sanırım haklısın. php benim "ana" dilim değil, bu yüzden çözümü veritabanı tasarımı perspektifinden değerlendiriyordum. Tarif ettiğiniz şey gerçekten bu tür şeyleri yapmanın (php'de) yaygın bir yoluysa, o zaman öyle olsun. Beni sevmiyor yine de :)
shylent

5
Bir diziyi bir DB'deki bir alanda saklamak ASLA uygun değildir. Dördüncü normal biçim, üçüncü normal biçim ve hatta ikinci normal biçim ihlali değil: BİRİNCİ NORMAL FORM İHLALİDİR. İlk normal forma bile uyamazsanız, başvurunuzda ciddi bir yanlışlık vardır. Bu Drupal ve Wordpress için geçerli; eğer bunu yaparlarsa, kesinlikle uygulamalarının o yönünün iyi tasarlanmış olmasından kaynaklanmıyor .. Bu argümanı son işimde yaşadım ve XCart bu saçmalığı yaptığı için mümkün olması gereken bir şeyi yaptı, bunun yerine son derece zor.
Dexygen


0

Evet, seri hale getir / seri hale getir, birçok açık kaynak projesinde en çok gördüğüm şey.


0

Implode / explode'u, herhangi bir dizi öğesinde bulunmayacağını bildiğiniz bir karakterle kullanmanızı öneririm. Ardından bunu bir dizge olarak SQL'de saklayın.


3
Bu soru 3 yıl önce soruldu ve kabul edilmiş bir cevabı var. Yeni soruları veya soruları cevapsız cevaplamayı daha yararlı bulabilirsiniz.
MDrollette

0

implode işlevini kontrol edin, değerler bir dizi içinde olduğundan, dizinin değerlerini, değerleri bir tabloya ekleyen bir mysql sorgusuna koymak istersiniz.

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

Dizideki değerler metin değerleriyse, tırnak işaretleri eklemeniz gerekir

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

mysql_query($query);

Ayrıca, yinelenen değerler istemiyorsanız, "INto" yu "IGNORE" olarak değiştirin ve tabloya yalnızca benzersiz değerler eklenecektir.


Bir birincil anahtarınız varsa, INSERT INTO ile yinelenen anahtarlar elde edemezsiniz. Bir birincil anahtarınız veya dizininiz yoksa IGNORE herhangi bir fark yaratmaz.
Peter Lindqvist

0

serialize($object)mysql'ye serileştirilmiş nesne (dizi) ekleyebilirsiniz, örnek ve nesne örneğini silebilirsinizunserialize($object)


-5

Veritabanına kaydetmek yerine bir dosyaya kaydedin ve daha sonra çağırın.

Pek çok php uygulamasının yaptığı şey (sugarcrm gibi), dizinin tüm verilerini bir dosyaya yankılamak için sadece var_export kullanmaktır. Yapılandırma verilerimi kaydetmek için kullandığım şey bu:

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

Sanırım bu, verilerinizi kaydetmenin daha iyi bir yolu!


Başka bir yol, ille de daha iyi değil.
Peter Lindqvist

Aslında. Sadece dosyaya erişmenin, dizi verilerini almak ve ardından diziyi başlatmak için veritabanını sorgulamaktan çok daha kolay olduğunu düşünüyorum. Bu şekilde sadece dosyayı dahil edersiniz ve biter.
AntonioCS
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.