PDO veritabanı soyutlama

2 Cevap php

Birisi bana bu kurulum ile neyin yanlış gittiğini görmek için yardımcı olabilir

I build the @sql query in the function below like this. The extra quotes are setup in the conditions array.

    	$sql .= " WHERE $field = \"$value\"";

Pdo güncelleme fonksiyonu böyle şartlar dizi döngüler.

if (!is_null($conditions))
{
$cond = ' WHERE';
$obj = new CachingIterator(new ArrayIterator($conditions));
foreach($obj as $k=>$v)
{
    $cond .= " $k=$v";
    $cond .= $obj->hasNext() ? ' AND' : '';
}
}

My point to make is that I can not build arrays with values without adding slashes for quotation marks around the values. Otherwise the sql error that is being thrown is that it is an unknown column.

Ben yapabilirim başka bir şey var mı?

Birisi bana bu konuda bazı girdi verebilir misiniz.

edit: the rest off the update function

Where could I bind the values of the conditions array and have them executed also? As I am seeing it now, only the values array is executed? Do I need to loop both arrays and then merge both arrays?

$obj = new CachingIterator(new ArrayIterator($values));

    		$db = db::getInstance();
    		$sql = "UPDATE $table SET \n";
    		foreach( $obj as $field=>$val)
    		{
    			$sql .= "$field= :$field";
    			$sql .= $obj->hasNext() ? ',' : '';
    			$sql .= "\n";
    		}

    		$sql .= $cond ; 
    		$stmt = $db->prepare($sql);

    		// bind de params
    		foreach($values as $k=>$v)
    		{
    			$stmt->bindParam(':'.$k, $v);
    		}


    		$stmt->execute($values );

teşekkürler, Richard

2 Cevap

Kullanmayınız addslashes(). Bu değerleri kaçmak için yetersiz bir şekilde, ve güvenlik hataları bilinir.

Standart SQL çift tırnak sınırlandırılmış tanımlayıcılar için vardır. Dize hazır tek tırnak kullanın.

MySQL varsayılan modu, birbirlerinin tek tırnak ve çift tırnak kullanımı ve geri-tırnak sınırlandırılmış tanımlayıcılar için olanak sağlar. Bu SQL kodunu diğer RDBMS satıcılara daha taşınabilir, hem de kodunuzu okuyan herkes için daha açık hale getirir çünkü Ama, dizeleri için sadece tek tırnak kullanma alışkanlığı içine almak tavsiye.

Mike B anlaşılacağı @ gibi, sorgu parametreleri kullanılmalıdır. Bu kolay ve SQL ifadeleri içine değişkenler interpolating çok daha güvenli.


Sen bindParam() kullanabilir veya execute() işlevi için $values ilişkisel dizi sağlayabilmektedir. Hem yapıyor gereksiz olduğunu.

Eğer execute() yöntemine vermek dizisi : karakter tutucu adını prepending olmak zorunda olmadığını unutmayın:

$stmt = $pdo->prepare("SELECT * FROM MyTable WHERE myfield = :myfield");
// both of the following would work:
$stmt->execute( array(":myfield" => $value ) );
$stmt->execute( array("myfield" => $value ) );

Ayrıca SET fıkra ve WHERE fıkrasında hem parametreleri desteklemek, sana parametre tutucu adlarını belirtmek zaman alanları ayırt öneririm. Bu şekilde (1 eski bir değeri aramak için, ve diğer bir yeni bir değer ayarlamak için) hem bentlerinde aynı alanı başvurursanız, olmaz çatışma.

Belki ":set$field" SET fıkrasında, ve ":where$field" WHERE maddesinde de.


update: Ben aşağıdaki kodu test ettik. Birincisi, ben yerine kullanılan CachingIterator arasında düz diziler kullanın. Ben join() kullanarak beri hasNext() yöntemi kullanmak gerekmez.

$settings = array("myfield" => "value");
$conditions = array("id" => 1);

$sql = "UPDATE $table SET \n";

Sonraki array_map() ve join() yerine döngüler kullanarak bir demo. Ben bu yüzden satır içi kapatma işlevlerini kullanabilirsiniz PHP 5.3.0 kullanıyorum. PHP önceki bir sürümünü kullanıyorsanız, daha önce fonksiyonları bildirmek ve geri aramaları gibi bunları kullanmak gerekecek.

$sql .= join(",",
    array_map(
        function($field) { return "$field = :set$field"; },
        array_keys($settings)
    )
);

if ($conditions)
{
    $sql .= " WHERE "
    . join(" AND ",
        array_map(
            function($field) { return "$field = :where$field"; },
            array_keys($conditions)
        )
    );
}

$stmt = $db->prepare($sql);

I bindParam() çalışmak için alamadım, yerine her zaman bu benim dizideki gerçek değerlerin değerini "1" ekliyor. Yani burada bir ilişkisel dizi hazırlamak ve execute() onu geçmek için kod:

$params = array();
foreach ($settings as $field=>$value) {
    $params[":set$field"] = $value;
}
foreach ($conditions as $field=>$value) {
    $params[":where$field"] = $value;
}

$stmt->execute($params);

Eğer PDO kullanarak ediyorsanız, neden bindParam() kullanmaz ve bindValue() yöntemleri demonstated here?