json_decode thinks a normal string is valid - php

Seems my old server this would return NULL or false...the new server returns the value, weird.
var_dump(json_decode("this is a normal string, not JSON"));
Output:
string(33) "this is a normal string, not JSON"
Expected:
NULL

You have not really formulated a question, but I try to answer it anyway:
Every software contains bugs. That's normal. We share the code, we share the bugs. What you ask about is a reported and fixed software flaw in PHP. Upgrade your PHP version or live with the bug.

Related

Strange Results for String comparison in PHP

We ran into an issue today that I am surprised I had not encountered before. It was related to string comparison:
echo ("9400110897799014514025" == "9400110897799014514018" ? "match" : "not");
echo ("94001108" == "94001107" ? "match" : "not");
Neither of the 2 sets matches, yet the first one reports a "match" incorrectly, while the second properly declares it "not" a match. We resolved the issue by using '===' in place of '==' but I'd really like to understand what is going on here.
Add: It's PHP 5.3
I tried running your code, but I got notnot in the first few attempts. Only after lowering the php version to 5.4.3 or below, I got matchnot.
It appears you're running on an outdated version of php, and encountered this bug. It has been solved since php5.4.4.
The best thing to do is probably to upgrade your php version (although strict comparison isn't a bad thing either way)
Edit: According to the comments on the original answer, it looks like the problem persists in later versions as well, but only on 32bit systems.
The problem itself comes from the fact that php is extremely loose with comparisons, converting strings that look like numbers to numbers before comparison. This leads to php considering "1e3" as equal to "1000", for example.

Why is get_env() treating my boolean environment variable as a string?

I upgraded my Wordpress instance from 4.5 to 4.8, and for some reason my boolean environment variable is now returning as a string of "false" rather than false. Since my PHP version hasn't changed, I'm a bit mystified at the change. More importantly however, about going forward, what's the best way to manage getting booleans into PHP via environment vars?
Here's the .env line I have:
WP_FORCE_SSL_ADMIN=false
Here's the line I had in my wp-config.php that is returning true due to string conversion.
define('FORCE_SSL_ADMIN', getenv('WP_FORCE_SSL_ADMIN'));
Here's the var_dump:
["WP_FORCE_SSL_ADMIN"]=>
string(5) "false"
I know that I can simply refactor the define to account for the string conversion, but I'm bothered that I don't understand what changed when nothing should have. This worked fine on for wordpress version 4.5.
Looking for an answer to explain the best method for passing boolean vars from my environment into PHP, or do I always have to account for the string conversion?
Just in case someone comes here looking for the answer to how I solved it, what I did was simply do a comparison to the string of "true".
define('FORCE_SSL_ADMIN', strtolower(getenv('WP_FORCE_SSL_ADMIN')) === "true");
While this works, it still doesn't feel quite right to me, like I'm missing something.

Array to string conversion exception with PHP 7

I was working with old legacy code and checked if it's running with PHP7. I got an exception (Array to string conversion) with following code:
json_decode($json_string)
->$array['id']
->foo
What helped was to use the curly brackets:
json_decode($json_string)
->{$array['id']}
->foo
My question is, was that already wrong PHP5 and if not, which change is the reason for that? Could not find anything because did not know for what to search... One idea I had is that the new introduced AST produces this behavior?
I think you are right. From what I know in PHP5 that works without any exception, but PHP 7 wants to be just a little bit more strict, because cases like this can cause a lot big problems after when not used correctly.

json_encode() turn non-UTF8 strings into null, but on live site returns false

In the framework I have to use for a project (Lithium) the output on a specific page goes through json_encode(). Locally and on live I try with one and the same data, and the result is:
Locally it returns the JSON, but some of the values are turned into null.
Live site - it returns false.
In both cases when I run json_last_error() - it gives me int(5). I can run phpinfo() on both places, if some setting is causing the problem.
(Locally I'm with PHP 5.3.*, on live it's 5.5.9.)
Actually you need to use optional parameters of json_encode in case of UTF8 characters
So You can use
JSON_UNESCAPED_UNICODE
option of
JSON_ENCODE
Example:
json_encode($array, JSON_UNESCAPED_UNICODE)
Visit php documentation here.
Although this is not documented on the version log here, non-UTF8 handling behaviour has changed in 5.5, in a way that can make debugging difficult.
Passing a non UTF-8 string to json_encode() will make the function return false in PHP 5.5, while it will only nullify this string (and only this one) in previous versions.
In a Latin-1 encoded file, write this:
$a = array('é', 1);
var_dump(json_encode($a));
PHP < 5.4: string(8) "[null,1]"
PHP >= 5.5: bool(false)
PHP 5.5 has it right of course (if encoding fails, return false) but its likely to introduce errors when updating to 5.5 because previously you could get the rest of the JSON even when one string was not in UTF8 (if this string wasn't used, you'd never notify it's nulled)
Finally - I used a slightly modified version of this gist - http://gist.github.com/oscar-broman/3653399 - but instead of encoding properties - I'm removing all the non-UTF8 strings ... and it's working. But - I had to modify the PHP framework the website is using ... and this is something I was really trying to avoid ... ... ... ... but anyway, this approach does the job for now :) ...
I get the same error with PhP 7.3.
You can fix it in multiple ways :
Ignore no-UTF8 char
json_encode(array("a" => "ç"), JSON_INVALID_UTF8_IGNORE);
This solution is fine if you just want to ignore all possible strange caractere, without trying to show them.
Replace no-UTF8 char
json_encode(array("a" => "ç"), JSON_INVALID_UTF8_SUBSTITUTE);
This is possible, but in my case I was getting "?" result.
UTF8-ize char
json_encode(array("a" => utf8_encode("ç")));
I'm using this solution which just convert into UTF8 format all char.

PHP 5.4's simplified string offset reading

As many of you already know, PHP 5.4 alpha has been released. I have a question regarding the following.
Simplified string offset reading.
$str[1][0] is now a legal construct.
How exactly does $str[1][0] work?
EDIT: http://php.net/releases/NEWS_5_4_0_alpha1.txt
It just means that when reading a string offset PHP returns a string again, on which you again can access an offset. (And on that access yet another offset. It gets funny with $str[0][0][0][0][0][0])
Before PHP 5.4 you would get an "Cannot use string offset as an array" error.
This is a side effect, and was mentioned in the proposal here:
http://php.markmail.org/thread/yiujwve6zdw37tpv
The feature is speed/optimization of string offsets.
Hi,
Recently I noticed that reading of
string offset is performed in two
steps. At first special string_offset
variant of temporary_variable is
created in
zend_fetch_dimension_address_read()
and then the real string value is
created in
_get_zval_ptr_var_string_offset().
I think we can create the real string
in the first place. This makes 50%
speed-up on string offset reading
operation and allows to eliminate some
checks and conditional brunches in VM.
The patch is attached (don't forget to
regenerate zend_vm_execute.h to test
it). However it changes behavior in
one bogus case. The following code now
will emit "b" (currently it generates
a fatal error - cannot use string
offset as an array).
$str = "abs";
var_dump($str[1][0]);
I think it's not a problem at all. "b"
makes sense because "abs"[1] -> "b"
and "b"[0] -> "b".
I'm going to commit the patch in case
of no objections.
Thanks. Dmitry.
This can actually create some interesting bugs when you upgrade code from php 5.3 to 5.4.
In 5.3 this construct would return false:
$array = array("This is a string");
echo isset($array[0][0][0]);
In 5.4 this would return true.

Categories