简体   繁体   English

预备语句始终返回false

[英]Prepared statement return false always

While trying to insert data into the database using prepared statement the prepared statement always returns false and not complete the connection. 在尝试使用prepared语句将数据插入数据库时​​,prepared语句始终返回false,并且不会完成连接。

I'm using this connection on cpanel (not sure if that's related) tried to change the order tried to change the data type. 我在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(); $ sql-> execute(); always return false and nothing has been inserted in the database. 始终返回false,并且数据库中未插入任何内容。

As I said in the comments: 正如我在评论中所说:

Well you have 14 ? 好吧,你有14 ? and 11 s by my count. 我数了11 s OR sssssssssss and ?????????????? sssssssssss?????????????? Which as most of us know, is gonna throw an error as your placeholder count doesn't match your values 正如我们大多数人所知,由于占位符计数与您的值不匹配,会抛出错误

If you can put your data in an array you can use that array to build your query. 如果可以将数据放入数组中,则可以使用该数组来构建查询。

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);

Lets walk thought this a bit 让我们想一想

Basically you can create your arguments with the same length as the $data with these 2 pieces of code: 基本上,您可以使用以下两段代码创建与$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

Then the real magic happens here with the ... "variadic" (variable length arguments): 然后,真正的魔力就在这里发生了... “可变”(可变长度参数):

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

In PHP v5.6+ you can just inject the data using ... in and it will unwind it for you. PHP v5.6+您可以使用... in注入数据,它将为您解开数据。 Or in other words, put each array item in as a new argument. 换句话说,将每个数组项作为新参数放入。


For the fields (columns) 对于字段(列)

If you want to do the fields too, that is a bit more tricky. 如果您也想做这些字段,那会比较棘手。 You have to be careful of what is in those if you put that data directly into the SQL. 如果将数据直接放入SQL,则必须小心其中的内容。 For example a User could edit the keys used in a $_POST request in such a way as to do SQLInjection if you just concatenate the Post Keys into the SQL. 例如,如果您仅将Post Keys连接到SQL,则用户可以以执行SQLInjection的方式编辑$_POST请求中使用的key。

One of the simplest ways to solve this is to have a whitelist of fields like so (matched to the column names): 解决此问题的最简单方法之一是拥有一个类似这样的字段白名单(与列名匹配):

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

You can use array_intersect_key to retain only the data you want for the query (assuming the data has matched keys). 您可以使用array_intersect_key仅保留查询所需的数据(假设数据具有匹配的键)。 The keys will be safe to use now in the query as they must match what is in the $whitelist . 这些键现在可以安全地在查询中使用,因为它们必须与$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);

Other things 其他事情

The only thing this doesn't cover is if you want all the fields in $whitelist to always be present. 唯一不涉及的是如果您希望$whitelist所有字段始终存在。 You can solve this with validation of the incoming data or you can merge in some empty fields to insure that all the data is present. 您可以通过验证传入的数据来解决此问题,也可以合并到一些空字段中以确保所有数据都存在。

  $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"=>""]

Array fill keys (similar to array fill from before) takes a list of keys, and adds a value in for each. 数组填充键(类似于之前的数组填充)获取一个键列表,并为每个键添加一个值。 So that gives us an array who's keys are the the values of $whitelist and an empty string for each items value. 这样就给我们提供了一个数组,其键是$whitelist的值,以及每个项目值的空字符串。 I call this a default row. 我将此称为默认行。

Then we merge this with our original data. 然后,将其与原始数据合并。 Data in the first array will be overwritten by any data with matched keys for the second array ( $_POST in my example). 第一个数组中的数据将被第二个数组(在我的示例中$_POST )具有匹配键的任何数据覆盖。 So if a key is present like id in the example above, it overwrite the empty one. 因此,如果在上面的示例中存在像id这样的密钥,它将覆盖空密钥。

Anything not overwritten keeps the empty value from the default row we made. 任何未覆盖的内容都会保留我们创建的默认行中的空值。 Then the array intersect key removes anything extra like before. 然后,数组相交键会删除之前的所有多余内容。

*PS I didn't test any of this so please forgive any syntax errors. * PS我没有测试任何一个,因此请原谅任何语法错误。

Enjoy! 请享用!

You have to execute the statement once you've bound the data. 绑定数据后,必须执行该语句。

$sql->execute();

The number of parameters are also inconsistent as pointed out by the comments. 如注释所指出的,参数的数量也不一致。

I think you don't execute your query calling the execute method : 我认为您不执行调用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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM