使用PDO出現了一個問題,當字元的最後一個為\的時候插入資料庫失敗,很是費解,參數綁定怎麼會出現如此的問題?
error_reporting(E_ALL);header("content-type:text/html;charset=utf8");$params = array();$params[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES UTF8';$dsn = "mysql:host=localhost;dbname=test;port=3306;";$dbh = new PDO($dsn, 'root', '123456', $params);$sql = 'INSERT INTO `fav_ls_1` (`uid`,`fid`,`type`,`title_md5`,`title`,`url`,`order`,`addtime`) VALUES (:uid,:fid,:type,:title_md5,:title,:url,:order,:addtime)';$bind = array( ':uid' => 5919639, ':fid' => 0, ':type' => 1, ':title_md5' => "0886c9605d1424e656c85736b4730e7f", ':title' => '\\敵\\', ':url' => "http://www.2345.com/?ie", ':order' => 0, ':addtime' => 1449156098,);$sth = $dbh->prepare($sql);if(false===$sth->execute($bind)){ print_r( $sth->errorInfo () );}else{ echo $dbh->lastInsertId();}
錯誤碼如下:
Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'http://www.2345.com/?ie','0','1449156098')' at line 1 )
補充一下:
這個設定了$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);就可以運行了,但是在其他sql上也會出現莫名其妙的錯誤。
回複內容:
使用PDO出現了一個問題,當字元的最後一個為\的時候插入資料庫失敗,很是費解,參數綁定怎麼會出現如此的問題?
error_reporting(E_ALL);header("content-type:text/html;charset=utf8");$params = array();$params[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES UTF8';$dsn = "mysql:host=localhost;dbname=test;port=3306;";$dbh = new PDO($dsn, 'root', '123456', $params);$sql = 'INSERT INTO `fav_ls_1` (`uid`,`fid`,`type`,`title_md5`,`title`,`url`,`order`,`addtime`) VALUES (:uid,:fid,:type,:title_md5,:title,:url,:order,:addtime)';$bind = array( ':uid' => 5919639, ':fid' => 0, ':type' => 1, ':title_md5' => "0886c9605d1424e656c85736b4730e7f", ':title' => '\\敵\\', ':url' => "http://www.2345.com/?ie", ':order' => 0, ':addtime' => 1449156098,);$sth = $dbh->prepare($sql);if(false===$sth->execute($bind)){ print_r( $sth->errorInfo () );}else{ echo $dbh->lastInsertId();}
錯誤碼如下:
Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'http://www.2345.com/?ie','0','1449156098')' at line 1 )
補充一下:
這個設定了$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);就可以運行了,但是在其他sql上也會出現莫名其妙的錯誤。
感謝king同學的答案:
我的問題是PHP環境是大於5.3.6的,需要在dsn中設定charset=utf8,低於PHP5.3.6版本的使用SET NAMES UTF8
修改代碼如下解決:
public function connect($config, $linkNum) { if(empty($this->_link[$linkNum])) { if(empty($config)) $config = $this->config; $params = array(); // PHP<=5.3.6使用此方法設定編碼 if(!empty($config['db_charset']) && version_compare(PHP_VERSION,'5.3.6','<=')) $params[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . $config['db_charset']; // 長連結 if(isset($config['db_params']['pconnect']) && $config['db_params']['pconnect'] == true) $params[PDO::ATTR_PERSISTENT] = true; // @link http://zhangxugg-163-com.iteye.com/blog/1835721 5.3.6下有bug if(version_compare(PHP_VERSION,'5.3.6','<=')) $params[PDO::ATTR_EMULATE_PREPARES] = false; // 禁用類比預先處理語句 // php 5.3.6+在PDO的DSN中指定charset屬性 $dsn_charset = version_compare(PHP_VERSION, '5.3.6', '>') ? "charset={$config['db_charset']};" : ''; $dsn = "{$config['db_type']}:dbname={$config['db_name']};host={$config['db_host']};port={$config['db_port']};" . $dsn_charset; $this->dbName = $config['db_name']; $this->dbType = $config['db_type']; try { $this->_link[$linkNum] = new PDO($dsn, $config['db_user'], $config['db_pass'], $params); $this->_link[$linkNum]->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); $this->_link[$linkNum]->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); } catch(PDOException $e) { throw new CException($e->getMessage()); } } $this->_linkId = $this->_link[$linkNum]; return $this->_linkId;}
注意,把ATTR_EMULATE_PREPARES設定為true並沒有真正的用參數綁定功能,這隻是類比
本來預設也是false,不明白為何你要開啟它
MySQL的參數綁定是通過prepare語句實現的,如果你的資料庫版本支援(MySQL 4.1以上版本支援),不應該開啟這個選項!
你的問題很可能是因為這個類比參數綁定,也就是本質上其實是通過轉義實現的出現的錯誤(推測,未驗證)
請見
http://php.net/manual/zh/pdo.setattribute.php