Php 如何从数据库中删除htmlentities()值?

Php 如何从数据库中删除htmlentities()值?,php,mysql,Php,Mysql,早在我知道任何事情之前——我现在知道的还不多——我就用php设计了一个web应用程序,在通过htmlentities()运行值之后,将数据插入我的mysql数据库。我终于醒悟过来,去掉了这一步,把它放在输出而不是输入中,继续快乐的生活 然而,后来我不得不重新访问一些旧数据,不幸的是,我遇到了一个问题,当它显示在屏幕上时,我得到的值被有效地绑定了两次 那么,是否有一种mysql或phpmyadmin方法可以将所有旧的、受影响的行更改回它们的相关字符,或者我必须编写一个脚本来读取每一行,解码并更新1

早在我知道任何事情之前——我现在知道的还不多——我就用php设计了一个web应用程序,在通过
htmlentities()
运行值之后,将数据插入我的mysql数据库。我终于醒悟过来,去掉了这一步,把它放在输出而不是输入中,继续快乐的生活

然而,后来我不得不重新访问一些旧数据,不幸的是,我遇到了一个问题,当它显示在屏幕上时,我得到的值被有效地绑定了两次

那么,是否有一种mysql或phpmyadmin方法可以将所有旧的、受影响的行更改回它们的相关字符,或者我必须编写一个脚本来读取每一行,解码并更新12个表中的所有1700万行

编辑:


谢谢大家的帮助,我在下面写下了我自己的答案,里面有一些代码,虽然不太好看,但是它在测试数据上运行得很快,所以除非有人在我睡觉的时候指出我代码中的一个明显错误,我明天会在备份数据库上运行它,如果可以的话,我会在实时数据库上运行它

因为PHP是一种编码方法,所以您需要使用它来解码。可以使用将其转换回原始字符。必须循环


只是要小心不要解码不需要它的行。不确定您将如何确定这一点。

我认为在这种情况下编写php脚本是一件好事。正如Dave所说,您可以使用html_entity_decode()函数将文本转换回来

首先在一个只有几个条目的表上尝试脚本。这将使您节省大量的测试时间。当然,记得在运行php脚本之前备份表


恐怕没有比这更短的可能性了。无论您如何转换回数据集,数百万行的计算仍然相当昂贵。因此,请使用php脚本。。。这是最简单的方法

有点麻烦,但我认为大规模更新是唯一的方法

$Query = "SELECT row_id, html_entitied_column FROM table";
$result = mysql_query($Query, $connection);
while($row = mysql_fetch_array($result)){
    $updatedValue = html_entity_decode($row['html_entitied_column']);
    $Query = "UPDATE table SET html_entitied_column = '" . $updatedValue . "' ";
    $Query .= "WHERE row_id = " . $row['row_id'];
    mysql_query($Query, $connection);
}
这是简化的,没有错误处理等。
不确定数百万行的处理时间,因此您可能需要将其分成多个块,以避免脚本超时

我最后用了这个,不漂亮,但我累了,凌晨2点,它完成了它的工作!(编辑:基于测试数据)

$tables=array('users','users\u more','users\u extra','forum\u posts','posts\u edits','forum\u threads','orders','product\u comments','products','favorites','blocked','notes');
foreach($tables作为$table)
{       
$sql=“从{$table}中选择*其中数据{$date}<'{$encode\u cutoff}'”;
$rows=$database->query($sql);
while($row=mysql\u fetch\u assoc($rows))
{
$new=array();
foreach($key=>$data的行)
{
$new[$key]=$database->escape_值(html_entity_decode($data,ENT_引号,'UTF-8'));
}
阵列移位(新);
$new_string=“”;
$i=0;
foreach($new as$new\u key=>$new\u data)
{
如果($i>0){$new_字符串=“,”;}
$new_string.=$new_key.='“$new_data.”;
$i++;
}
$sql=“UPDATE{$table}SET”。$new_字符串。“其中id=”。$row['id']。“”;
$database->query($sql);
//加上一些代码来检查这一切
}
}

我也有同样的问题。由于我有多个客户机在生产环境中运行该应用程序,所以我希望避免运行PHP脚本来清理每个客户机的数据库

我想出了一个远非完美的解决方案,但却毫不费力地完成了这项工作

  • 在插入数据之前,跟踪代码中使用htmlentities()的所有点,并将其删除
  • 将“将数据显示为HTML”方法更改为类似以下内容:

    返回html_entity_decode(htmlentities($chaine,ENT_NOQUOTES),ENT_NOQUOTES)


  • 撤销-重做过程有点荒谬,但它确实起到了作用。每次用户更新不正确的数据时,您的数据库都会缓慢地自我清理

    这是我的防弹版本。它迭代数据库中的所有表和字符串列,确定主键并执行更新

    它旨在从命令行运行php文件以获取进度信息

    <?php
    $DBC = new mysqli("localhost", "user", "dbpass", "dbname");
    $DBC->set_charset("utf8");
    
    $tables = $DBC->query("SHOW FULL TABLES WHERE Table_type='BASE TABLE'");
    while($table = $tables->fetch_array()) {
        $table = $table[0];
        $columns = $DBC->query("DESCRIBE `{$table}`");
        $textFields = array();
        $primaryKeys = array();
        while($column = $columns->fetch_assoc()) {
            // check for char, varchar, text, mediumtext and so on
            if ($column["Key"] == "PRI") {
                $primaryKeys[] = $column['Field'];
            } else if (strpos( $column["Type"], "char") !== false || strpos($column["Type"], "text") !== false ) {
                $textFields[] = $column['Field'];
            }
        }
        if (!count($primaryKeys)) {
            echo "Cannot convert table without primary key: '$table'\n";
            continue;
        }
        foreach ($textFields as $textField) {
            $sql = "SELECT `".implode("`,`", $primaryKeys)."`,`$textField` from `$table` WHERE `$textField` like '%&%'";
            $candidates = $DBC->query($sql);
            $tmp = $DBC->query("SELECT FOUND_ROWS()");
            $rowCount = $tmp->fetch_array()[0];
            $tmp->free();
            echo "Updating $rowCount in $table.$textField\n";
            $count=0;
            while($candidate = $candidates->fetch_assoc()) {
                $oldValue = $candidate[$textField];
                $newValue = html_entity_decode($candidate[$textField], ENT_QUOTES | ENT_XML1, 'UTF-8');
                if ($oldValue != $newValue) {
                    $sql = "UPDATE `$table` SET `$textField` = '"
                        . $DBC->real_escape_string($newValue)
                        . "' WHERE ";
                    foreach ($primaryKeys as $pk) {
                        $sql .= "`$pk` = '" . $DBC->real_escape_string($candidate[$pk]) . "' AND ";
                    }
                    $sql .= "1";
                    $DBC->query($sql);
                }
                $count++;
                echo "$count / $rowCount\r";
            }
        }
    }
    ?>
    
    real\u escape\u字符串($newValue)
    . “‘何处’;
    foreach($primaryKeys作为$pk){
    $sql.=“`$pk`='”$DBC->real\u escape\u string($candidate[$pk])。“`AND”;
    }
    $sql.=“1”;
    $DBC->query($sql);
    }
    $count++;
    回显“$count/$rowCount\r”;
    }
    }
    }
    ?>
    
    干杯
    Roland

    是的,我知道该函数的用法,如果我必须更新每一行,我将使用它,但我想知道在mysql或phpmyadmin中是否有一种较短的方法,即对受影响的行进行大规模更新。一些模糊的函数,他们藏起来了。@webbie至于你的编辑点,是的,我很幸运,我有我写的源代码和日志文件的旧备份,所以我准确地知道代码是什么时候被修改的,并且在数据库中的行周围嗅了嗅,在那个时候也确认了它。幸亏你这么做了!HTML实体有什么问题?它们绝对是非英语语言的发展方向…熟悉的问题,恐怕我也还没有解决…@nico html实体没有问题,只是我更喜欢输入时存储的数据,输出时可以通过htmlentities运行。这是我在启动网站后做出的一个选择,但需要对所有行进行标准化。@Chris将其保存在数据库中作为HTML实体,这样每次显示时都可以调用htmlentities。不管怎么说,我认为没有捷径可以走
    <?php
    $DBC = new mysqli("localhost", "user", "dbpass", "dbname");
    $DBC->set_charset("utf8");
    
    $tables = $DBC->query("SHOW FULL TABLES WHERE Table_type='BASE TABLE'");
    while($table = $tables->fetch_array()) {
        $table = $table[0];
        $columns = $DBC->query("DESCRIBE `{$table}`");
        $textFields = array();
        $primaryKeys = array();
        while($column = $columns->fetch_assoc()) {
            // check for char, varchar, text, mediumtext and so on
            if ($column["Key"] == "PRI") {
                $primaryKeys[] = $column['Field'];
            } else if (strpos( $column["Type"], "char") !== false || strpos($column["Type"], "text") !== false ) {
                $textFields[] = $column['Field'];
            }
        }
        if (!count($primaryKeys)) {
            echo "Cannot convert table without primary key: '$table'\n";
            continue;
        }
        foreach ($textFields as $textField) {
            $sql = "SELECT `".implode("`,`", $primaryKeys)."`,`$textField` from `$table` WHERE `$textField` like '%&%'";
            $candidates = $DBC->query($sql);
            $tmp = $DBC->query("SELECT FOUND_ROWS()");
            $rowCount = $tmp->fetch_array()[0];
            $tmp->free();
            echo "Updating $rowCount in $table.$textField\n";
            $count=0;
            while($candidate = $candidates->fetch_assoc()) {
                $oldValue = $candidate[$textField];
                $newValue = html_entity_decode($candidate[$textField], ENT_QUOTES | ENT_XML1, 'UTF-8');
                if ($oldValue != $newValue) {
                    $sql = "UPDATE `$table` SET `$textField` = '"
                        . $DBC->real_escape_string($newValue)
                        . "' WHERE ";
                    foreach ($primaryKeys as $pk) {
                        $sql .= "`$pk` = '" . $DBC->real_escape_string($candidate[$pk]) . "' AND ";
                    }
                    $sql .= "1";
                    $DBC->query($sql);
                }
                $count++;
                echo "$count / $rowCount\r";
            }
        }
    }
    ?>