通过带有自定义本地(小数点=逗号)的GET_OPTION()实现的小数值

时间:2020-02-24 作者:wittich

我有一个插件中有一个棘手的bug,我正试图找出是谁的错。

插件在其init方法中使用检查DB是否必须更新。我使用的子主题设置了一个自定义本地setlocal(). 因此get_option() 返回字符串而不是浮点值。

以下是如何再现错误的基本设置:

// set custom local
setlocale(LC_ALL, \'de_DE.UTF-8\');

// set current DB version
update_option("db_version", 5.39);

// get DB version
$db_version = get_option("db_version"); // (string) 5,39

// Update DB if necessary
if(!empty($db_version) and $db_version < 5.13) {
    $wpdb->query("ALTER TABLE example CHANGE `cat_id` `cat_ids` VARCHAR(255) NOT NULL DEFAULT \'\'");
}
由于更新已经在系统中,它会抛出一个错误((string) "5,39" < 5.13) === true.

测试PHP行为

我写了一个小检查,看看是什么导致了错误:

<?php
setlocale(LC_ALL, \'de_DE.UTF-8\');
echo \'<pre>\';
$locale_info = localeconv();
echo \'decimal_point=\' . $locale_info[\'decimal_point\'] . "\\n"; // decimal_point=,
// Test like the DB update check in WP
$db_version = floatval(\'5.39\');
if(!empty($db_version) and $db_version < 5.13) // <==
    echo "ERROR $db_version is not smaller than 5.13";
else 
    echo "SUCCESS $db_version > 5.13";
?>
我对结果感到惊讶:

成功5,39>5.13

如果我正确解释了我的测试,PHP会正确读取十进制值,并且即使在locale 已更改。但由于WP似乎忽略了小数点已设置为逗号值的情况,因此在使用时只返回字符串值get_option("db_version").

问题是数据库更新检查if(!empty($db_version) and $db_version < 5.13) 插件错误或使用错误setlocale() 对于WP项目?

如何解决这个问题,有什么好的建议吗?

1 个回复
最合适的回答,由SO网友:Jacob Peattie 整理而成

get_option() 始终返回字符串。这与setlocale() 已使用。选项都存储在option_value 第列,共列wp_options, 这是一个文本列。当它试图在文本列中插入浮点时,可能正在为您的区域设置设置浮点格式。

您的问题是,您将版本号视为浮点数,这是不正确的。它们可能看起来像浮点数,但版本号是字符串。例如,浮点数5.2 高于5.15, 但是5.15 版本号高于5.2.

因此,您无法使用<> 在浮动上。您需要使用字符串,并且version_compare() 比较它们。因此,首先确保将值设置为字符串:

update_option( \'my_db_version\', \'5.13\' );
还要注意的是db_version 是WordPress core已经使用的选项,您需要在选项前面加上项目特有的前缀。

然后可以比较如下值:

$current_version = get_option( \'my_db_version\' );
$new_version     = \'5.39\'; // String

// If the current version is lower than the new version...
if ( version_compare( $current_version, $new_version ) < 0 ) { 
    // ...update to the new version.
    update_option( \'my_db_version\', $new_version );
}