最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - Decimal values via get_option() with custom local (decimal point = comma)

programmeradmin1浏览0评论

I have a tricky bug in a plugin and I'm trying to figure out who's fault it is.

The plugin uses in its init method a check if the DB has to be updated. And the child theme I'm using has set a custom local with setlocal(). As a result get_option() return a string instead of a float value.

Here is the basic setup how to reproduce the error:

// 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 ''");
}

As the update is already in the system it throws an error as ((string) "5,39" < 5.13) === true.

Test the PHP behavior

I wrote a little check up for me to see what causes the error:

<?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";
?>

I was surprised by the output:

SUCCESS 5,39 > 5.13


If I interpreted my testing correct, PHP reads the decimal values correct and compares them correctly even after the locale has changed. But as WP seems to ignore the case that the decimal point has been set to a comma value and returns just a string value when using get_option("db_version").

Question

  1. Is DB update check if(!empty($db_version) and $db_version < 5.13) of the plugin wrong or is it wrong to use setlocale() for a WP project?

  2. Any good recommendation how to solve this issue?

I have a tricky bug in a plugin and I'm trying to figure out who's fault it is.

The plugin uses in its init method a check if the DB has to be updated. And the child theme I'm using has set a custom local with setlocal(). As a result get_option() return a string instead of a float value.

Here is the basic setup how to reproduce the error:

// 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 ''");
}

As the update is already in the system it throws an error as ((string) "5,39" < 5.13) === true.

Test the PHP behavior

I wrote a little check up for me to see what causes the error:

<?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";
?>

I was surprised by the output:

SUCCESS 5,39 > 5.13


If I interpreted my testing correct, PHP reads the decimal values correct and compares them correctly even after the locale has changed. But as WP seems to ignore the case that the decimal point has been set to a comma value and returns just a string value when using get_option("db_version").

Question

  1. Is DB update check if(!empty($db_version) and $db_version < 5.13) of the plugin wrong or is it wrong to use setlocale() for a WP project?

  2. Any good recommendation how to solve this issue?

Share Improve this question asked Feb 24, 2020 at 23:47 wittichwittich 1732 silver badges10 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

get_option() always returns a string. That has nothing to do with whether setlocale() has been used. Options are all stored in the option_value column of wp_options, which is a text column. Your float is likely being formatted for your locale when it tries to insert a float into the text column.

Your problem is that you're treating version numbers as floats, which is incorrect. They might look like floats, but version numbers are strings. For example, a float 5.2 is higher than 5.15, but 5.15 is a higher version number than 5.2.

So you can't compare version numbers by using < or > on floats. You need to use strings, and version_compare() to compare them. So first make sure to set the value as a string:

update_option( 'my_db_version', '5.13' );

Also note that db_version is an option already used by WordPress core, you need to prefix your options with something unique to your project.

Then you can compare the values like this:

$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 );
}
发布评论

评论列表(0)

  1. 暂无评论