Illegal string offset PHP 5.6 - php

We have an old version of CakePHP that we've moved to a new server running PHP 5.6 and we've started to recieve this error when adding a product to the basket:
Warning (2): Illegal string offset 'AddBasketData'
[APP/controllers/personalisation_controller.php, line 848]
Here is line 848 within the file:
if (is_array($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
}else {
$personalisation_data['Personalise'] = array();
}
Could anyone shed any light on this, I think it's down to the specific PHP version we're running now but any help would be great.
Thanks

Transforming my comments into an answer :
The problem here seems to be that $this->data is a string and not an array.
You should test this first, then check if the offset AddBasketData exists, and finally if the offset AddBasketData is an array :
if (is_array($this->data) && isset($this->data['AddBasketData']) && is_array($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
} else {
$personalisation_data['Personalise'] = array();
}
Of course, that will only correct the symptoms (which is the raised warning), you might have some code debugging to do to find out why $this->data is a string instead of an array.

As noted by #roberto06 in the comments to your question, the reason you're getting the error is because you're trying to treat a string value as an array.
The reason for that specific error message is because you can use the array-offset notation to fetch a single character from the string. Just like you'd do in C's string arrays. But this only support numerical indices, and not a string index as shown in the code you posted.
Now, the easy way to stop the error from occurring is to simply test the type of the data, and whether or not the given index actually exists.Like so:
if (is_array ($this->data) && !empty ($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
} else {
$personalisation_data['Personalise'] = array();
}
However, seeing as you're not suddenly getting this error after update hints towards something else being the issue. Especially since the code you posted expects the value stored in the Personalise index to be an array. I'd trace where the $this->data member gets set, and changed, to see if you can find the underlying reason for why this apparent change in behavior. This might be the side-effect of a more nefarious subtle bug, after all.

Related

Array to string conversion error on foreach on php 7.3 but work on php 5.6

I have upgraded my server to use PHP version 7.3 from 5.6
I ran compatibility check from PHPStorm for all my files, and it only showed me only weak warning for few of the codes but since I am no longer using those script I ignored it, but it does not point out anything wrong on this code.
But after migration, I found that this piece of code is not working as required. I have this code to get state short code when I pass the 2 digit country code.
$jsonitemfile = file_get_contents('countries-states.json');
$conobjitems = json_decode($jsonitemfile);
$findBystatename = function($constatename) use ($conobjitems) {
foreach ($conobjitems->$_POST['Contact0Country']->states as $short => $outputstate) {
if ($outputstate->name == $constatename) return $short;
}
return false;
};
$p2 = 'New York';
echo $findBystatename($p2) ?: $p2;
When I run this code I get the following error
Notice: Array to string conversion in /home/domain.com/public_html/code/code_check.php on line 27
Notice: Undefined property: stdClass::$Array in /home/domain.com/public_html/code/code_check.php on line 27
Notice: Trying to get property 'states' of non-object in /home/domain.com/public_html/code/code_check.php on line 27
Warning: Invalid argument supplied for foreach() in /home/domain.com/public_html/code/code_check.php on line 27
The same code is working on PHP 5.6 without throwing any error.
Although I fixed the code by doing the below changes
$findBystatename = function($constatename) use ($conobjitems) {
$p1 = $_POST['Contact0Country'];
foreach ($conobjitems->$p1->states as $short => $outputstate) {
if ($outputstate->name == $constatename) return $short;
}
return false;
};
For my learning curve can anyone please advise why its not working? And even with the updated code, if I define $p1 above the function, it start to throw the same error.
Also is there a way the original code start working on PHP 7.3 without updating the code?
$conobjitems->$_POST['Contact0Country']->state is ambiguous. It could mean the state property of an object defined by $conobjitems->$_POST['Contact0Country'] (as you and PHP 5.6 assume), or it could mean the state property of an object defined by $_POST['Contact0Country'] and then whatever that resolves to as a property on $conobjitems, which seems to be what modern PHP considers it.
Obviously a compiler/run time environment cannot treat a line as meaning two things, so it has to pick one and move on, or error out and fail. Historically PHP has been lenient in what it copes with, but as the language has improved and got faster some of that leniency has been removed in favour of making the coder be specific instead of ambiguous (which also helps make the code readable)
If this is just a toy example - this won't work, but your piece of code can be written as:
$jsonitemfile = file_get_contents('countries-states.json');
$conobjitems = json_decode($jsonitemfile);
$country=$conobjitems->$_POST['Contact0Country'];
$states=$country->states;
$findBystatename = function($constatename) use ($states) {
foreach ($states as $short => $state) {
if ($state->name == $constatename) return $short;
}
return false;
};
$p2 = 'New York';
echo $findBystatename($p2) ?: $p2;
$country could be skipped but it makes the code more readable, likewise separating the state list into $states before injecting into the closure makes it clear to the reader and PHP what you want to do.
By the way, since you seem to choose the country by user-input (which could be manipulated, even if you're using a drop down), you could also get an error, warning or exception when you create $country if that country doesn't exist in the $conobjitems set. You could use property_exists first to make sure the country is found.

Is array error possibly a PHP version issue?

I work on a website that, since last Oct, has had the following lines of code that work just fine:
if(empty($post_types))
{
$post_types[] = 'post';
$post_types[] = 'product-list';
}
I had not seen this construct in PHP before, (and since I started my programming work in C, it's a little irritating), but it works.
We started a second site with the same technology and basic setup that threw the following error at the same lines of code,
"Uncaught Error: [] operator not supported for strings ..."
The sites are hosted at the same place, but I noticed that they are using different 7.x versions of PHP. I did a bit of research to see if the behavior is due to a change in PHP 7.3, but I didn't find an answer.
Please note that my question is on whether this situation is possibly a PHP version issue, not how to solve the array problem, which I changed with
$post_types = array('post', 'product-list');
I found your answer in the PHP docs Creating/modifying with square bracket syntax:
$arr[key] = value;
$arr[] = value;
// key may be an integer or string
// value may be any value of any type
If $arr doesn't exist yet, it will be created, so this is also an
alternative way to create an array. This practice is however
discouraged because if $arr already contains some value (e.g. string
from request variable) then this value will stay in the place and []
may actually stand for string access operator. It is always better to
initialize a variable by a direct assignment.
Note: As of PHP 7.1.0, applying the empty index operator on a string throws a fatal error. Formerly, the string was silently converted to
an array.
So it appears there is a change in PHP 7.1.0 matching with the problem you described.
In your code, your $post_type variable must be initialized as a string [EDIT : I could only reproduce the problem with an empty string], and was previously ( PHP < 7.1.0) silently converted to an array.

In what way is my array index an 'Illegal string offset'?

When "future-proofing" code by testing it on PHP 5.4, I get a warning I don't understand.
function __clone() {
$this->changed = TRUE;
foreach ($this->conditions as $key => $condition) {
if (
$condition['field']
instanceOf QueryConditionInterface) {
$this->conditions[$key]['field'] = clone($condition['field']);
}
}
}
I broke out $condition['field'] into its own row to reduce the amount of code to focus on. About that specific line, PHP has this to say
Warning: Illegal string offset 'field' in DatabaseCondition->__clone()
And I just can't see how 'field', is an illegal string offset. I'm guessing that I'm just missing something obvious, but if the community can't find a problem, I'll file a bug report.
I interpret the warning as "Under no circumstances is 'field' a valid key". This error would have made sense if I had tried to us for example an array as a key.
Without more knowledge about the creation of the conditions array/iterator, I can only assume that you should first check if the offset exists.
if(isset($condition['field']) && $condition['field'] instanceOf QueryConditionInterface)
Using isset in this situation is enough and faster than array_key_exists, the only difference is, if $condition['field'] is NULL isset will return falls, array_key_exists will return true, cause the key exists. But because you only want to work on fields that are an instance of QueryConditionInterface, you will running fine with isset.
The warning looks like its saying that $condition is a string. Without any knowledge of the code I don't whether that makes any sense.

New to programming php, and have seen similar problems

So currently I'm trying to fix up some old code for a stats server for a game (that is definitely outdated, and has been replaced recently with a new version). MUCH of the code is deprecated, so it's kind of guesswork on fixing it right, but I found a section thats completely broken that I have no idea how to fix, and it's causing a fatal error.
The code is as follows
for ($i=0; $i<$armyCount; $i++)
{
$summary['total']['time'] += $armies[0]['time'.$i];
$summary['total']['win'] += $armies[0]['win'.$i];
$summary['total']['loss'] += $armies[0]['loss'.$i];
$summary['total']['score'] += $armies[0]['score'.$i];
$summary['total']['best'] += $armies[0]['best'.$i];
$summary['total']['worst'] += $armies[0]['worst'.$i];
$summary['total']['brnd'] += $armies[0]['brnd'.$i];
}
The errors I get are as follows
Notice: Uninitialized string offset: 0 in C:\xampp\htdocs\dontneedthis\playerstats.inc.php on line 136
Fatal error: Cannot use string offset as an array in C:\xampp\htdocs\dontneedthis\playerstats.inc.php on line 136
I've seen similar questions asked, and seen how they were resolved, but I don't fully understand how it was done, so don't quite know how to go about fixing this one. Any assistance would be awesome, and I fully intend to release the bugfixed and fully working code (whenever I get that done) to the community that remains.
It looks like your $armies[0]['time'.$i] is initialized as an empty string and not as an array (likely $armies= "").
Notice: Uninitialized string offset: 0
That means that php tries to access your string-variable $armies as an array. If the string is non-empty then this would result in getting single letters from that string. But it seems that $armies is an empty string and so getting the letter with index 0 is not possible.
Fatal error: Cannot use string offset as an array
means that the result of the operation above (which showed the notice) cannot be accessed as an array. Remember that $armies is a astring and the first letter of the string was accessed and the result of this attempt will be accessed as an array.
Try resolving how the $armies variable is filled and why its filled the wrong way.
$armies is an empty string, and you are treating it as any array, in an unrecoverable way.
Show us what $armies should look like, what you get when you var_dump($armies);, and the code from where you assigned it, and we'll help you work out what went wrong.

Cannot use [] for reading

In one of my scripts, I try to do the following
$data[] = self::get($row['sr_id']); // <-- line 55
However, PHP does not allow me to do this, giving me this error
Fatal error: Cannot use [] for reading in /file.php on line 55
The self::get function return either a bool, or an object.
Edit: The get function creates a new object which again loads data from a mysql database.
The solution in my case was this:
Bad line:
$this->$ExtraTag[] = $fullscript;
Good line:
$this->{$ExtraTag}[] = $fullscript;
or
$this->ExtraTag[] = $fullscript;
Old PHP versions accepted $var[] in expressions, allowed reading out the $var content regardless of syntax. PHP 5.1 made that illegal. But sometimes the error is triggered outside of the intented context.
So my guess (again: show more code) is that the preceeding line contains an unfinished expression, to which the $data[] joins.
In case of object attribute you can wrap your $data var into { }, but that doesn't seem to be the problem in your case. (Else there is something in line 54, that you didn't show.) The right hand side can't reasonably trigger the error. Even array accessing [] an integer or object wouldn't trigger that fatal error.
So if nothing helps, just use array_push(). Work around PHP.
The error I got was:
Fatal error: Cannot use [] for reading in
/pathtosite/drupal/sites/all/themes/zenui/templates/page.tpl.php on line 33
Sometime the problem is when you include a line like this:
$page['sidebar_first'][]
This might happen if you are copying a variable name and forgot to comment out the line.
There was two problems:
1. Missing semicolon
2. $variable[] must set a variable
After fixing these two problems my code read:
$page['sidebar_first'][] = $value;
Don't forget to comment out line you are not using to help with the debugging process
Hope this helps fellow programmers like me!
I had same error with following:
echo implode(',', $array[]);
which should have been
echo implode(',', $array);
Hope this can help someone
try:
$data = Array();
$data[] = self::get($row['sr_id']); // <-- line 55
I had the same problem with my script, the following line threw the same error:
$array[]=$value
I simply replaced it by
$array[count($array)-1]=$value
and it worked perfectly.
Another possible problem could be an accidental double ==.
For example accidentally doing $myArray[] == $myNewValue; would cause this error (because you are trying to read a value with the == instead of telling PHP to assign a new array index).

Categories