Reputation: 48899
In Twig, how can I list all keys/value pairs from an object (read: private/protected properties), given that the proper getters exist?
class MyObject
{
protected $foo;
public function __construct()
{
$this->foo = 'bar';
}
public function getFoo()
{
return $this->foo;
}
}
In the above example I'd like to get "foo" (the key) and "bar" (the value). Twig already let me do something like myobject.foo
or myobject['foo']
to get "bar".
The following doesn't work (array-like syntax):
{% for key, val in myobject %}
{{ key }}={{ val }}
{% endfor %}
Should I implement Iterator
interface or there is a better/native way?
Upvotes: 1
Views: 2027
Reputation: 6946
If you're looking for a solution other than Iterator (which personally I would go with), you could create a twig extension that provides a filter:
http://symfony.com/doc/current/cookbook/templating/twig_extension.html
From here you can manipulate the object however you wish. For example a to_array
filter, that accepts various types of values and converts them (to the best of its ability) to an array, eg:
Convert PHP object to associative array
{% for key, val in myobject|to_array %}
{{ key }}={{ val }}
{% endfor %}
However this is simply providing you with the solution you asked for, Peter's method is generally better practice.
Upvotes: 1
Reputation: 105868
This has nothing to do with Twig directly, but rather how PHP handles the iteration of objects.
So, for example, what happens if you do this?
class MyObject
{
protected $foo;
public function __construct()
{
$this->foo = 'bar';
}
public function getFoo()
{
return $this->foo;
}
}
$myObject = new MyObject();
foreach ( $myObject as $property => $value )
{
echo "$property: $value<br>";
}
Nothing. Zilch. Nada. A white screen in your browser.
However, if you cast your object as an array, then it works
foreach ( (array) $myObject as $property => $value )
{
echo "$property: $value<br>";
}
// *foo: bar
What's up with that asterisk? More on that later...
However, you can't use PHP's explicit type casting in Twig. So what now? Enter IteratorAggregate
class MyObject implements \IteratorAggregate
{
protected $foo;
public function __construct()
{
$this->foo = 'bar';
}
public function getFoo()
{
return $this->foo;
}
public function getIterator()
{
return new \ArrayIterator( (array) $this );
}
}
However, you will still have one issue: that darned asterisk. It's there because MyObject::$foo
is protected
- PHP automatically does this when the type is converted from MyObject to array. So, what now? Well, there are other ways to expose/create iterators on objects. You could always do it "manually"
public function getIterator()
{
return new \ArrayIterator( array(
'foo' => $this->getFoo()
) );
}
You could alternatively implement Iterator or go even deeper down the rabbit's hole and inherit from ArrayObject
Upvotes: 3