2013-08-26 40 views
1

我正在創建一個自定義類,以使連接和使用mysql更容易。我創建了很多功能,除了一部分外,其他部分都可以正常工作我似乎無法弄清楚如何確定一個字符串是一個實際的字符串,還是如果它是一個mysql函數來引用它或不是。我把一個函數放在一起,我可以傳遞兩個參數,它會插入到數據庫中。第一個參數是要插入的表,而第二個參數是列,值對的數組。也許這個代碼示例會幫助你更多地理解。注意:我已經轉義了所有字符串,並刪除了該代碼以顯示問題的簡單性。MySQL確定是否將單引號括在一個字符串中如果自定義類的MySQL函數

function insert($table,array $array){ 
    $table = "`".$table."`"; 
    $columns = ""; 
    $values = ""; 
    foreach($array as $key => $value){ 
     $columns = ($columns=="") ? "`".$key."`" : $columns.", `".$key."`"; 
     if($value===NULL || $value=="NULL"){ 
      $value = "NULL"; 
     } else { 
      $value = "'".$value."'"; 
     } 
     $values = ($values=="") ? "".$value."" : $values.", ".$value.""; 
    } 
    $query = "INSERT INTO $table ($columns) VALUES ($values)"; 
    return $this->query($query); 
} 

這裏是兩種不同的用途和預期的結果或每個

$data = array(
    "first_name"=>"John", 
    "last_name"=>"Doe", 
    "entry_date"=>"2013-08-26" 
); 
$MyClass->insert("people",$data); 

的一個例子將執行

INSERT INTO `people` (`first_name`,`last_name`,`entry_date`) VALUES ('John','Doe','2013-08-26') 

其然而預期以下用途:

$data = array(
    "first_name"=>"John", 
    "last_name"=>"Doe", 
    "entry_date"=>"NOW()" 
); 
$MyClass->insert("people",$data); 

將執行爲

INSERT INTO `people` (`first_name`,`last_name`,`entry_date`) VALUES ('John','Doe','NOW()') 

這將無法正常工作,因爲如果MySQL函數帶有引號,將不會運行。我知道這可能是一個小的安全風險,因爲如果沒有發現它會允許用戶的功能。有沒有更好的方法來做到這一點,或者MySQL函數不允許在這樣的類插入函數中使用?如果有一個正則表達式可以幫助查找並允許mysql函數,那麼這可能是一個解決方案。如果再沒有這樣的正則表達式存在一個可能性是從頭寫一個,我一點兒也不太好......

編輯:

,我將在此期間使用另一種解決方案是讓形成數組時PHP的日期。如果可能的話,我想盡可能使用MySQL函數。這是我解決了問題,但不知道如何我更喜歡目前的代碼:

$data = array(
    "first_name"=>"John", 
    "last_name"=>"Doe", 
    "entry_date"=>date('Y-m-d H:i:s'), 
); 
$MyClass->insert("people",$data); 
+2

'if(preg_match(「/^[A-Z _] + \(。*?\)/」,$ value)){// Mysql function}' – phpisuber01

+0

@ phpisuber01 perfect reg-ex,I [tested] (http://regexpal.com/)它和它完美的作品。如果您想將其轉換爲答案,那麼我會考慮將其作爲所有其他答案中的最佳答案,但到目前爲止,這似乎正在起作用。 – amaster

回答

2

我實現了一個功能做你1.0幾年前的描述Zend框架的東西。

我通過區分純字符串標量和包含字符串的對象解決了這個問題。

$data = array(
    "first_name"=>"John", 
    "last_name"=>"Doe", 
    "entry_date"=>new Zend_Db_Expr("NOW()") 
); 
$MyClass->insert("people",$data); 

這樣我的框架,可以告訴大家,我打算待處理 作爲SQL字符串PHP字符串之間的差額(即報價),與即在一個對象捲起的字符串。

if($value===NULL || $value=="NULL"){ 
    $value = "NULL"; 
} else if ($value instanceof Zend_Db_Expr) { 
    $value = $value->__toString(); // no quotes 
} else { 
    $value = "'".$value."'"; 
} 

PS:有些人可能會建議你使用而不將逃脫變量,你正在做的查詢參數。我同意這個建議,但它與你的原始問題確實沒什麼關係,所以我不會去討論它。還有許多其他StackOverflow問題使用查詢參數進行處理。


回覆您的評論:

你可以使用正則表達式專門匹配NOW()和所有其他MySQL的功能和對待他們,但你怎麼能插入文本字符串「NOW()」(沒有結果該名稱的功能)?

答案:你不能 - 就像你不能在你當前的代碼中插入文字字符串「NULL」,因爲你已經把這個詞當作一種特殊情況。

您需要某種方法來區分SQL表達式NOW()和「NOW()」。僅僅因爲你今天不需要將這個字符串插入到你的數據庫中並不意味着你永遠不需要這個能力。請記住,您正在設計這個insert()函數,用於針對當前或未來的任何表。

你實際上正在設計一個框架。

+0

感謝您的建議和答案。將更多的代碼寫入數組本身以形成對象,然後測試該對象並不是我想要通過它去做的路線。它需要成爲一個解決方案,可以讓數組獨立並將其固定在類本身中。我沒有使用Zend Framework。這可能適用於其他人,但不適用於我自己。抱歉。 – amaster

+0

+1表示可能是一個需求,但不適用於此應用程序,但我將爲其他應用程序重用此自定義框架,因此需要考慮這些問題。 – amaster

0

感謝@ phpisuber1的正則表達式if(preg_match("/^[A-Z_]+\(.*?\)/", $value)) { // Mysql function }和謝謝@BillKarwin,與你們兩個我已經創建了一個解決方案與您的輸入組合。

對我的解決方案是添加一些更多的參數到我的類函數與默認值告訴函數是否插入爲MySQL函數或作爲字符串,以及是否插入爲NULL或作爲字符串"NULL"請參閱下面的新函數:

/** 
* @param string $table the table to insert array into 
* @param array $array contains column => value pairs values may be MySQL Function 
* @param bool $mysql_functions true to insert mysql functions as function, false to insert mysql functions as string 
* @param bool $null_string_is_null true to insert string "NULL" as NULL; false to insert string "NULL" as string "NULL" 
* @param bool $empty_string_is_null true to insert string "" as NULL; false to insert string "" as string "" 
* @return bool Returns FALSE on failure. For successful queries will return TRUE. 
*/ 
function insert($table,array $array,$mysql_functions = false,$null_string_is_null = true,$empty_string_is_null = false){ 
    $table = "`".$table."`"; 
    $columns = ""; 
    $values = ""; 
    foreach($array as $key => $value){ 
     $columns = ($columns=="") ? "`".$key."`" : $columns.", `".$key."`"; 
     if($value===NULL || ($value=="NULL" && $null_string_is_null) || ($value=="" && $empty_string_is_null)){ 
      $value = "NULL"; 
     } else if(preg_match("/^[A-Z_]+\(.*?\)/", $value) && $mysql_functions) { 
      $value = "".$value.""; 
     } else { 
      $value = "'".$value."'"; 
     } 
     $values = ($values=="") ? "".$value."" : $values.", ".$value.""; 
    } 
    $query = "INSERT INTO $table ($columns) VALUES ($values)"; 
    return $this->query($query); 
} 

這又不是完整的功能,因爲我出於安全考慮而遺漏了部分內容,但這是一個正常運行的版本。我將研究查詢參數,看看它是否會提高這個和其他函數的安全性,而不是連接轉義字符串。此功能的默認參數適用於我的默認使用,並且可以更改以供將來使用。總的來說,我認爲這是最好的解決方案。如果你認爲否則我會很樂意閱讀你的評論。

相關問題