# array_key_exists BC break

- Thread: https://externals.io/message/41348
- Original archive: https://news-web.php.net/php.internals/41348
- Started by Stanislav Malyshev on 2008-10-23T20:16:01+00:00
- Messages: 57
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/41348.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #41348 — Stanislav Malyshev — 2008-10-23T20:16:01+00:00

URL: https://externals.io/message/41348#41348

Hi!

I notice that 5.3 differs from 5.2 in how array_key_exists treats 
objects. In 5.2, if the second parameter (array) is allowed to be object 
and HASH_OF is applied to it. However, in 5.3 it would produce a warning 
requiring an array if object passed to it. Was it intentional?
Maybe the problem is deeper and is in zend_parse_arg_impl where it 
should allow objects for 'a' if we can have HASH_OF from them?
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #41349 — Mark van der Velden — 2008-10-23T20:40:48+00:00

URL: https://externals.io/message/41348#41349 · In reply to: #41348

Stanislav Malyshev wrote:
> Hi!
> 
> I notice that 5.3 differs from 5.2 in how array_key_exists treats
> objects. In 5.2, if the second parameter (array) is allowed to be object
> and HASH_OF is applied to it. However, in 5.3 it would produce a warning
> requiring an array if object passed to it. Was it intentional?
> Maybe the problem is deeper and is in zend_parse_arg_impl where it
> should allow objects for 'a' if we can have HASH_OF from them?

To my understanding, it's superseded by the function property_exists.
Also notice the difference of argument order.

As written here: http://docs.php.net/array_key_exists

---

## #41350 — Stanislav Malyshev — 2008-10-23T21:15:10+00:00

URL: https://externals.io/message/41348#41350 · In reply to: #41349

Hi!

> > […]
> 
> To my understanding, it's superseded by the function property_exists.
> Also notice the difference of argument order.

Ah, ok, missed this note, thanks.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #41355 — Ionut Gabriel Stan — 2008-10-24T09:05:07+00:00

URL: https://externals.io/message/41348#41355 · In reply to: #41349

But wouldn't be useful to at least accept objects implementing ArrayAccess?



> Stanislav Malyshev wrote:
>    
> > […]
>
> To my understanding, it's superseded by the function property_exists.
> Also notice the difference of argument order.
>
> As written here: http://docs.php.net/array_key_exists

---

## #41356 — Alexey Zakhlestin — 2008-10-24T09:15:26+00:00

URL: https://externals.io/message/41348#41356 · In reply to: #41355

On Fri, Oct 24, 2008 at 1:05 PM, Ionut Gabriel Stan
<ionut.g.stan@gmail.com> wrote:
> But wouldn't be useful to at least accept objects implementing ArrayAccess?

sounds like a good idea to me

>
> 
> > […]
>
>
> --
> 
> 
>
>



-- 
Alexey Zakhlestin
http://blog.milkfarmsoft.com/

---

## #41357 — Felipe Pena — 2008-10-24T10:06:05+00:00

URL: https://externals.io/message/41348#41357 · In reply to: #41350

Hi Stas,

2008/10/23 Stanislav Malyshev <stas@zend.com>:
> Hi!
>
> > […]
>
> Ah, ok, missed this note, thanks.

In fact, all HASH_OF was removed in standard/array.c, and that's
already is mentioned implicitly though, as
"The functions `next()`/current/… don't take objects anymore as
parameters. For accessing their properties using this way you have to
cast the objects to arrays first."

-- 
Regards,
Felipe Pena.

---

## #41367 — johannes@php.net — 2008-10-24T13:28:08+00:00

URL: https://externals.io/message/41348#41367 · In reply to: #41356

> On Fri, Oct 24, 2008 at 1:05 PM, Ionut Gabriel Stan
> <ionut.g.stan@gmail.com> wrote:
> > […]
> 
> sounds like a good idea to me

nope that would mean that some scripts might work different between 5.2
and 5.3, now one gets an error. consider such a script:

<?php
class Foo extends ArrayAccess {
    public $prop = 42;
    function offsetGet($n) { ... }
    ....
}

$o = new foo;
array_key_Exists('prop', $o);
?>

In <= 5.2 it will return the value of $o->prop, in 5.3 it would call the
offsetGet() method. 

I prefer an error, if many people want the old behavior that's fine to
me, but don't change it.

btw. this also affects quite a few other functions: next/current/key/...
at least ... and maybe more after using the "new" parameter parsing API.

johannes

---

## #41368 — David Grudl — 2008-10-24T14:01:36+00:00

URL: https://externals.io/message/41348#41368 · In reply to: #41348

Hello,

I have reported this bug http://bugs.php.net/bug.php?id=46354, because 
new behaviour breaks my script. The question is how fix scripts for new 
behaviour. Example:

// common array
$a = array('item' => NULL);
isset($a['item']) -> `FALSE` 
array_key_exists($a['item']) -> `TRUE` 

// ArrayObject
$o = new ArrayObject($a);
isset($o['item']) -> `TRUE` (!)
$o->offsetExists($o['item']) -> `TRUE` (!), in PHP 5.2.1 `FALSE` (!)

Should one rely on this 'isset' behaviour, i.e. will isset($a['item']) 
return `TRUE` in future?

David Grudl

---

## #41369 — Stanislav Malyshev — 2008-10-24T17:05:48+00:00

URL: https://externals.io/message/41348#41369 · In reply to: #41367

Hi!

> nope that would mean that some scripts might work different between 5.2
> and 5.3, now one gets an error. consider such a script:

Just so it is clear - some scripts ALREADY work differently, that's why 
it says "BC break".

> <?php
> class Foo extends ArrayAccess {
>     public $prop = 42;
>     function offsetGet($n) { ... }
>     ....
> }
> 
> $o = new foo;
> array_key_Exists('prop', $o);
> ?>
> 
> In <= 5.2 it will return the value of $o->prop, in 5.3 it would call the
> offsetGet() method. 

In 5.2 it would return true and not the value of $o->prop.
In 5.3 I don't think it would call offsetGet. It would call 
get_properties method of ArrayAccess, and that should return list of 
object's properties as array, so in this case the return will still be true.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #41371 — johannes@php.net — 2008-10-24T18:23:04+00:00

URL: https://externals.io/message/41348#41371 · In reply to: #41369

> Hi!
> 
> > […]
> 
> Just so it is clear - some scripts ALREADY work differently, that's why 
> it says "BC break".

There's a difference between "working differently, but doing something"
and "throwing an error".

> > […]
> 
> In 5.2 it would return true and not the value of $o->prop.
> In 5.3 I don't think it would call offsetGet. It would call 
> get_properties method of ArrayAccess, and that should return list of 
> object's properties as array, so in this case the return will still be true.

I didn't check array_key_exists but most of the affected functions use
Z_OBJ_HT and therefore directly access the property table, not the
property access APIs.

Now changing to these APIs will be a silent change, whereas the old
behavior might be considered as a bug, throwing an error might be a good
compromise.

Example showing the 3 different behaviors:

$ cat array_key_exists_array_access.php
<?php
class Test implements ArrayAccess {
    public $prop = "property";

    public function offsetExists($key) {
        echo __METHOD__,"($key)\n";
        return false;
    }

    public function offsetGet($key) {
        echo __METHOD__,"($key)\n";
        return null;
    }

    public function offsetSet($key, $value) {}
    public function offsetUnset($key) {}
}

$o = new Test();
var_dump(array_key_exists("prop", $o));
?>

1)
$ php52 array_key_exists_array_access.php
bool(true)

2)
$ php53 array_key_exists_array_access.php

Warning: `array_key_exists()` expects parameter 2 to be array, object
given in /home/johannes/public_html/- on line 20
 `NULL` 

3)
Result after using ArrayAccess:

Test::offsetExistst(prop)
bool(false)


Going from 1) to 3) will certainly confuse users and leads to changes in
behavior which can't be found in an easy way...

johannes

---

## #41476 — Andrei Zmievski — 2008-10-27T18:34:09+00:00

URL: https://externals.io/message/41348#41476 · In reply to: #41367

Johannes Schlüter wrote:
> btw. this also affects quite a few other functions: next/current/key/...
> at least ... and maybe more after using the "new" parameter parsing API.

I would say "no" for 5.3. But for 6 it would be fantastic to have all array-related 
operations supporting ArrayAccess interface, where possible.

-Andrei

---

## #41477 — Sean Coates — 2008-10-27T18:39:35+00:00

URL: https://externals.io/message/41348#41477 · In reply to: #41476

> > […]
>
> I would say "no" for 5.3. But for 6 it would be fantastic to have  
> all array-related operations supporting ArrayAccess interface, where  
> possible.

I was hoping someone would revive this thread (-:

In Habari, we have/had an ArrayObject that we passed to the view  
(theme). As far as the theme knows, this is an array (but it has extra  
methods if the theme is particularly smart).

Unfortunately, this breaks in 5.3, because many of the themes use  
 `reset()` to get the first element of the array (ArrayObject, but the  
theme doesn't necessarily know this).

This is a real-world BC break, and without allowing ArrayObject to act  
like an array, it's nearly useless. We've temporarily "solved" this by  
casting the ArrayObject to an array, which is silly. This should be  
fixed in 5.3, IMO.

I discussed this with Johannes a bit, yesterday.

S

---

## #41478 — Andrei Zmievski — 2008-10-27T18:41:58+00:00

URL: https://externals.io/message/41348#41478 · In reply to: #41477

Sean Coates wrote:
> I was hoping someone would revive this thread (-:
> 
> In Habari, we have/had an ArrayObject that we passed to the view 
> (theme). As far as the theme knows, this is an array (but it has extra 
> methods if the theme is particularly smart).
> 
> Unfortunately, this breaks in 5.3, because many of the themes use 
> `reset()` to get the first element of the array (ArrayObject, but the 
> theme doesn't necessarily know this).
> 
> This is a real-world BC break, and without allowing ArrayObject to act 
> like an array, it's nearly useless. We've temporarily "solved" this by 
> casting the ArrayObject to an array, which is silly. This should be 
> fixed in 5.3, IMO.
> 
> I discussed this with Johannes a bit, yesterday.

I see. If it's a real-world BC break, then it should be fixed.

-a

---

## #41518 — Lars Strojny — 2008-10-28T13:16:40+00:00

URL: https://externals.io/message/41348#41518 · In reply to: #41476

Hi Andrei,

Am Montag, den 27.10.2008, 11:34 -0700 schrieb Andrei Zmievski:
[...]
> I would say "no" for 5.3. But for 6 it would be fantastic to have all array-related 
> operations supporting ArrayAccess interface, where possible.

+1 for this.

cu, Lars
-- 
   Jabber: lars@strojny.net
   Weblog: http://usrportage.de

---

## #41519 — Ionut Gabriel Stan — 2008-10-28T14:00:20+00:00

URL: https://externals.io/message/41348#41519 · In reply to: #41518

While we're at this and considering the new lambdas that we now have in 
the language
I must say I'd like some functions to support Traversables. Those would be:

 `array_map()`, `array_reduce()`, `array_filter()`, `array_walk()` and 
 `array_walk_recursive()`

Although I'd rather want a class (because the array_* functions don't 
adhere to some strict param order standards)
to provide functional style methods, like those in Javascript 1.8:

https://developer.mozilla.org/index.php?title=En/New_in_JavaScript_1.6#section_2
https://developer.mozilla.org/index.php?title=En/New_in_JavaScript_1.8#section_4

Array.forEach()
Array.map()
Array.filter()
Array.reduce()
Array.reduceRight()
Array.some()
Array.every()


In PHP something like this would be nice:

$processedDirectoryIterator = SplFunctional(new 
DirecotoryIterator(__DIR__)).map(function() {
     // do stuff here
});

where SplFunctional is a function returning a SplFunctional object whose 
construcor accepts iteratable
structures (arrays or Traversables) and $processDirectoryIterator is a 
DirectoryIterator resulted after applying
the lamba to each of the SplFileObjects contained.

I know right now we have FilterIterator as an equivalent to 
 `array_filter()` for Iterators and we could implement our
own Functional classes but that means a new class for situations where a 
simple lambda could do the job
just as well.

I hope my proposal makes sense.


P.S. I introduced a SplFunctional function just to skip the 
instantiation of the object.




> Hi Andrei,
>
> Am Montag, den 27.10.2008, 11:34 -0700 schrieb Andrei Zmievski:
> [...]
>    
> > […]
>
> +1 for this.
>
> cu, Lars

---

## #41520 — Lars Strojny — 2008-10-28T14:08:18+00:00

URL: https://externals.io/message/41348#41520 · In reply to: #41519

Hi Ionut,

Am Dienstag, den 28.10.2008, 16:00 +0200 schrieb Ionut Gabriel Stan:
[...]
> While we're at this and considering the new lambdas that we now have
> in the language I must say I'd like some functions to support
> Traversables.

Nevertheless I agree that this would be a great feature, I would like to
ask to stop concrete feature evaluation here and write an RFC so we have
something to read before we start to think about "what would be nice?".

cu, Lars
-- 
   Jabber: lars@strojny.net
   Weblog: http://usrportage.de

---

## #41521 — Kalle Sommer Nielsen — 2008-10-28T14:23:00+00:00

URL: https://externals.io/message/41348#41521 · In reply to: #41519

Hi Ionut

2008/10/28 Ionut Gabriel Stan <ionut.g.stan@gmail.com>:
> While we're at this and considering the new lambdas that we now have in the
> language
> I must say I'd like some functions to support Traversables. Those would be:
>
> `array_map()`, `array_reduce()`, `array_filter()`, `array_walk()` and
> `array_walk_recursive()`
>
> Although I'd rather want a class (because the array_* functions don't adhere
> to some strict param order standards)
> to provide functional style methods, like those in Javascript 1.8:
>
> https://developer.mozilla.org/index.php?title=En/New_in_JavaScript_1.6#section_2
> https://developer.mozilla.org/index.php?title=En/New_in_JavaScript_1.8#section_4
>
> Array.forEach()
> Array.map()
> Array.filter()
> Array.reduce()
> Array.reduceRight()
> Array.some()
> Array.every()
>
>
> In PHP something like this would be nice:
>
> $processedDirectoryIterator = SplFunctional(new
> DirecotoryIterator(__DIR__)).map(function() {
>    // do stuff here
> });

This would indeed be nice, but theres one thing yet, PHP doesn't
support closure objects, take for example:

<?php
class Test
{
	public function hello($who)
	{
		echo 'Hello ' . $who;
	}
}

$closure = function()
{
	static $instance;

	if(!$instance)
	{
		$instance = new Test;
	}

	return($instance);
};

$closure->hello('Kalle'); // Fatal error, undefined method Closure::hello()

But you should indeed make an RFC for this and even create a patch if
you're able to :)

>
> where SplFunctional is a function returning a SplFunctional object whose
> construcor accepts iteratable
> structures (arrays or Traversables) and $processDirectoryIterator is a
> DirectoryIterator resulted after applying
> the lamba to each of the SplFileObjects contained.
>
> I know right now we have FilterIterator as an equivalent to `array_filter()`
> for Iterators and we could implement our
> own Functional classes but that means a new class for situations where a
> simple lambda could do the job
> just as well.
>
> I hope my proposal makes sense.
>
>
> P.S. I introduced a SplFunctional function just to skip the instantiation of
> the object.
>
>
>
> 
> > […]
>
>
> --
> 
> 
>
>



-- 
Kalle Sommer Nielsen

---

## #41522 — Stan Vassilev | FM — 2008-10-28T14:33:15+00:00

URL: https://externals.io/message/41348#41522 · In reply to: #41518

> > […]
>
>+1 for this.
>
>Hi,
>cu, Lars

Just making sure but: I think the BC break should be fixed. It's breaking 
actual code out there. The practice of passing traversable objects to our 
views, mixed with real arrays, is already common (I do it too).

Regards,
Stan Vassilev

---

## #41524 — Kalle Sommer Nielsen — 2008-10-28T14:41:13+00:00

URL: https://externals.io/message/41348#41524

2008/10/28 Stan Vassilev | FM <sv_forums@fmethod.com>:
> > […]
>
> Technically since the closure holds a function returning the object, it
> should be:

doh yes, I must be sleeping :)

>
> $closure()->hello('Kalle');
>
> Regards, Stan Vassilev
>



-- 
Kalle Sommer Nielsen

---

## #41540 — Ionut Gabriel Stan — 2008-10-28T22:31:48+00:00

URL: https://externals.io/message/41348#41540 · In reply to: #41521

Hi,

Thanks for your positive feedback about my idea and sorry for hijacking this
thread.

Although my C skills are limited to its syntax only I'll create an RFC, then
someone
else might give it a try an create a patch.

All the best,
Ionut


On Tue, Oct 28, 2008 at 4:23 PM, Kalle Sommer Nielsen
<kalle.php@gmail.com>wrote:

> Hi Ionut
>
> 2008/10/28 Ionut Gabriel Stan <ionut.g.stan@gmail.com>:
> > […]
> the
> > […]
> be:
> > […]
> adhere
> > […]
> https://developer.mozilla.org/index.php?title=En/New_in_JavaScript_1.6#section_2
> > […]
> https://developer.mozilla.org/index.php?title=En/New_in_JavaScript_1.8#section_4
> > […]
>
> This would indeed be nice, but theres one thing yet, PHP doesn't
> support closure objects, take for example:
>
> <?php
> class Test
> {
>        public function hello($who)
>        {
>                echo 'Hello ' . $who;
>        }
> }
>
> $closure = function()
> {
>        static $instance;
>
>        if(!$instance)
>        {
>                $instance = new Test;
>        }
>
>        return($instance);
> };
>
> $closure->hello('Kalle'); // Fatal error, undefined method Closure::hello()
>
> But you should indeed make an RFC for this and even create a patch if
> you're able to :)
>
> > […]
> `array_filter()`
> > […]
> of
> > […]
>
>
>
> --
> Kalle Sommer Nielsen

---

## #41665 — Lukas Kahwe Smith — 2008-11-04T21:55:48+00:00

URL: https://externals.io/message/41348#41665 · In reply to: #41522

> > […]
>
> Just making sure but: I think the BC break should be fixed. It's  
> breaking actual code out there. The practice of passing traversable  
> objects to our views, mixed with real arrays, is already common (I  
> do it too).


so where do we stand here?

regards,
Lukas Kahwe Smith
mls@pooteeweet.org

---

## #41669 — Stanislav Malyshev — 2008-11-04T22:59:49+00:00

URL: https://externals.io/message/41348#41669 · In reply to: #41665

Hi!

> so where do we stand here?

I'd prefer to have it fixed, but then it probably requires changing the 
parameters API for 'a', which might lead to some unexpected results with 
regard to functions that modify their arguments. I think we may leave it 
alone for this alpha but try to resolve it for 5.3 release.
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #41670 — Sean Coates — 2008-11-04T23:06:13+00:00

URL: https://externals.io/message/41348#41670 · In reply to: #41669

> I'd prefer to have it fixed, but then it probably requires changing  
> the parameters API for 'a', which might lead to some unexpected  
> results with regard to functions that modify their arguments. I  
> think we may leave it alone for this alpha but try to resolve it for  
> 5.3 release.

If my opinion matters, I'd also prefer to see that fixed. As I  
mentioned earlier in the thread, ArrayObject loses a lot of value if  
it can't be treated as an array.

S

---

## #41686 — Geoffrey Sneddon — 2008-11-05T16:20:20+00:00

URL: https://externals.io/message/41348#41686 · In reply to: #41669

> > […]
>
> I'd prefer to have it fixed, but then it probably requires changing  
> the parameters API for 'a', which might lead to some unexpected  
> results with regard to functions that modify their arguments. I  
> think we may leave it alone for this alpha but try to resolve it for  
> 5.3 release.

If it isn't fixed it ought to be a documented as a BC break, seeming  
it does break real apps.


--
Geoffrey Sneddon
<http://gsnedders.com/

---

## #41718 — Felipe Pena — 2008-11-06T12:10:06+00:00

URL: https://externals.io/message/41348#41718 · In reply to: #41686

Hi all,

Em Qua, 2008-11-05 às 16:20 +0000, Geoffrey Sneddon escreveu:
> 
> 
> > […]
> 
> If it isn't fixed it ought to be a documented as a BC break, seeming  
> it does break real apps.
> 
> 

So as suggested and wished, here is a patch that add a modifier '%' to
'a' in parameter parsing API, where it allows object that implements
ArrayAccess to be accept. Although it doesn't invoke any their methods,
i.e. just how it works nowdays.

A list of functions that allow object on current 5.2:
. end
. prev
. next
. reset
. current
. key
. array_key_exists
. array_unique
. array_flip
. array_walk_recursive
. array_walk
. uksort
. uasort
. usort
. natcasesort
. natsort

Hence, I added such modifier to this functions in the patch.

5.3: http://felipe.ath.cx/diff/arg_arrayaccess.diff

-- 
Regards,
Felipe Pena

---

Next page: https://externals.io/message/41348.md?page=2
