I need to have a numeric float using a dot separator, that stays a numeric after (json) encoding for sending in the POST headers to a third-party API.
However, have been trying for a few hours, but cannot get it to work.
What I need is:
{
"price": 17.95,
// BUT NOT:
"price": "17.95" OR 17,95
}
Why? Because the receiving API endpoint does a check for the first but throws a non-numeric
error on the latter 2 values.
Now, we're in Holland. So our "locale" uses a comma separator. Working around that by setting the locale from nl_NL
to en_US
gives the number_format
function the correct format, however, as a string.
Casting a comma or dot separated string using (float)
causes it to lose any value from the point of separation. ("17.95"
becomes 17
)
Updating the product details is a function taking a few arguments that passes them on without modification to cURL. Which encodes the array of POST variables into what it should be above. I'm limited in passing the following:
$client->updateShopItem($shopId, $articleNumber, $updateArray)
$shopId
= int
$articleNumber
= string
$updateArray
= array
Complete, correct, call looks like:
$client->updateShopItem(12345, "a1b2c3", [
"price" => 17.95,
"sale_price" => 12.99,
//... other values
]);
Values to use instead of the ones in example above are string type: "17,95".
Have tried:
$price = "17,95" //Starting point (locale = nl_NL)
number_format($price, 2) // "17.00" - incorrect type and value
number_format(str_replace(',', '.', $price), 2) // "17.95" - string
(float) str_replace(',', '.', $price); // 17,95 - comma
(float) number_format(str_replace(',', '.', $price), 2) //17,95 - comma
setLocale(LC_ALL, 'en_US'); //Changing locale here, US uses dot separator
$check = locale_get_default(); // "en_US"
number_format($price, 2) // "17.00" - incorrect type and value
number_format(str_replace(',', '.', $price), 2) // "17.95" - string
(float) number_format(str_replace(',', '.', $price), 2) // 17,95 - comma
(float) str_replace(',', '.', $price); // 17,95 (can't figure why comma with US locale)
Extra test to see what json_encode()
makes of the different types/values:
json_encode(["test1" => "17,95", "test2" => 17.95]);
//Results in:
{"test1":"17,95","test2":17.95}
UPDATE: to avoid confusion: full code, only removed non-relevant stuff, otherwise unedited. Has included locale se
setlocale(LC_ALL, 'nl_NL');
ini_set('intl.default_locale', 'nl-NL');
$update = [
'price' => ((float)number_format(str_replace(',', '.', $prijs), 2)),
'discount_price' => (float) str_replace(',', '.', $actieprijs),
];
setlocale(LC_ALL, 'en_US');
ini_set('intl.default_locale', 'en-US');
// Update a shopitem
$update2 = [
'price' => ((float)number_format(str_replace(',', '.', $prijs), 2)),
'discount_price' => (float) str_replace(',', '.', $actieprijs),
];
UPDATE 2: SOLUTION FOUND After some comments back 'n' forth with @KevinStich about his answer found that the problem when trying to change the locale was in the fact that I'm on Windows.
His answer solves it, after adding the following code above where it needs to get set:
if (!setlocale(LC_ALL, 'en_US.utf8')) { //Works on "normal" server/Linux stuff
setlocale(LC_ALL, 'us'); //Windows is special
}
Found in the docs that the setlocale()
function returns false
if it didn't set a new locale, or else returns the new locale. Which led to the above and that @KevinStich's answer worked.