【问题标题】:How to solve cannot use string offset as an array error in PHP?如何解决PHP中不能使用字符串偏移作为数组错误?
【发布时间】:2015-04-22 17:38:23
【问题描述】:

我想一次将多个数据添加到表中,但我的代码给出了一个错误,提示“不能将字符串偏移量用作数组”。我附上了我的代码。谁能帮我解决这个问题?

$issuedate=$_POST['issuedate'];
$member=$_POST['member'];
$bno[0]['TitleNo'] = $_POST['bno'];
$bno[1]['TitleNo'] = $_POST['bno1'];
$bno[2]['TitleNo'] = $_POST['bno2'];
$bno[3]['TitleNo'] = $_POST['bno4'];                        
$returndate = $_POST['returndate'];

for($i=0; $i<4; $i++)
{
    $sql5 = mysqli_query($db, "INSERT INTO borrow(TitleNo,MemberID,IssueDate,dueDate,ReturnDate) VALUES ('".$bno[$i]['TitleNo']."','$member','$issuedate','$returndate')");
}

if ($sql5)
{
    echo '<h4 class="message">Add New Book Copies! </h4>'; // echo $test;   
}
else
{
    echo 'Fail.';
}

【问题讨论】:

  • 错误在哪一行?
  • 您也可以使用数组作为输入的名称属性,让您的生活更轻松。而且你有一个 sql 注入问题。
  • 看起来 $bno 在此代码之前分配了字符串而不是数组。
  • 开始...开始观看视频(如 Laracast)并阅读教程以获得清晰且可重用的代码!另一方面......只需添加“$bno = array();”

标签: php mysql database mysqli


【解决方案1】:

您可能正在将字符串分配给$bno 变量,因此它会动态变为string 类型。更多信息here。关于这个例子你应该

  1. $bno = array();
  2. 转义所有数据库输入(或者更好的是,使用prepared statements
  3. if..else 放在for 循环中更有意义

这样

$bno = array();

$mysqli_conn = mysqli_connect("localhost", "user", "password", "schema");

$issuedate = mysqli_real_escape_string($mysqli_conn, $_POST['issuedate']);
$member = mysqli_real_escape_string($mysqli_conn, $_POST['member']);
$bno[0]['TitleNo'] = mysqli_real_escape_string($mysqli_conn, $_POST['bno']);
$bno[1]['TitleNo'] = mysqli_real_escape_string($mysqli_conn, $_POST['bno1']);
$bno[2]['TitleNo'] = mysqli_real_escape_string($mysqli_conn, $_POST['bno2']);
$bno[3]['TitleNo'] = mysqli_real_escape_string($mysqli_conn, $_POST['bno4']);                        
$returndate = mysqli_real_escape_string($mysqli_conn, $_POST['returndate']);

for($i=0; $i<4; $i++)
{
    $sql = mysqli_query($db, "INSERT INTO borrow(TitleNo,MemberID,IssueDate,dueDate,ReturnDate) VALUES ('".$bno[$i]['TitleNo']."','".$member."','".$issuedate."','".$returndate."')");

    if ($sql)
    {
        echo '<h4 class="message">Add New Book Copies! </h4>'; // echo $test;   
    }
    else
    {
        echo 'Fail.';
    }
}

【讨论】:

  • 您的代码中有错误。在程序样式中使用 mysqli_real_escape_string 时,您应该传递数据库实例。
  • mysqli_real_escape_string 使用错误!请检查文档并修复您的代码。
  • 抱歉,打字速度有点快。编辑了答案。
【解决方案2】:

您在之前的一些代码中将 $bno 设置为字符串。 您可以做的快速修复是:

  1. $bno 更改为其他内容,例如 $book
$book[0]['TitleNo'] = $_POST['bno'];  
$book[1]['TitleNo'] = $_POST['bno1'];
//..
  1. $bno 设置为新数组,然后分配值
$bno = array();
$bno[0]['TitleNo'] = $_POST['bno'];  
$bno[1]['TitleNo'] = $_POST['bno1'];  
//...

附加说明

顺便说一句,最好以某种方式转义您在数据库中输入的值。你可以使用 mysqli_real_escape_string

只需为所有值赋值即可:

$bno[0]['TitleNo'] = mysqli_real_escape_string($db, $_POST['bno']);

阅读来源

http://php.net/manual/en/mysqli.real-escape-string.php

【讨论】:

    【解决方案3】:

    您应该看看prepared statementsbind params。当您执行插入语句时,您选择五列并且只插入四个值。

     $sql5 = mysqli_query($db, "INSERT INTO borrow(TitleNo,MemberID,IssueDate,dueDate,ReturnDate) VALUES ('".$bno[$i]['TitleNo']."','$member','$issuedate','$returndate')");
    

    正如@jeroen 提到的,您的代码存在 sql-injection 问题,请阅读更多关于 sql-injection here 的信息。

    我已经使用准备好的语句和绑定参数创建和示例。注意:

    $stmt->bind_param('sssss',$bno[$i]['TitleNo'], $member, $issuedate, $dueDate, $returndate);
    

    'sssss' 仅用于演示目的,我假设 dueDate 和 returndate 列是 datetime 类似的东西。

    $DBServer = 'localhost';
    $DBUser  = 'root';
    $DBPass = 'root';
    $DBName = 'borrow';
    
    $conn = new mysqli($DBServer, $DBUser, $DBPass, $DBName);
    
    $sql = ' INSERT INTO borrow (TitleNo,MemberID,IssueDate,dueDate,ReturnDate) VALUES (?,?,?,?,?)';
    
    $TitleNo = $bno[0]['TitleNo'];
    $member = 'MemberID';
    $issuedate = 'issuedate';
    $dueDate = 'dueDate';
    $returndate = 'returndate';
    
    /* Prepare statement */
    $stmt = $conn->prepare($sql);
    if($stmt === false) {
    trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR);
    }
    
    
    for( $i= 0; $i < count($bno); $i++){
    /* Bind parameters. s = string, i = integer, d = double,  b = blob */
    $stmt->bind_param('sssss',$bno[$i]['TitleNo'], $member, $issuedate, $dueDate, $returndate);
    
    /* Execute statement */
    $stmt->execute();
    }
    if( $stmt->affected_rows > 0 ){
        echo '<h4 class="message">Add New Book Copies!</h4>';
    }
    
    $stmt->close();
    

    但是我不确定使用 for 循环对 db 进行大规模插入是否是最佳实践。

    【讨论】:

      【解决方案4】:

      初始化您的数组(即,$bno 可能在您的代码中初始化为一个字符串,导致您看到的错误),转义输入并执行单个 INSERT(而不是 4,您只检查结果最后一个):-

      <?php 
      $bno = array();
      $sql_array = array();
      $issuedate = mysqli_real_escape_string($db, $_POST['issuedate']);
      $member = mysqli_real_escape_string($db, $_POST['member']);
      $bno[0]['TitleNo'] = mysqli_real_escape_string($db, $_POST['bno']);
      $bno[1]['TitleNo'] = mysqli_real_escape_string($db, $_POST['bno1']);
      $bno[2]['TitleNo'] = mysqli_real_escape_string($db, $_POST['bno2']);
      $bno[3]['TitleNo'] = mysqli_real_escape_string($db, $_POST['bno4']);                        
      $returndate = mysqli_real_escape_string($db, $_POST['returndate']);
      
      foreach($bno AS $abno)
      {
          $sql_array = "('".$bno['TitleNo']."','$member','$issuedate','$returndate')"
      }
      $sql5 = mysqli_query($db, "INSERT INTO borrow(TitleNo,MemberID,IssueDate,dueDate,ReturnDate)
              VALUES ".implode(', ', $sql_array));            
      if ($sql5) 
      {
          echo '<h4 class="message">Add New Book Copies!</h4>';
          // echo $test;
      } 
      else
      {
          echo 'Fail.';
      }
      

      这确实表明数据库可以进一步规范化,因为您插入了多行,除了一个值外,它们都是相同的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多