<pre><code>    {{ entry.title }}
</code></pre>
<p>compiles down to:</p>
<pre class="lang-php prettyprint-override"><code>        echo twig_escape_filter($this-&gt;env, craft\helpers\Template::attribute($this-&gt;env, $this-&gt;source, (isset($context[&quot;entry&quot;]) || array_key_exists(&quot;entry&quot;, $context) ? $context[&quot;entry&quot;] : (function () { throw new RuntimeError('Variable &quot;entry&quot; does not exist.', 19, $this-&gt;source); })()), &quot;title&quot;, []), &quot;html&quot;, null, true);
</code></pre>
<p>...and</p>
<pre><code>    {{ entry['title'] }}
</code></pre>
<p>compiles down to:</p>
<pre class="lang-php prettyprint-override"><code>        echo twig_escape_filter($this-&gt;env, craft\helpers\Template::attribute($this-&gt;env, $this-&gt;source, (isset($context[&quot;entry&quot;]) || array_key_exists(&quot;entry&quot;, $context) ? $context[&quot;entry&quot;] : (function () { throw new RuntimeError('Variable &quot;entry&quot; does not exist.', 20, $this-&gt;source); })()), &quot;title&quot;), &quot;html&quot;, null, true);
</code></pre>
<p>...and</p>
<pre><code>    {{ attribute(entry, 'title') }}
</code></pre>
<p>compiles down to:</p>
<pre class="lang-php prettyprint-override"><code>        echo twig_escape_filter($this-&gt;env, craft\helpers\Template::attribute($this-&gt;env, $this-&gt;source, (isset($context[&quot;entry&quot;]) || array_key_exists(&quot;entry&quot;, $context) ? $context[&quot;entry&quot;] : (function () { throw new RuntimeError('Variable &quot;entry&quot; does not exist.', 21, $this-&gt;source); })()), &quot;title&quot;, [], &quot;array&quot;), &quot;html&quot;, null, true);
</code></pre>
<p>If they look similar, that's because... they are identical in terms of the PHP code they compile down to.</p>
<p>So the difference is... whichever one uses the fewest keystrokes to type.</p>

CC BY-SA 4.0
2021-03-04T17:23:34.517Z
There seems to hovewer be some difference - for non existing field, `entry.dwfgfrg is defined` returns true, but `entry['dwfgfrg'] is defined` returns false.
Piotr Pogorzelski
CC BY-SA 4.0
2021-03-05T15:41:57.567Z
Check out Ben Parizek's answer in this thread: https://craftcms.stackexchange.com/questions/2116/twig-is-defined-always-returning-true
andrew.welch
CC BY-SA 4.0
2021-03-05T17:50:17.453Z
They will definitely throw different errors in different circumstances. You may want to conduct the same test, but where `entry` is properly defined, and it's only the `attribute` that is missing.
Lindsey D
CC BY-SA 4.0
2021-03-06T18:11:41.893Z
The difference here is in how the "is defined" test works tho, now how the various ways of accessing properties works. Ben gives a really good explanation in the above link
andrew.welch
CC BY-SA 4.0
2021-03-04T03:31:10.070Z
2021-03-04T03:31:10.070Z
andrew.welch
<p>There are three methods for that:</p>
<pre><code>object.attribute
</code></pre>
<pre><code>object['attribute']
</code></pre>
<pre><code>attr(object, 'attribute')
</code></pre>
<p>How are these different from each other?</p>

<templating>
Accessing array/object attributes in Twig
# Accessing array/object attributes in Twig

(Asked by: username_0 on 2021-03-01)

There are three methods for that:
object.attribute

object['attribute']

attr(object, 'attribute')

How are these different from each other?

**Tags:** templating


---

## 1 answers

### Answer by username_1 on 2021-03-04. Score: 4 | Accepted answer

{{ entry.title }}

compiles down to:
        echo twig_escape_filter($this->env, craft\helpers\Template::attribute($this->env, $this->source, (isset($context["entry"]) || array_key_exists("entry", $context) ? $context["entry"] : (function () { throw new RuntimeError('Variable "entry" does not exist.', 19, $this->source); })()), "title", []), "html", null, true);

...and
    {{ entry['title'] }}

compiles down to:
        echo twig_escape_filter($this->env, craft\helpers\Template::attribute($this->env, $this->source, (isset($context["entry"]) || array_key_exists("entry", $context) ? $context["entry"] : (function () { throw new RuntimeError('Variable "entry" does not exist.', 20, $this->source); })()), "title"), "html", null, true);

...and
    {{ attribute(entry, 'title') }}

compiles down to:
        echo twig_escape_filter($this->env, craft\helpers\Template::attribute($this->env, $this->source, (isset($context["entry"]) || array_key_exists("entry", $context) ? $context["entry"] : (function () { throw new RuntimeError('Variable "entry" does not exist.', 21, $this->source); })()), "title", [], "array"), "html", null, true);

If they look similar, that's because... they are identical in terms of the PHP code they compile down to.
So the difference is... whichever one uses the fewest keystrokes to type.

> **Comments:**
> **username_0**: There seems to hovewer be some difference - for non existing field, `entry.dwfgfrg is defined` returns true, but `entry['dwfgfrg'] is defined` returns false.  
> **username_1**: Check out Ben Parizek's answer in this thread: https://craftcms.stackexchange.com/questions/2116/twig-is-defined-always-returning-true  
> **username_2**: They will definitely throw different errors in different circumstances. You may want to conduct the same test, but where `entry` is properly defined, and it's only the `attribute` that is missing.  
> **username_1**: The difference here is in how the "is defined" test works tho, now how the various ways of accessing properties works. Ben gives a really good explanation in the above link  

---

