Php 准备好的语句总是返回false

Php 准备好的语句总是返回false,php,mysqli,Php,Mysqli,当尝试使用prepared语句将数据插入数据库时,prepared语句总是返回false,并且不会完成连接 我正在cpanel上使用此连接(不确定是否相关)尝试更改顺序尝试更改数据类型 $conn = mysqli_connect($servername,$username,$password,$database); // $sql=$conn->prepare("insert into asset 'assetName'=?, 'grp' ='?' ,'Descrip' = '?'

当尝试使用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,并且数据库中未插入任何内容。

绑定数据后,必须对语句进行修改

$sql->execute();

正如注释所指出的,参数的数量也不一致。

我认为您没有调用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 

正如我在评论中所说:

嗯,据我计算,你有14个和11个。或者
ssssss
?????
,我们大多数人都知道,这会抛出一个错误,因为占位符计数与值不匹配

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

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”(可变长度参数):

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


用于字段(列)

如果你也想做字段,那就有点棘手了。如果将数据直接放入SQL中,则必须小心其中的内容。例如,用户可以编辑
$\u POST
请求中使用的键,如果您只是将POST键连接到SQL中,就可以执行SQLInjection

解决此问题的最简单方法之一是创建一个这样的字段白名单(与列名匹配):

您可以使用
array\u intersect\u 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
的值,每个items值都有一个空字符串。我称之为默认行

然后我们将其与原始数据合并。第一个数组中的数据将被第二个数组中具有匹配键的任何数据覆盖(在我的示例中为
$\u POST
)。因此,如果在上面的示例中出现一个键,如
id
,它将覆盖空键

任何未被覆盖的内容都会保留我们创建的默认行中的空值。然后,数组的intersect键会像以前一样删除任何额外的内容

*PS我没有测试这些,因此请原谅任何语法错误


享受吧

您应该检查以找出失败的原因。这是您的脚本的完整版本吗?我想你没有提到execute方法?你现在还没有执行任何东西。据我统计,你有14个
和11个
s
。或者
ssssss
??????????
,正如我们大多数人所知,这将抛出一个错误,因为占位符计数与您的值不匹配。
stru repeat('s',count($data))
@Quasimodo'sclone-Doah,好建议我应该看到这一点。我只是在偷懒。我更新了它。我确实执行了它,但忘了附加它。
我确实执行了
-从来没有说过你没有。占位符的数量是错误的。谢谢所有人,但我确实执行了。谢谢所有人,但我确实执行了它。
 //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);
  $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"=>""]