Ilişkilendirilebilir bir dizi kullanarak iyi bir PHP veritabanı insert yazmak nasıl

5 Cevap php

PHP, ben alan / değer çiftleri bir ilişkisel dizi içerdiği verileri kullanarak bir veritabanına eklemek istediğiniz.

Example:

$_fields = array('field1'=>'value1','field2'=>'value2','field3'=>'value3');

Aşağıdaki gibi çıkan SQL insert bakmak gerekir:

INSERT INTO table (field1,field2,field3) VALUES ('value1','value2','value3');

Ben aşağıdaki PHP tek-liner ile geldi:

mysql_query("INSERT INTO table (".implode(',',array_keys($_fields)).") VALUES (".implode(',',array_values($_fields)).")");

Bu birleşmeli dizinin anahtarlarını ve değerlerini ayırır ve implodes virgülle ayrılmış bir dize oluşturmak için. Sorun kaçmak ya da veritabanına yerleştirildi değerleri alıntı olmamasıdır. $_fields, aşağıdaki ihtiva etmesi tehlike göstermek için, düşünün:

$_fields = array('field1'=>"naustyvalue); drop table members; --");

Aşağıdaki SQL oluşturulmuş olacak:

INSERT INTO table (field1) VALUES (naustyvalue); drop table members; --;

Neyse ki, multiple queries are not supported, yine alıntı ve kaçan SQL enjeksiyon açıklarını önlemek için gereklidir.

How do you write your PHP Mysql Inserts?

Note: PDO or mysqli prepared queries aren't currently an option for me because the codebase already uses mysql extensively - a change is planned but it'd take alot of resources to convert?

5 Cevap

I değiştirecek tek şey, okunabilirliği amacıyla sprintf'i kullanmak olacaktır

$sql = sprintf(
    'INSERT INTO table (%s) VALUES ("%s")',
    implode(',',array_keys($_fields)),
    implode('","',array_values($_fields))
);
mysql_query($sql);

ve değerler kaçtı emin olun.

Bunda yanlış bir şey yok. Ben aynı şeyi.

Ama aksi takdirde SQL injection açığı bakıyoruz, emin mysql_escape() yapmak ve sorguda sopa değerleri alıntı.

Pratikte yerine bir sorgu dizesi bina, kendisi dizi geçebileceği durumda dönüşümlü, sen parametrized sorguları kullanabilirsiniz.

En iyi uygulama bir ORM (Doktrini 2.0), bir ActiveRecord uygulaması (Doktrin 1.0, redbean), ya da bir TableGateway desen uygulaması (Zend_Db_Table, uskur) kullanmak ya da budur. Bu araçlar hayatınızı çok kolaylaştıracak ve sizin için ağır kaldırma çok idare, ve SQL enjeksiyon korunmanıza yardımcı olabilir olacaktır.

Bunun dışında ne yaptığınızı ile doğal olarak yanlış bir şey var farklı yerlerde işlevselliğini tekrar böylece, sadece, bir sınıf veya fonksiyon içine uzak soyut buna isteyebilirsiniz.

Kullanarak sprintf Galen olarak bahsettiği kandırmak bir previous answer, ben aşağıdaki kod ile geldi:

$escapedfieldValues = array_map(create_function('$e', 'return mysql_real_escape_string(((get_magic_quotes_gpc()) ? stripslashes($e) : $e));'), array_values($_fields));

$sql = sprintf('INSERT INTO table (%s) VALUES ("%s")', implode(',',array_keys($_fields)), implode('","    ',$escapedfieldValues));

mysql_query($sql);

Bu kaçtı ve alıntı ekleme üretir. Ayrıca magic_quotes_gpc açık ya da kapalı olmasından bağımsız baş edebiliyor. Ben yeni bir PHP v5.3.0 anonymous functions kullanılan ama eski PHP yüklemeleri çalıştırmak gerekiyorsa kod güzel olabilir.

Bu kod, orijinal (ve yavaş) ama o daha güvenli olduğunu biraz daha uzundur.

(Kabul cevap) NULL ile bir sorun "" değerler boş dizeye dönüştürülür vardır. Yani bu NULL tırnak işaretleri olmadan NULL olur, düzeltmedir:

function implode_sql_values($vals)
{
    $s = '';
    foreach ($vals as $v)
        $s .= ','.(($v===NULL)?'NULL':'"'.mysql_real_escape_string($v).'"');

    return substr($s, 1);
}

Kullanımı:

implode_sql_values(array_values( array('id'=>1, 'nick'=>'bla', 'fbid'=>NULL) ));
// =='"1","bla",NULL'