Discussion:
Best way of iterating over object member fields?
Peter Ford
2014-09-03 09:23:34 UTC
Permalink
I came across a bug in some of my code, where I do something like the following:

$obj = new MyObject();

foreach ($obj as $key=>$value)

{

echo $key;

}


Note that I don't use $value in the loop - I'm only doing processing based on
the field name.
Now my IDE flags this unused variable as a hint, so (on autopilot) I changed it
to be

$obj = new MyObject();
foreach (array_keys($obj) as $key)
{
echo $key;
}

Which removes the hint, and looks like the right sort of thing.
Of course this doesn't work: "array_keys() expects parameter 1 to be an array,
object found".

So what is the correct way to list the field names of an object?

Cheers
Pete
--
Peter Ford phone: 01580 893333 fax: 01580 893399
Justcroft International Ltd. www.justcroft.com
Justcroft House, High Street, Staplehurst, Kent TN12 0AH United Kingdom
Registered in England and Wales: 2297906
Registered office: Stag Gates House, 63/64 The Avenue, Southampton SO17 1XS
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Stuart Dallas
2014-09-03 09:34:34 UTC
Permalink
On Wednesday, Sep 3, 2014 at 10:23 am, Peter Ford <***@justcroft.com>, wrote:


-Stuart




— 

Stuart Dallas

3ft9 Ltd

http://3ft9.com/
I came across a bug in some of my code, where I do something like the following:

$obj = new MyObject();

foreach ($obj as $key=>$value)

{

echo $key;

}


Note that I don't use $value in the loop - I'm only doing processing based on
the field name.
Now my IDE flags this unused variable as a hint, so (on autopilot) I changed it
to be

$obj = new MyObject();
foreach (array_keys($obj) as $key)
{
echo $key;
}

Which removes the hint, and looks like the right sort of thing.
Of course this doesn't work: "array_keys() expects parameter 1 to be an array,
object found".

So what is the correct way to list the field names of an object?

Two ways depending on whether you want to get them from the class definition or what the object actually contains:




* http://php.net/get-class-vars
* http://php.net/get-object-vars
Peter Ford
2014-09-03 10:19:35 UTC
Permalink
Post by Stuart Dallas
-Stuart

Stuart Dallas
3ft9 Ltd
http://3ft9.com/
$obj = new MyObject();
foreach ($obj as $key=>$value)
{
echo $key;
}
Note that I don't use $value in the loop - I'm only doing processing based on
the field name.
Now my IDE flags this unused variable as a hint, so (on autopilot) I changed it
to be
$obj = new MyObject();
foreach (array_keys($obj) as $key)
{
echo $key;
}
Which removes the hint, and looks like the right sort of thing.
Of course this doesn't work: "array_keys() expects parameter 1 to be an array,
object found".
So what is the correct way to list the field names of an object?
* http://php.net/get-class-vars
* http://php.net/get-object-vars
Thanks Stuart,

RTFM works nicely :)

Of course, the line gains a bit of weight:

foreach (array_keys(get_class_vars('MyObject')) as $key)


but at least it clears the hint.
--
Peter Ford phone: 01580 893333 fax: 01580 893399
Justcroft International Ltd. www.justcroft.com
Justcroft House, High Street, Staplehurst, Kent TN12 0AH United Kingdom
Registered in England and Wales: 2297906
Registered office: Stag Gates House, 63/64 The Avenue, Southampton SO17 1XS
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
David Harkness
2014-09-03 17:52:17 UTC
Permalink
Post by Peter Ford
RTFM works nicely :)
foreach (array_keys(get_class_vars('MyObject')) as $key)
but at least it clears the hint.
Keep in mind that hints are just that: hints that perhaps you may simplify
the code or improve performance by removing an operation that produces a
value that's never used. Iterating over the keys and values of an object is
an O(n) operation. Building an array of key/value mappings from an object's
properties is an O(n) operation. And building another array holding just
the keys (as values) is yet another O(n) operation.

Thus, to remove a squiggly line under the $value variable in your IDE,
you've turned an O(n) operation into an O(3n) operation. Granted, O(3n) is
still O(n), but clearly it will take roughly three times as long.* And
consider what happens when transforming the object to an array of
key/values to an array of keys. Note that the values are accessed, packaged
up into an array, and then tossed away. That's no different from ignoring
the value in the loop.

Moving from performance to simplicity of design, I find this form more
complicated. You must recognize (or look up) the two functions to see
what's happening. But the simpler loop over the object with an underlined
$value is immediately obvious: you're looping over the object's properties
and ignoring the values.

I would revert to your original form and possibly file a feature request to
support using $ without a name to indicate a throwaway variable that should
not receive a value (similar to _ in Python, though I believe that is an
actual variable and _ is used as a convention to indicate "I don't care
about this value").

foreach ($object as $key => $)

This would come in handy in other cases where you want to ignore values:

list($, $author, $name) = explode(',', '123,Charles Lutwidge
Dodgson,Alice in Wonderland');

Cheers,
David

* Of course, array_keys and get_class_vars are internal functions and will
execute faster than iteration over the resulting array or object in PHP
code.
David Harkness
2014-09-04 18:20:20 UTC
Permalink
The IDE I'm using (NetBeans) can be tuned to turn various hints on and
off, but the 'unused variable' hint that my code throws up is not
fine-grained enough to handle cases where the unused variable is actually
the most efficient way to do it.
I use NetBeans as well, and it seems like a reasonable request to have it
detect these two cases of acceptable unused variables. I've submitted a
feature request [1] and noticed that they recently altered the hint in the
case of catching and ignoring an exception [2].

Cheers,
David

[1] https://netbeans.org/bugzilla/show_bug.cgi?id=246880
[2] https://netbeans.org/bugzilla/show_bug.cgi?id=246230
Peter Ford
2014-09-05 08:23:51 UTC
Permalink
Post by David Harkness
The IDE I'm using (NetBeans) can be tuned to turn various hints on and
off, but the 'unused variable' hint that my code throws up is not
fine-grained enough to handle cases where the unused variable is actually
the most efficient way to do it.
I use NetBeans as well, and it seems like a reasonable request to have it
detect these two cases of acceptable unused variables. I've submitted a
feature request [1] and noticed that they recently altered the hint in the
case of catching and ignoring an exception [2].
Cheers,
David
[1] https://netbeans.org/bugzilla/show_bug.cgi?id=246880
[2] https://netbeans.org/bugzilla/show_bug.cgi?id=246230
Thanks for opening that, David: I hadn't got around to submitting a request yet!
I have contributed a comment regarding the object iteration that was my special
case, and voted for it. Let's see what happens.

Cheers
Pete
--
Peter Ford phone: 01580 893333 fax: 01580 893399
Justcroft International Ltd. www.justcroft.com
Justcroft House, High Street, Staplehurst, Kent TN12 0AH United Kingdom
Registered in England and Wales: 2297906
Registered office: Stag Gates House, 63/64 The Avenue, Southampton SO17 1XS
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
David Harkness
2014-09-05 21:09:42 UTC
Permalink
Post by Peter Ford
I have contributed a comment regarding the object iteration that was my
special case.
Oops, I read too quickly and thought one of the devs had commented with an
objection. You can ignore my reply to your comment. :) I see also that they
escalated it to a defect instead of an enhancement which makes it very
likely to be addressed.

Cheers,
David

Shawn McKenzie
2014-09-03 19:31:17 UTC
Permalink
Should also work:

foreach(array_keys((array)$MyObject) as $key)

Or:

while(list($key) = each($MyObject))
Shaun Morrow
2014-09-03 09:42:38 UTC
Permalink
Post by Peter Ford
$obj = new MyObject();
foreach ($obj as $key=>$value)
{
echo $key;
}
Note that I don't use $value in the loop - I'm only doing processing based
on the field name.
Now my IDE flags this unused variable as a hint, so (on autopilot) I
changed it to be
$obj = new MyObject();
foreach (array_keys($obj) as $key)
{
echo $key;
}
Which removes the hint, and looks like the right sort of thing.
Of course this doesn't work: "array_keys() expects parameter 1 to be an
array, object found".
So what is the correct way to list the field names of an object?
Cheers
Pete
--
Peter Ford phone: 01580 893333 fax: 01580 893399
Justcroft International Ltd.
www.justcroft.com
Justcroft House, High Street, Staplehurst, Kent TN12 0AH United Kingdom
Registered in England and Wales: 2297906
Registered office: Stag Gates House, 63/64 The Avenue, Southampton SO17 1XS
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
You could use get_object_vars

http://php.net/manual/en/function.get-object-vars.php

So something like the following may work (not tested)

$obj = new MyObject();
foreach (array_keys(get_object_vars($obj)) as $key)
{
echo $key;
}

Regards,

Shaun
Loading...