【问题标题】:Save PHP array to MySQL?将 PHP 数组保存到 MySQL?
【发布时间】:2010-12-31 00:14:02
【问题描述】:

将数据数组保存到单个 mysql 字段的好方法是什么?

此外,一旦我在 mysql 表中查询该数组,有什么好方法可以将其恢复为数组形式?

是序列化和反序列化的答案吗?

【问题讨论】:

    标签: php mysql arrays


    【解决方案1】:

    没有好的方法可以将数组存储到单个字段中。

    您需要检查关系数据并对架构进行适当的更改。有关此方法的参考,请参见下面的示例。

    如果您必须将数组保存到单个字段中,那么serialize()unserialize() 函数就可以解决问题。但是您不能对实际内容执行查询。

    作为序列化函数的替代方案,还有json_encode()json_decode()

    考虑以下数组

    $a = array(
        1 => array(
            'a' => 1,
            'b' => 2,
            'c' => 3
        ),
        2 => array(
            'a' => 1,
            'b' => 2,
            'c' => 3
        ),
    );
    

    要将其保存在数据库中,您需要创建一个这样的表

    $c = mysql_connect($server, $username, $password);
    mysql_select_db('test');
    $r = mysql_query(
        'DROP TABLE IF EXISTS test');
    $r = mysql_query(
        'CREATE TABLE test (
          id INTEGER UNSIGNED NOT NULL,
          a INTEGER UNSIGNED NOT NULL,
          b INTEGER UNSIGNED NOT NULL,
          c INTEGER UNSIGNED NOT NULL,
          PRIMARY KEY (id)
        )');
    

    要处理记录,您可以执行诸如此类的查询(是的,这是一个示例,请注意!)

    function getTest() {
        $ret = array();
        $c = connect();
        $query = 'SELECT * FROM test';
        $r = mysql_query($query,$c);
        while ($o = mysql_fetch_array($r,MYSQL_ASSOC)) {
            $ret[array_shift($o)] = $o;
        }
        mysql_close($c);
        return $ret;
    }
    function putTest($t) {
        $c = connect();
        foreach ($t as $k => $v) {
            $query = "INSERT INTO test (id,".
                    implode(',',array_keys($v)).
                    ") VALUES ($k,".
                    implode(',',$v).
                ")";
            $r = mysql_query($query,$c);
        }
        mysql_close($c);
    }
    
    putTest($a);
    $b = getTest();
    

    connect()函数返回一个mysql连接资源

    function connect() {
        $c = mysql_connect($server, $username, $password);
        mysql_select_db('test');
        return $c;
    }
    

    【讨论】:

      【解决方案2】:

      一般来说,是的,序列化和反序列化是要走的路。

      但是,如果您的数据很简单,那么保存为逗号分隔的字符串可能会更适合存储空间。例如,如果您知道您的数组只是一个数字列表,那么您应该使用 implode/explode。这就是1,2,3a:3:{i:0;i:1;i:1;i:2;i:2;i:3;} 的区别。

      如果不是,则对所有情况进行序列化和反序列化工作。

      【讨论】:

      • 读者,既然你在这里,我想花时间宣布,通过多年的经验,我发现这确实不是正确的选择。公认的答案是一种更强大的方法。
      • 你在这里,读者我将与你分享这完全取决于你的要求。如果您不需要通过数组值查询并且需要非常快速的东西,您可以安全地将这样的数据存储在单个字段中(这是问题明确说明的内容),在其上打一个主键然后离开.如果您想知道应用程序是什么:将数据推送到每 5 分钟 cron'd 的队列中。另一个 cron 创建需要更多时间的数组。 que 获取计算数据并将其传递给第 3 方 API。没有比这更好的方法了。
      • @RidIculous 我很困惑,您是在谈论您自己的个人应用程序还是导致被问到问题的应用程序?
      • 虽然这与我陈述的前提无关,但前缀“如果您想知道应用程序是什么”应该提供清晰的说明。
      【解决方案3】:

      只需使用序列化 PHP 函数:

      <?php
      $myArray = array('1', '2');
      $seralizedArray = serialize($myArray);
      ?>
      

      但是,如果您使用这样的简单数组,不妨使用 implode 和 explode。使用空白数组而不是 new。

      【讨论】:

        【解决方案4】:

        序列化/反序列化数组以存储在数据库中

        访问http://php.net/manual/en/function.serialize.php

        来自 PHP 手册:

        在页面的“返回”下查看

        返回一个字符串,其中包含可以存储在任何地方的值的字节流表示形式。

        请注意,这是一个可能包含空字节的二进制字符串,需要按原样存储和处理。例如,serialize() 输出通常应存储在数据库中的 BLOB 字段中,而不是 CHAR 或 TEXT 字段中。

        注意:如果要将 html 存储到 blob 中,请务必对其进行 base64 编码,否则可能会破坏序列化功能。

        示例编码:

        $YourSerializedData = base64_encode(serialize($theHTML));
        

        $YourSerializedData 现在可以存储在 blob 中了。

        从 blob 获取数据后,您需要 base64_decode 然后反序列化 解码示例:

        $theHTML = unserialize(base64_decode($YourSerializedData));
        

        【讨论】:

          【解决方案5】:

          我发现自己最好的方法是将数组保存为带有分隔符的数据字符串

          $array = array("value1", "value2", "value3", "...", "valuen");
          $array_data = implode("array_separator", $array);
          
          $query = "INSERT INTO my_tbl_name (id, array_data) VALUES(NULL,'" . $array_data . "');";
          

          然后您可以通过简单的查询搜索存储在数组中的数据

          $query = "SELECT * FROM my_tbl_name WHERE array_data LIKE '%value3%'";
          

          使用explode()函数将“array_data”字符串转换为数组

          $array = explode("array_separator", $array_data);
          

          请注意,这不适用于多维数组,并确保您的“array_separator”是唯一的并且不存在于数组值中。

          小心!!!如果您只是将表单数据放入数据库中,那么您将陷入困境,因为表单数据不是 SQL 安全的!你必须处理你的表单值 使用 mysql_real_escape_string 或者如果您使用 MySQLi mysqli::real_escape_string 或者如果值是整数或布尔类型转换 (int) (boolean)

          $number = (int)$_POST['number'];
          $checked = (boolean) $_POST['checked'];
          
          $name = mysql_real_escape_string($db_pt, $_POST['name']);
          $email = mysqli_obj->real_escape_string($_POST['email']);
          

          【讨论】:

          • 就我而言,我想这对我来说是最好的选择。
          【解决方案6】:

          序列化和反序列化是很常见的。您还可以通过 json_encode 和 json_decode 使用 JSON,以获得较少的 PHP 特定格式。

          【讨论】:

            【解决方案7】:

            如前所述 - 如果您不需要在数组中搜索数据,您可以使用序列化 - 但这是“仅限 php”。所以我建议使用json_decode / json_encode - 不仅是为了性能,也是为了可读性和可移植性(其他语言,如 javascript 可以处理 json_encoded 数据)。

            【讨论】:

              【解决方案8】:

              呃,不知道为什么大家都建​​议序列化数组。

              我说,最好的方法是将它实际放入您的数据库架构中。我不知道(你也没有提供任何线索)关于数组中数据的实际语义含义,但通常有两种存储序列的方法

              create table mydata (
                id int not null auto_increment primary key,
                field1 int not null,
                field2 int not null,
                ...
                fieldN int not null
              )
              

              这样您将数组存储在一行中。

              create table mydata (
                  id int not null auto_increment primary key,
                  ...
              )
              
              create table myotherdata (
                  id int not null auto_increment primary key,
                  mydata_id int not null,
                  sequence int not null,
                  data int not null
              )
              

              显然,第一种方法的缺点是,如果数组中有很多项,则使用该表将不是最优雅的事情。使用可变长度的序列也是不切实际的(可能,但也很不雅 - 只是使列可以为空)。

              对于第二种方法,您可以拥有任意长度的序列,但只能是一种类型。当然,您可以制作一种类型 varchar 或其他类型并序列化数组中的项目。不是最好的做法,但肯定比序列化整个数组更好,对吧?

              无论哪种方式,这些方法中的任何一个都具有明显的优势,即能够访问序列的任意元素,并且您不必担心序列化数组和诸如此类的丑陋事情。

              至于拿回来。好吧,通过查询获取适当的行/行序列,然后,使用 loop.. 对吗?

              【讨论】:

              • 有时数组确实是合适的。如果您只打算将它作为第一个对象的属性来访问,那么这是有道理的。
              • 我不得不在最严厉的条件下不同意 - 对我来说存储随机的、非结构化的(php“数组”实际上根本不是数组,对吗?),无类型的数据块似乎相当不合适。 关系数据库。无论如何,如果您的数组中可能包含任何字符串,您将使用什么分隔符?这只是以许多不同的方式自找麻烦。在 99.9% 的情况下,还有另一种更自然的方式。我在这里做一个疯狂的猜测并建议,提问者的案例不属于剩余的 0.1%。
              • 其实,有时将数组存储在数据库中的字段中是非常合适的。示例是像全局“变量”表这样的元数据,系统插件和模块可以在其中存储它们的各种设置。存储任意“会话”数据的表可能最好使用包含键/值的关联数组的字段来实现。序列化和反序列化(这是正确答案)处理分隔符。检查几个成功和流行的开源项目,比如 WordPress 或 Drupal - 你会发现数组有时像这样存储在数据库中
              • @Scott Evernden:我想你毕竟是对的。 php 不是我的“主要”语言,所以我从数据库设计的角度来判断解决方案。如果您所描述的确实是做这些事情的常用方法(在 php 中),那就这样吧。虽然不让我喜欢它:)
              • 永远不适合将数组存储在数据库的字段中。它不违反第四范式,第三范式甚至第二范式:它是对第一范式的违反。如果您甚至无法遵守第一范式,则说明您的申请存在严重问题。这适用于 Drupal 和 Wordpress;如果他们这样做,那肯定不是因为他们的应用程序设计得很好。我在上一份工作中曾有过这样的论点,而且因为 XCart 正在做这种无稽之谈,所以它使本来应该可能的事情变得非常困难。
              【解决方案9】:

              您可以将数组保存为 json。
              有 json 数据类型的文档:https://dev.mysql.com/doc/refman/5.7/en/json.html
              我认为这是最好的解决方案,并且会通过避免疯狂的函数来帮助您保持代码更具可读性。
              我希望这对你有帮助。

              【讨论】:

                【解决方案10】:

                是的,序列化/反序列化是我在许多开源项目中看到最多的。

                【讨论】:

                  【解决方案11】:

                  我建议将 implode/explode 与您知道不会包含在任何单个数组项中的字符一起使用。然后将其作为字符串存储在 SQL 中。

                  【讨论】:

                  • 这个问题是 3 年前提出的,并且有一个公认的答案。您可能会发现回答新问题或没有答案的问题更有帮助。
                  【解决方案12】:

                  查看 implode 函数,因为值在数组中,所以您希望将数组的值放入 mysql 查询中,该查询将值插入表中。

                  $query = "INSERT INto hardware (specifications) VALUES (".implode(",",$specifications).")";
                  

                  如果数组中的值是文本值,则需要加引号

                  $query = "INSERT INto hardware (specifications) VALUES ("'.implode("','",$specifications)."')";
                  
                  mysql_query($query);
                  

                  另外,如果您不想重复值,请将“INto”切换为“IGNORE”,这样只会将唯一值插入到表中。

                  【讨论】:

                  • 如果你有一个主键,无论如何你都不会得到重复的 INSERT INTO。如果您没有主键或索引,则 IGNORE 没有任何区别。
                  【解决方案13】:

                  您可以将序列化对象(数组)插入 mysql,例如serialize($object),您可以取消序列化对象例如unserialize($object)

                  【讨论】:

                    【解决方案14】:

                    不要将其保存到数据库中,而是将其保存到文件中,然后再调用它。

                    许多 php 应用程序(如 Sugarcrm)所做的只是使用 var_export 将数组的所有数据回显到文件中。 这是我用来保存配置数据的:

                    private function saveConfig() {
                        file_put_contents($this->_data['pathtocompileddata'],'<?php' . PHP_EOL . '$acs_confdata = ' . var_export($this->_data,true) . ';');        
                    }
                    

                    我认为这是保存数据的更好方法!

                    【讨论】:

                    • 这是另一种方式,不一定更好。
                    • 确实如此。我只是认为访问文件比查询数据库以检索数组数据然后初始化数组要容易得多。这样,您只需包含文件即可。
                    猜你喜欢
                    • 1970-01-01
                    • 2012-09-29
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-01
                    • 1970-01-01
                    • 2014-03-17
                    相关资源
                    最近更新 更多