Php 如何从数据库中删除htmlentities()值?
早在我知道任何事情之前——我现在知道的还不多——我就用php设计了一个web应用程序,在通过Php 如何从数据库中删除htmlentities()值?,php,mysql,Php,Mysql,早在我知道任何事情之前——我现在知道的还不多——我就用php设计了一个web应用程序,在通过htmlentities()运行值之后,将数据插入我的mysql数据库。我终于醒悟过来,去掉了这一步,把它放在输出而不是输入中,继续快乐的生活 然而,后来我不得不重新访问一些旧数据,不幸的是,我遇到了一个问题,当它显示在屏幕上时,我得到的值被有效地绑定了两次 那么,是否有一种mysql或phpmyadmin方法可以将所有旧的、受影响的行更改回它们的相关字符,或者我必须编写一个脚本来读取每一行,解码并更新1
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脚本来清理每个客户机的数据库
我想出了一个远非完美的解决方案,但却毫不费力地完成了这项工作
撤销-重做过程有点荒谬,但它确实起到了作用。每次用户更新不正确的数据时,您的数据库都会缓慢地自我清理 这是我的防弹版本。它迭代数据库中的所有表和字符串列,确定主键并执行更新 它旨在从命令行运行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";
}
}
}
?>