2013-07-24 13 views
8

Şu anda sadece iki öğeyle küçük bir arama formum var: search adında bir metin girişi ve param adında bir "seçim" kutusu. Bu kutuda seçilen seçenek, DB'mdeki hangi tablo sütununun alınacağını seçmek için bir parametre olarak kullanılmalıdır. mysql_ fonksiyonlarını kullanmaBir mysqli kullanarak bir WHERE yan tümcesine nasıl bir değişken geçirebilirim?

, böyle bir şey yapılabilir:

$param = $_POST['param' ]; 
$search = $_POST['search']; 

$query = 'SELECT * FROM table WHERE $param LIKE "%$search%"'; 

Ama mysqli_ sözdizimi ile çalışmak için alınamıyor. Ben hazır deyimleri kullanmaya çalışıyorum, ancak şimdiye kadar yaptığım en iyi şudur:

$param = $_POST['param' ]; 
$search = $_POST['search']; 

if($param == 'first_name') 
{ 
    if($prep = $link->prepare('SELECT * FROM table 
           WHERE first_name 
           LIKE CONCAT("%", ?, "%")')) 
    { 
     $prep->bind_param('s', $search); 
     $prep->execute(); 
     $prep->bind_result($first_name, $last_name); 

     while($prep->fetch()) 
      echo $first_name . ' ' . $last_name; 

     $prep->close(); 
    } 
    else 
     echo 'Error while preparing statement.'; 
} 
else if($param == 'last_name') 
{ 
    ... 
} 

Ama sadece else if s bir demet kullanarak ben sütun sürü zorunda, eğer özel bir yeri tekrarlayan ve verimsiz görünmektedir sap.

Denediğim ilk şey, parametre bağlama - ... WHERE ? LIKE ... ve $prep->bind_param('ss', $param, $search) - oldu, ancak işe yaramadı (ve hala nedenini bilmiyorum).

Bunu daha zekice yapmanın bir yolu var mı?

+0

+1 sorularınızı biçimlendirme güzel! –

+0

.... WHERE ". $ Param." LIKE ....genel olarak sql deyimleriyle ne yapıyorum – Adsy2010

+1

Sütun adları için yer tutucuları, bildiğim kadarıyla kullanamazsınız, bu yüzden işe yaramadı. –

cevap

3

sadece olası params karmasını oluşturmak, her param için aynı SQL kodunu kullanıyorsanız: (CGI param name => table column name)

$params = array(
    'first_name' => 'first_name', 
    'last_name' => 'last_name', 
); 

Size SQL enjeksiyonu korunur olarak bakış güvenlik açısından çok daha iyi.

Sonra karma sütun adını almak ve sorguda koymak - ve eğer-s kurtulmak edeceğiz:

$name = $params[$param]; 
$sql = "SELECT * FROM table 
WHERE 
$name LIKE ?"; 

if($prep = $link->prepare($sql)) 
{ 
    $prep->bind_param('s', "%$search%"); 
    ... 

@Akam dediği gibi, CONCAT gerek ("% Sorgudaki ",?", "%") - değeri hemen yüzdelerle bağlamak daha iyidir. yerine sorguda daha örn -

+1

sorgusuna uymaya gerek yok: 'bind_param ('s',"% $ arama% ")' –

+1

@Akam Yanıtı iyileştirildi – user4035

+0

Etkin ve temiz. Teşekkür ederim! – Renato

2

PHP kılavuzunda bu örneğe göre

http://www.php.net/manual/en/mysqli-stmt.bind-param.php#108790

Sen bağlayıcı dize değişkenine '%' eklemek iyi görünüyor Örneğin:

Test edilmedi, ancak mantıklı bir çözüm gibi görünüyor.

+0

Bu, dinamik alan adı kullanma problemini çözmeyecek, ancak çözümüne olan örneğini çözecektir. –

+0

Üzgünüm, haklısın, noktayı özledim. Basitçe $ param dizesini, sütun adı yerine sorgu dizesiyle değiştirirdim. Bununla birlikte, ilk başta içerik üzerinde ciddi filtreleme uygularım. $ Unsafe_col_name = "/ [^ a-z-0-9 \\\ _] /"; $ Param = preg_replace ("$ unsafe_col_name", "", $ param); –

1

Sütun adları için yer tutucularını kullanamazsınız, bu nedenle sütun adlarını normal olarak birleştirmeniz gerekir.

$allowed_params = array('first_name', 'last_name', etc); 

$param = $_POST['param' ]; 
$search = $_POST['search']; 


if(!in_array($param, $allowed_params)) 
    die("Uh oh, the request seems to have an invalid param!"); 

if($prep = $link->prepare('SELECT * FROM table 
          WHERE ' . $param . ' 
          LIKE ?')) 
{ 
    $prep->bind_param('s', '%' . $search . '%'); 
    $prep->execute(); 
    $prep->bind_result($first_name, $last_name); 

    while($prep->fetch()) 
     echo $first_name . ' ' . $last_name; 

    $prep->close(); 
} 
else 
    echo 'Error while preparing statement.'; 

Ayrıca concat ifadesinin kaldırılmasını not edin ve yerine PHP'de birleştirerek: Eğer bir süre liste yaklaşımı öneririm sütun sınırlı sayıda var çünkü Ancak, yerine sadece mysqli ile kaçan. Bu, hazırlanmış ifadeler için sunucuya geldiğinde (aslında hazırlanmış ifadelerin korunması) gerçekte bir araya gelmediği için önemlidir, dolayısıyla joker karakterler $search dizgisiyle gönderilmedikçe düzgün çalışmayacaktır.

İlgili konular