Fatal Error - Cannot use string offset as an array...

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

astions wrote:I don't agree with that at all. Brackets should strictly be reserved for array indexes and braces should be strictly reserved for string offsets.
Having a C background I was surprised that there was something like $str{1}. Strings were either objects or an array of chars for me. Why bother to add more special symbols for accessing a single element of a string?
Did you know that {} and [] are completely interchangeable?

Code: Select all

$arr = array('abc', new stdClass);
ecno $arr[0][1], "\n";
echo $arr{1}->prop = 1234;
print_r($arr);
There's no difference for the engine. Only the manual said "use x for this and y for that".

Code: Select all

$arr = array('abc', 'xyz');
echo $arr[1][1];
If you find that confusing you can always use

Code: Select all

$arr = array('abc', 'xyz');
echo substr($arr[1], 1 ,1);
These people are nuts. Who can I gripe to?
I'd ask Zeev Suraski ;)
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

volka wrote: Did you know that {} and [] are completely interchangeable?
Except that $a{} = x is not allowed and curlies are also used for indirect references as in $obj->{blah}.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

stereofrog wrote:Except that $a{} = x is not allowed

Code: Select all

<?php
$arr = array();
$arr{1} = 'abc';
print_r($arr);
works fine for me ;)
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

No, I meant empty curlies:

Code: Select all

$a = array();

$a[] = 10; // works
$a{} = 10; // parse error
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

ah ok. let me rephrase that "[] and {} are interchangeable when used to access an element".
And that's my point/opinion: [] is for accessing elements. Elements of an array or elements of a string ...or if the language supports that elements of an object.
{} is for binding things together, marking them as "one piece".
if (true) { more(); than(); one(); statement(); }
"..{$var[1][2]}..."
$obj->{$a.$b}
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

No, {} as block operator and as an accessor are completely different. The latter is just a funny way to put an expression after $ or ->

Code: Select all

$abc = 'var';
$o = new stdclass;
$o->def = '123';

echo ${'abc'};
echo ${'ab'.'c'};
echo $o->{'de'.'f'};
Of course, this is quite stupid. There's no reason why $ or -> cannot take a normal expression on the right (probably with parenthesis because of their high precedence) and why there should be a separate language construct for that.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

stereofrog wrote:No, {} as block operator and as an accessor are completely different.
I disagree.
{} is not used as accessor. I can access a variable or property without braces.
echo $a; echo $o->a; even echo $o->$a; echo "... $a ... "; All of this is possible with one atom.
But if I want two (or more) atoms to act together as identifier I need to glue them together ${'a'.'b'}, $o->{'m_'.$b}, "... {$a[1][0]} ... ".
The {} doesn't make it possible to access the data. It makes it possible to combine separate atoms to act as one identifier.
Same with codeblocks. if (true) echo 'abc'; valid and working. The {} is not necessary for a loop or condition to work.
But if I want to combine more than one statement I need the braces*. Same with functions. function foo() { a(); b(); }. The braces show us that statements have been combined.
There are differences in the implementation of course. But {} tells me something has been combined/acts as one.

--
* C syntax. Other languages may have a completely different syntax. It's "only" about consistency and "These people are nuts".
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

Object properties can be referenced directly and indirectly. With a direct reference, the property name is known at compile time and is an _identifier_

Code: Select all

php: $foo->bar 

javascript: foo.bar

java: foo.bar
With indirect reference, the property name is generally unknown at compile time because it is an _expression_ . At run-time, the expression is getting evaluated, the result is converted to string and used as a key to lookup in object property list. The expression can be trivial or quite complex, this doesn't matter a bit

Code: Select all

php: $foo->{'bar '} or $foo->{baz(quux()) + 23498230}

javascript: foo['bar'] or foo[blah() + bah()]

java: foo.getClass().getDeclaredField('bar').get()
(not sure about java one). Anyways, {} in this case have absolutely nothing to do with C-style block operator. The counterpart of the block operator on expression level is parenthesis (), not "reference brackets" {}
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

I still disagree (since I'm not talking about the technical aspect). But anyway, it doesn't matter.
Post Reply