预备语句始终返回false

时间:2019-04-01 17:18:06

标签: php mysqli

在尝试使用Prepared语句将数据插入数据库时​​,Prepared语句始终返回false并没有完成连接。

我正在cpanel上使用此连接(不确定是否相关)试图更改顺序,尝试更改数据类型。

$conn = mysqli_connect($servername,$username,$password,$database);

// $sql=$conn->prepare("insert into asset 'assetName'=?, 'grp' ='?'  ,'Descrip' = '?'  , 'enteredValue' = '?',  'depreciationRate' = '?','entrydate'='?' 'availability'= '?'  ,'enteredBy' = '?' , 'updatedOn' = '?' , 'isPeriodic' = '?' , 'assetType' = '?','Frequency'='?','ExitDate'='?'");

if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")){

$sql->bind_param("sssssssssss",$name,$group,$value,$depreciation,$entryDate,$availability,$enteredBy,$updatedOn,$isPeriodic,$type,$frequency,$exitDate);

$ sql-> execute(); 始终返回false,并且数据库中未插入任何内容。

3 个答案:

答案 0 :(得分:1)

正如我在评论中所说的:

  

根据我的计算,您有14 ?11 s。或sssssssssss??????????????,正如我们大多数人所知道的那样,由于您的占位符计数与您的值不匹配,会抛出错误

如果您可以将数据放入数组中,则可以使用该数组来构建查询。

if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (".implode(',', array_fill(0,count($data), '?')).")")){
   $sql->bind_param(str_repeat('s', count($data)),...$data);

让我们这样想一下

基本上,您可以使用以下两段代码来创建与$data相同长度的参数:

  implode(',', array_fill(0,count($data), '?')) //implode "?" with ","  equal to the length of data
  str_repeat('s', count($data)) //create 's' equal to the length of data

然后真正的魔术发生在这里,是...“ variadic”(可变长度参数):

 $sql->bind_param(str_repeat('s', count($data)),...$data);

PHP v5.6+中,您可以使用...插入数据,它将为您展开数据。或者换句话说,将每个数组项作为新参数。


用于字段(列)

如果您也想做这些字段,那会比较棘手。如果将数据直接放入SQL,则必须小心其中的内容。例如,如果您仅将Post键连接到SQL中,则用户可以以执行SQLInjection的方式编辑$_POST请求中使用的键。

解决此问题的最简单方法之一是拥有类似这样的字段白名单(与列名匹配):

 //all allowed column names for this query (case sensitive)
 $whitelist = ["id", "assetName", ...];

您可以使用array_intersect_key仅保留查询所需的数据(假设数据具有匹配的键)。这些键现在可以安全地在查询中使用,因为它们必须与$whitelist中的键匹配。

 //remove unknown keys form input data (~ retain only known ones)
 //array_flip($whitelist) = ["id"=>0, "assetName"=>1, ...];
 $data = array_intersect_key($_POST, array_flip($whitelist));

 if($sql = $conn->prepare("INSERT INTO `asset`(`".implode("`,`", array_keys($data))."`)VALUES(".implode(',', array_fill(0,count($data), '?')).")".)){
    $sql->bind_param(str_repeat('s', count($data)),...$data);

其他内容

这唯一不涉及的是如果您希望$whitelist中的所有字段始终存在。您可以通过验证传入的数据来解决此问题,也可以合并到一些空字段中以确保所有数据都存在。

  $default =  array_fill_keys($whitelist, ''); //["id"=>"", "assetName"=>"", ...] ~ create empty "default" row

  //$default['updatedOn'] = date('Y-m-d'); //you can also manually set a value

  $data =  array_intersect_key(
                 array_merge(
                        $default,
                        $_POST  //["id"=>"1", ...] ~ missing assetName
                 ), array_flip($whitelist)); //-> ["id"=>"1","assetName"=>""]

数组填充键(类似于之前的数组填充)获取一个键列表,并为每个键添加一个值。这样就给我们提供了一个数组,其键是$whitelist的值,以及每个项目值的空字符串。我将此称为默认行。

然后将其与原始数据合并。第一个数组中的数据将被第二个数组(在我的示例中为$_POST)具有匹配键的任何数据覆盖。因此,如果在上面的示例中存在像id这样的密钥,它将覆盖空密钥。

任何未覆盖的内容都会保留我们创建的默认行中的空值。然后,数组相交键会删除之前的所有多余内容。

* PS 我没有对此进行任何测试,因此请原谅任何语法错误。

享受!

答案 1 :(得分:0)

绑定数据后,您必须execute语句。

$sql->execute();

注释中指出的参数数量也不一致。

答案 2 :(得分:0)

我认为您不执行调用execute方法的查询:

$conn = mysqli_connect($servername,$username,$password,$database);

// $sql=$conn->prepare("insert into asset 'assetName'=?, 'grp' ='?'  ,'Descrip' = '?'  , 'enteredValue' = '?',  'depreciationRate' = '?','entrydate'='?' 'availability'= '?'  ,'enteredBy' = '?' , 'updatedOn' = '?' , 'isPeriodic' = '?' , 'assetType' = '?','Frequency'='?','ExitDate'='?'");

if($sql = $conn->prepare("INSERT INTO `asset`(`id`, `assetName`, `grp`, `Descrip`, `enteredValue`, `depreciationRate`, `entrydate`, `availability`, `enteredBy`, `updatedOn`, `isPeriodic`, `assetType`, `Frequency`, `ExitDate`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")){

$sql->bind_param("sssssssssss",$name,$group,$value,$depreciation,$entryDate,$availability,$enteredBy,$updatedOn,$isPeriodic,$type,$frequency,$exitDate);
sql->execute();
sql->close(); // close connection