【问题标题】:insert array into mysql (userCake)将数组插入mysql(userCake)
【发布时间】:2015-02-19 16:15:12
【问题描述】:

我正在基于 userCake 源代码建立一个网站。此时我有一个数组,我想插入到我的 MySQL 数据库中。

我从表单中获取数组的数据。这是构建数组的代码:

$pauzes = array();
    foreach($users as $usr)
    {
      $pauzes = array_merge($pauzes, array(
        $usr['username'] => $_POST[$usr['username']]));
    }

当我在这段代码之后调用 print_r($pauzes) 时,可能的输出可能是:

数组([jules] => 12.30-13.00 [marc] => 12.30-13.00 [nick] => 13.30-14.00 [paulo] => --- [kevin] => --- [rick] => --- [sanam] => --- [yvette] => --- [bas] => -- - [布鲁斯] => --- )

('---'表示没有选择时间)

userCake 的工作方式我将不得不使用 bind_param,但我无法发送数组 (???) 我找到了一些如何从数组中获取数据的代码,所以输出应该类似于用户名时间

这是应该将数据写入数据库的函数:

function add_pauze($datum, $pauzes)
{
    GLOBAL $mysqli, $db_table_prefix;

    // array $pauzes opdelen in aparte stukken zodat deze kan worden opgeslagen in de database
    if(is_array($pauzes))
    {
        $data = array();
        foreach($pauzes as $row){
                $naam = mysqli_real_escape_string($mysqli,$row['username']);
                $tijd = mysqli_real_escape_string($mysqli, $row['tijd'] );
                $data[] = "($naam', '$tijd')";
        }
    }
    $stmt = $mysqli->prepare("INSERT INTO " . $db_table_prefix . "pauzes
                                                        (
                                                        datum,
                                                        gegevens
                                                        )
                                                        VALUES
                                                        " . implode(',', $data) ."
                                                        ");
    $stmt->bind_param("ss", $datum, $naam, $tijd);
    $result = $stmt->execute();
    $stmt->close();
    return($result);
}

当我现在尝试插入数据时,我收到了几个带有非法字符串偏移的警告。我相信这是因为 $naam ($row['username']) 和 $tijd ($row['tijd']) 没有在数组中定义?

我尝试将构建数组的代码更改为如下所示:

$pauzes = array();
    foreach($users as $usr)
    {
      $pauzes = array_merge($pauzes, array(
        "username" => $usr['username'] , "tijd" => $_POST[$usr['username']]));
    }

但是我的数组不再正确了:

数组([用户名] => bruce [tijd] => --- )

所以现在我想知道如何将我的数组(右一个在这篇文章的顶部)插入到我的数据库中。

提前致谢!

--- 更新信息---

我更改了构建数组的代码:

$pauzes = array("user" => array(), "pauze" => array());
    foreach($users as $usr)
    {
      array_push($pauzes['user'], $usr['username']);
      array_push($pauzes['pauze'], $_POST[$usr['id']]);

    }

当我执行 print_r($pauzes) 时,输出为:

数组 ( [user] => 数组 ( [0] => jules [1] => marc [2] => nick [3] => paulo [4] => kevin [5] => rick [6] => sanam [7] => yvette [8] => bas [9] => bruce ) [pauze] => 数组 ([0] => 13.30-14.00 [1] => --- [2] => --- [3] => 13.00-13.30 [4] => --- [5] => 12.00-12.30 [6] => --- [7] => --- [8] => -- - [9] => --- ) )

函数 add_pauze 更新如下:

function add_pauze($datum, $pauzes)
{
    GLOBAL $mysqli, $db_table_prefix;

    // array $pauzes opdelen in aparte stukken zodat deze kan worden opgeslagen in de database
    if(is_array($pauzes))
    {
        $data = array();
        foreach($pauzes as $row){
                $naam = $row['user'];
                $tijd =  $row['pauze'];
                $data[] = "('$naam', '$tijd')";
        }
    }
    $stmt = $mysqli->prepare("INSERT INTO " . $db_table_prefix . "pauzes
                                                        (
                                                        datum,
                                                        naam,
                                                        tijd
                                                        )
                                                        VALUES
                                                        " . implode(',', $data) ."
                                                        ");

    $stmt->bind_param("ss", $datum, $naam, $tijd);
    $result = $stmt->execute();
    $stmt->close();
    return($result);
}

当我在这个函数中回显sql语句时,输出为:

INSERT INTO applepauzes ( datum, naam, tijd ) VALUES ('', ''),('', '')

这是因为 userpauze 索引无法识别。

我的数据库中用于表 applepauzes 的列是:

  1. 身份证
  2. 基准
  3. naam
  4. tijd

naam中需要存储用户名。 在 tijd 中需要存储休息时间(pauze)。

按照 cmets 的要求,当我执行 print_r($datum) 时,输出为:

2015-02-21(写作时的当前日期)

【问题讨论】:

  • 您好,您是否尝试过检查您在流程结束时生成的 SQL 字符串?您可以通过直接在数据库上尝试该 sql 语句来获取有关正在发生的事情的更多信息。另一件事我会尝试暂时使用 if 语句并填充时间 00:00 - 00:00 如果它是空的。所以我可以看到确切的问题。如果您确定您的数组+您创建的sql语句,我认为您将更好地了解您的问题。
  • 它使用mysqli 而不是PDO。两者非常不同。
  • @SühaBoncukçu - sql 语句返回两次名称和两次时间,并希望将其插入数据库。我也把array_merge改成了array_push,不知道这样好不好?
  • 你实际上有很多问题......你对很多事情感到困惑。 print_r($datum) 看起来像什么?表pauzes 有哪些列?需要插入哪些数据以及插入哪些列?我可以告诉你如何解决这个问题,但我需要知道这些事情才能给你一个可行的例子并解释它。
  • @Jules、array_merge 和 array_push 的工作方式不同。所以我认为这不是一个好主意。但是,根据您使用的语法,所有对都应使用两个 var 创建。作为(datum1,gegevens1),(datum2,gegevens2),...。如果其中之一与列列表不匹配;它会根据这里抛出一个错误:dev.mysql.com/doc/refman/5.6/en/insert.html,它说:“以下语句是非法的,因为列表中的值的数量与列名的数量不匹配:”对不起,我无法提供更多帮助,但是这个问题确实需要更多澄清。

标签: php mysql arrays pdo sql-insert


【解决方案1】:

首先,您使用的是准备好的语句,但错误地绑定了您的值。你给mysqli::prepare的sql应该是这样的:

INSERT INTO applepauzes (datum, naam, tijd) VALUES (?,?,?)

(?,?,?) 为每个用户重复。然后使用mysqli::bind_param 将数据绑定到这些值。不幸的是,mysqli::bind_param 让你一次绑定它们,并接受可变数量的参数 - 每个参数一个绑定,并且它们必须通过引用进行,这使得它更加烦人。

让我们来获取您的数据...为了运行 SQL 语句,我们最终需要的是一个如下所示的数组:

Array(
  0 => '2015-02-21',
  1 => 'juels',
  2 => '12.30-13.00',
  3 => '2015-02-21',
  4 => 'marc',
  5 => '12.30-1:00'
  // repeat for each user in the same order
)

但是,为了正确地制作查询,我们需要将以下内容组织起来:

Array (
   0 => array(
      0 => '2015-02-21',
      1 => 'juels',
      2 => '12.30-13.00'
   ),
   1 => array(
      3 => '2015-02-21',
      4 => 'marc',
      5 => '12.30-1:00'
   ),
   // repeat for every user record
)

我假设$_POST 看起来像:

Array(
   'juels' => '12.30-13.00',
   'marc' => '12.30-13.00',
   // etc
)

所以我们需要做的第一件事就是妥善组织:

$pauzes = array();
foreach ($users as $u) {
   $username = $u['username'];
   // if a user has an entry in the Form then add it to 
   // $pauzes array for insert into the DB
   if (isset($_POST[$username]) {
      // even though we want numeric keys eventually we
      // we will use the field names here so that its not ambiguous
      // later and we can easily reroder them
      $pauzes[] = array(
          'naam' => $username,
          'tijd' => $_POST[$username]
      )
   }
}

// call out function
add_pauzes(date('Y-m-d'), $pauzes);

所以现在我们进入问题的核心......mysqli 的实际插入:

// add an array typehint so that the function
// only takes an array
function add_pauze($datum, array $pauzes)
{
    GLOBAL $mysqli, $db_table_prefix;

    // first we need to prepare our base array structure
    $records = array();
    $params = array();

    foreach ($pauzes as $pauze) {
        $prefix = $pauze['username'];
        // give the items unique keys so we can reference them 
        // in the flat array $params
        $records[$prefix] = array(

           $prefix . 'datum' => $datum,
           $prefix . 'naam' => $pauze['username'],
           $prefix . 'tijd' => $pauze['tijd']
        );


        $params = array_merge($params, $records[$prefix]);
    }

    print_r($params);

    // get our total number of records for insertion
    // eg. each array in $records represents a set of values
    // for a db record in the table
    $recordCount = count($records);

    // create placeholders (?,?,?), one for each $record element
    $placeholders = array_fill(0, $recordCount, '(?,?,?)');

    // create the SQL string for our insert using
    // sprintf will substitute our the %s for the other arguments
    // we give it...    
    $sql = sprintf(
        'INSERT INTO %spauzes (datum, naam, tijd) VALUES %s',   
        $db_table_prefix,
        implode(',', $placeholders)
    );

    // prepare out statmement
    $stmt = $mysqli->prepare($sql);


    // we have to use references to bind the params
    // and to make it easy we want to do so with call_user_func_array
    // so setablish an array of arguemnts the first being th param
    // type and then so loop over $params and assign the values to
    // $args by reference
    $args = array(str_repeat('s', count($params)));
    foreach ($params as $k => &$v) {
        $args[$k] = &$v;
    }

    // bind all of our params using a callable and an array
    // of arguments to be passed into that callable
    call_user_func_array(array($stmt, 'bind_param'), $args);


    $result = $stmt->execute();
    $stmt->close();

    return $result;
}

【讨论】:

  • 稍作改动,您的代码就可以工作了。非常感谢!
  • 更新了更改。在本地测试并工作。也提醒我为什么我厌恶mysqli
【解决方案2】:

我解决了我的问题。

我将构建数组的代码更改为:

$pauze_users = array("users" => array());
$pauze_tijd = array("tijd" => array());
foreach($users as $usr)
{
  array_push($pauze_users, $usr['username']);
  array_push($pauze_tijd, $_POST[$usr['id']]);

}

之后,我确保数据是正确的,并使用以下代码将其放入 SQL 语句中:

$count_users = count($pauze_users);
$sql;
                for($i = 0; $i < $count_users; $i++)
                {
                    $sql .= "(" . $datum . ", " . $pauze_users[$i] . ", " . $pauze_tijd[$i] . ") ";     
        }

使用这段代码,我会得到这样的输出:

(2015-02-22, jules, 11.30-12.00) (2015-02-22, marc, 12.30-13.00) (2015-02-22, 尼克, ---) (2015-02-22, 保罗, 12.00-12.30) (2015-02-22, 凯文,---)(2015 年 2 月 22 日,里克,---)(2015 年 2 月 22 日,萨南,---) (2015-02-22, yvette, ---) (2015-02-22, bas, ---) (2015-02-22, 布鲁斯, ---)

(我知道我需要在数据之间放置 > 以使其能够被 SQL 接受

感谢您帮助解决我的问题!

【讨论】:

  • 请看我的回答......你在这里让自己对 SQL 注入持开放态度,因为你没有正确绑定你的参数。我的方式肯定更复杂,但确实值得。
  • 正确,我还没有保护代码免受 sql 注入。这将在稍后阶段进行。我的代码现在可以工作了,但稍后会看看你的代码。感谢您花时间帮助我!
  • 除了@prodigitalson 指出的非常重要的注入问题,-根据我的经验-使用具有相同迭代器的两个不同数组通常会给脚本语言带来未来的痛苦。您可能需要重新考虑重建您的阵列。
  • 不用担心...实际上我只是对其进行了一些重构以确保一切正常,并且仍然存在通过 ref 传递 bind_param 的问题。
【解决方案3】:

如果您只想将一个数组(或任意 PHP 结构)插入到 MySQL 表中并能够将其取出,请考虑以下方法。注意:您将无法通过 SQL 语句轻松检查任何数组元素。

将此添加到您的表中:

json TEXT NOT NULL COMMENT 'opaque array of stuff'

使用json_encode($array) 将您的数组转换为字符串,然后将该字符串插入到json 列中。

json 列选择为$json 后,执行以下操作以取回数组:

$array = json_decode($json, true);

【讨论】:

    猜你喜欢
    • 2013-03-05
    • 1970-01-01
    • 2011-11-10
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多