<p>You don't want to expose a <a href="http://buildwithcraft.com/docs/plugins/records" rel="nofollow noreferrer">Record</a> to the template level for many reasons, including inadvertently letting a template call <code>record.save()</code> causing unexpected updates to the database, but you also don't want to expose any unnecessary data to the template (like "password", in your example).  A bit more info on that <a href="https://craftcms.stackexchange.com/a/2973/57">here</a>.</p>

<p>This is where <a href="http://buildwithcraft.com/docs/plugins/models" rel="nofollow noreferrer">Models</a> come in. They don't have the database overhead and you can limit what gets exposed to the template as well as combine data from multiple records into one model for easy consumption.</p>

<p>Create a <code>MyPlugin_TwitterAccountModel</code> class like so:</p>

<pre><code>class MyPlugin_TwitterAccountModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'oauth_token' =&gt; AttributeType::String,
            'screenname'  =&gt; AttributeType::String,
        );
    }
}
</code></pre>

<p>(include any other attributes your template might access)</p>

<p>Then change your <code>getAllAccounts()</code> method in your service to:</p>

<pre><code>public function getAllAccounts()
{
    $records = MyPlugin_TwitterAccountRecord::model()-&gt;findAll(array('order'=&gt;'oauth_token'));
    return MyPlugin_TwitterAccountModel::populateModels($records);
}
</code></pre>

<p>Now your template will only have access to your plugin's model.</p>

<p>Having typed all of that, I literally have no idea if it will solve your original issue.  </p>

<p>It might be some odd bug with Twig's interactions with Records that you're the first to run into since we highly discourage exposing Records to templates.</p>

CC BY-SA 3.0
2015-02-05T08:38:39.740Z
Thanks Brad that totally fixed the problem and I learned a good lesson on populating models from records. The template now works as I'd expected, so I think this is a freak bug in Twig but only instigated when there are pebkac issues... ;oD
billythekid
CC BY-SA 3.0
2015-02-05T02:21:03.083Z
2015-02-05T02:21:03.083Z
2017-04-13T12:51:00.303Z
Brad Bell
<p>I have a template variable thus</p>

<pre><code>public function twitterAccounts()
{
  return craft()-&gt;myPlugin-&gt;getAllAccounts();
  //Craft::dd(craft()-&gt;myPlugin-&gt;getAllAccounts());
}
</code></pre>

<p>it calls the following service method</p>

<pre><code>public function getAllAccounts()
{
  return MyPlugin_TwitterAccountRecord::model()-&gt;findAll(array('order'=&gt;'oauth_token'));
}
</code></pre>

<p>the record is set up like this:</p>

<pre><code>class MyPlugin_TwitterAccountRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'myPlugin_twitter_accounts';
    }

    protected function defineAttributes()
    {
        return array(
            'screen_name' =&gt; AttributeType::String,
            'id_str'      =&gt; AttributeType::String,
            'password'    =&gt; AttributeType::String,
            'oauth_token' =&gt; AttributeType::String, // this is a reference to the oauth_tokens table ID, not the actual token.
            'last_tweet'  =&gt; AttributeType::DateTime,
            'is_company'  =&gt; AttributeType::Bool,

            //array(AttributeType::Enum, 'values' =&gt; "alcohol,mixer,other"),
        );
    }
}
</code></pre>

<p>I have three records in that table 2 have values for the oauth_token field and one is NULL.</p>

<p>Before the NULL value row the following worked fine in a template...</p>

<pre><code>{% set twitterAccounts = craft.myPlugin.twitterAccounts %}
{% for thisAccount in twitterAccounts %}
  {% if thisAccount.oauth_token is defined and thisAccount.oauth_token is not null %}
    {{ thisAccount.screen_name }} is oauthed
  {% else %}
    {{ thisAccount.screen_name }} is not oauthed
  {% endif %}
{% endfor %}
</code></pre>

<p>but now I'm getting (devmode)</p>

<pre><code>Craft\MyPlugin_TwitterAccountRecord and its behaviors do not have a method or closure named "oauth_token".
</code></pre>

<p>The annoying thing is when I comment out the return in the template variable method and use the Craft::dd() I see all three rows with their proper attributes, including the null value.</p>

<p>If I change the conditional to</p>

<pre><code>{% if false and thisAccount.oauth_token is defined and thisAccount.oauth_token is not null %}
</code></pre>

<p>...in order to always be false and skip into the else, it lists all three accounts in there!</p>

<p>Can someone point me in the right direction here please? Is there a bug in templating with a NULL value in an activerecord collection? (this happens whether or not I have that orderBy oauth_token in the findAll())</p>

<p>Cheers.</p>

<plugin-development><templating><null>
Template variables from active record on NULL value
# Template variables from active record on NULL value

(Asked by: username_0 on 2015-02-04)

I have a template variable thus
public function twitterAccounts()
{
  return craft()->myPlugin->getAllAccounts();
  //Craft::dd(craft()->myPlugin->getAllAccounts());
}

it calls the following service method
public function getAllAccounts()
{
  return MyPlugin_TwitterAccountRecord::model()->findAll(array('order'=>'oauth_token'));
}

the record is set up like this:
class MyPlugin_TwitterAccountRecord extends BaseRecord
{
    public function getTableName()
    {
        return 'myPlugin_twitter_accounts';
    }

    protected function defineAttributes()
    {
        return array(
            'screen_name' => AttributeType::String,
            'id_str'      => AttributeType::String,
            'password'    => AttributeType::String,
            'oauth_token' => AttributeType::String, // this is a reference to the oauth_tokens table ID, not the actual token.
            'last_tweet'  => AttributeType::DateTime,
            'is_company'  => AttributeType::Bool,

            //array(AttributeType::Enum, 'values' => "alcohol,mixer,other"),
        );
    }
}

I have three records in that table 2 have values for the oauth_token field and one is NULL.
Before the NULL value row the following worked fine in a template...
{% set twitterAccounts = craft.myPlugin.twitterAccounts %}
{% for thisAccount in twitterAccounts %}
  {% if thisAccount.oauth_token is defined and thisAccount.oauth_token is not null %}
    {{ thisAccount.screen_name }} is oauthed
  {% else %}
    {{ thisAccount.screen_name }} is not oauthed
  {% endif %}
{% endfor %}

but now I'm getting (devmode)
Craft\MyPlugin_TwitterAccountRecord and its behaviors do not have a method or closure named "oauth_token".

The annoying thing is when I comment out the return in the template variable method and use the Craft::dd() I see all three rows with their proper attributes, including the null value.
If I change the conditional to
{% if false and thisAccount.oauth_token is defined and thisAccount.oauth_token is not null %}

...in order to always be false and skip into the else, it lists all three accounts in there!
Can someone point me in the right direction here please? Is there a bug in templating with a NULL value in an activerecord collection? (this happens whether or not I have that orderBy oauth_token in the findAll())
Cheers.

**Tags:** plugin-development, templating, null


---

## 1 answers

### Answer by username_1 on 2015-02-05. Score: 4 | Accepted answer

You don't want to expose a Record to the template level for many reasons, including inadvertently letting a template call record.save() causing unexpected updates to the database, but you also don't want to expose any unnecessary data to the template (like "password", in your example).  A bit more info on that here.
This is where Models come in. They don't have the database overhead and you can limit what gets exposed to the template as well as combine data from multiple records into one model for easy consumption.
Create a MyPlugin_TwitterAccountModel class like so:
class MyPlugin_TwitterAccountModel extends BaseModel
{
    protected function defineAttributes()
    {
        return array(
            'oauth_token' => AttributeType::String,
            'screenname'  => AttributeType::String,
        );
    }
}

(include any other attributes your template might access)
Then change your getAllAccounts() method in your service to:
public function getAllAccounts()
{
    $records = MyPlugin_TwitterAccountRecord::model()->findAll(array('order'=>'oauth_token'));
    return MyPlugin_TwitterAccountModel::populateModels($records);
}

Now your template will only have access to your plugin's model.
Having typed all of that, I literally have no idea if it will solve your original issue.  
It might be some odd bug with Twig's interactions with Records that you're the first to run into since we highly discourage exposing Records to templates.

> **Comments:**
> **username_0**: Thanks Brad that totally fixed the problem and I learned a good lesson on populating models from records. The template now works as I'd expected, so I think this is a freak bug in Twig but only instigated when there are pebkac issues... ;oD  

---

