Answers.Body: <p>I was able to figure almost all of this stuff out by diving through the code. The only exception is triggering the <code>find()</code> method automatically.</p>
  
  <p>The key here was to follow the code in the <code>ElementCriteriaModel</code>. First thing I did was create a method in the <code>MyPluginService</code> class to fetch the data.</p>
  
  <pre><code>public function foo($criteria = false)
  {
      return new MyPlugin_MyCriteriaModel($criteria ?: array());
  }
  </code></pre>
  
  <p>I added a wrapper to my <code>MyPluginVariable</code> class.</p>
  
  <pre><code>public function parcels($criteria = array())
  {
      return craft()-&gt;myPlugin-&gt;foo($criteria);
  }
  </code></pre>
  
  <p>This will allow for the following syntax:</p>
  
  <pre><code>{% set data = craft.myPlugin.foo().limit(5).offset(1).find() %}
  </code></pre>
  
  <p>You must define a <code>find()</code> method in your <code>MyPlugin_MyCriteriaModel</code> class that will perform the SQL query to actually fetch your data. You also have to loop through the results set and instantiate <code>MyPlugin_FooModel</code> for each db row if you want to return a <code>Model</code> to the template instead of a <code>stdObject</code> or array.</p>
  
  <p>For example, my find method looks like this:</p>
  
  <pre><code>public function find($attributes = null)
  {   
      $this-&gt;setAttributes($attributes);
  
      if (!isset($this-&gt;_matchedObjects))
      {
          $objects = craft()-&gt;myplugin_foo-&gt;find($this);
  
          $this-&gt;setMatchedObjects($objects);
      }
  
      return $this-&gt;_matchedObjects;
  }
  </code></pre>
  
  <p>Then in <code>MyPlugin_FooService</code> I have this:</p>
  
  <pre><code>public function query(MyPlugin_MyCriteriaModel $criteria)
  {
      $record = new MyPlugin_FooRecord();
  
      $query = craft()-&gt;db-&gt;createCommand()
          -&gt;select('*')
          -&gt;from($record-&gt;getTableName())
          -&gt;limit($criteria-&gt;limit)
          -&gt;offset($criteria-&gt;offset)
          -&gt;order($criteria-&gt;order);
  
      if($criteria-&gt;id)
      {
          $query-&gt;where('id = :id', array(':id' =&gt; $criteria-&gt;id));
      }
  
      if($criteria-&gt;uid)
      {
          $query-&gt;where('uid = :uid', array(':uid' =&gt; $criteria-&gt;uid));
      }
  
      // More conditionals may go here
  
      return $query;
  }
  
  public function find(MyPlugin_MyCriteriaModel $criteria)
  {
      $query = $this-&gt;query($criteria);
  
      return $this-&gt;_populateModelsFromArray($query-&gt;queryAll());
  }
  
  protected function _populateModelsFromArray(Array $array)
  {
      $models = array();
  
      foreach($array as $row)
      {
          $models[] = MyPlugin_FooModel::populateModel($row);
      }
  
      return $models;
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-09T06:24:10.617Z
Answers.Text: what does your MyPluginVariable class look like with the wrapper function?
Answers.UserDisplayName: a-am
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-09T17:19:59.833Z
Answers.Text: also are you extending ElementCriteriaModel in MyPlugin_MyCriteriaModel?
Answers.UserDisplayName: a-am
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-09T19:38:15.447Z
Answers.Text: `MyPlugin_MyCriteriaModel` is a class that extends `BaseModel`. It's just a regular model with some arbitrary attributes. I did base the logic off `ElementCriteriaModel`, but it does not extend it. The `MyPluginVariable` wrapping method looks like this: `public function parcels($criteria = array()) { return craft()->postmaster->parcels($criteria); }`
Answers.UserDisplayName: Justin Kimbrell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-09T19:42:10.460Z
Answers.Text: so where your calling foo above, for your plugin your calling parcels?
Answers.UserDisplayName: a-am
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-09T19:47:46.067Z
Answers.Text: That's right. The logic is kinda confusing. You use the variables to call the criteria model, which returns a "chainable" object. Then the `find` method in the criteria model sends the model to the `ParcelService` instance, which actually runs the query.
Answers.UserDisplayName: Justin Kimbrell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-01-09T19:49:02.937Z
Answers.Text: Feel free to download Postmaster to see the complete code I am referencing. https://github.com/objectivehtml/Postmaster-for-Craft-CMS
Answers.UserDisplayName: Justin Kimbrell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-12-10T18:49:23.587Z
Answers.LastActivityDate: 2014-12-10T18:49:23.587Z
Answers.UserDisplayName: Justin Kimbrell
Body: <p>My main issue is perhaps not totally understanding the unique idioms of Yii, but I need to output data from my custom data tables in a template. So obviously I have a <code>MyPluginVariables</code> class and a <code>MyPluginService</code> to handle to actual business logic.</p>
  
  <p>Using my <code>MyPlugin_FooRecord</code> I can use ActiveRecord to fetch some data. But this obviously returns the actual record objects, when I really just need a model passed to the template. From what I understand, I should use models not the records themselves. Is this correct?</p>
  
  <p>Also, how exactly should I build a chainable syntax, similar to fetching entries in a template?</p>
  
  <p>For example, I am trying to get this to work:</p>
  
  <pre><code>{% set rows = craft.myPlugin.someMethod().limit(10).order('some_col').sort('asc') %}
  </code></pre>
  
  <p>So relating this syntax back to my original question, how would I build this and return an array of models? The <code>ElementCriteriaModel</code> will automatically execute the <code>find()</code> method when it's used an array, should I just overriding the <code>__toArray()</code> method?</p>
  
  <p>I have been searching and looking through the docs, so perhaps I missed something. I have also been looking through the code in Craft, but due to the abstractions and not being familiar with Yii core classes, I am getting a little lost in figuring out how this works.</p>
  
Tags: <plugin-development>
Title: What is the proper way to fetch items from a custom db table and output them in twig?
ThreadText: # What is the proper way to fetch items from a custom db table and output them in twig?
  
  (Asked by: username_0 on 2014-12-06)
  
  My main issue is perhaps not totally understanding the unique idioms of Yii, but I need to output data from my custom data tables in a template. So obviously I have a `MyPluginVariables` class and a `MyPluginService` to handle to actual business logic.
  
  Using my `MyPlugin_FooRecord` I can use ActiveRecord to fetch some data. But this obviously returns the actual record objects, when I really just need a model passed to the template. From what I understand, I should use models not the records themselves. Is this correct?
  
  Also, how exactly should I build a chainable syntax, similar to fetching entries in a template?
  
  For example, I am trying to get this to work:
  
  ```
  {% set rows = craft.myPlugin.someMethod().limit(10).order('some_col').sort('asc') %}
  
  ```
  
  So relating this syntax back to my original question, how would I build this and return an array of models? The `ElementCriteriaModel` will automatically execute the `find()` method when it's used an array, should I just overriding the `__toArray()` method?
  
  I have been searching and looking through the docs, so perhaps I missed something. I have also been looking through the code in Craft, but due to the abstractions and not being familiar with Yii core classes, I am getting a little lost in figuring out how this works.
  
  **Tags:** plugin-development
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2014-12-10. Score: 4 | Accepted answer
  
  I was able to figure almost all of this stuff out by diving through the code. The only exception is triggering the `find()` method automatically.
  
  The key here was to follow the code in the `ElementCriteriaModel`. First thing I did was create a method in the `MyPluginService` class to fetch the data.
  
  ```
  public function foo($criteria = false)
  {
      return new MyPlugin_MyCriteriaModel($criteria ?: array());
  }
  
  ```
  
  I added a wrapper to my `MyPluginVariable` class.
  
  ```
  public function parcels($criteria = array())
  {
      return craft()->myPlugin->foo($criteria);
  }
  
  ```
  
  This will allow for the following syntax:
  
  ```
  {% set data = craft.myPlugin.foo().limit(5).offset(1).find() %}
  
  ```
  
  You must define a `find()` method in your `MyPlugin_MyCriteriaModel` class that will perform the SQL query to actually fetch your data. You also have to loop through the results set and instantiate `MyPlugin_FooModel` for each db row if you want to return a `Model` to the template instead of a `stdObject` or array.
  
  For example, my find method looks like this:
  
  ```
  public function find($attributes = null)
  {   
      $this->setAttributes($attributes);
  
      if (!isset($this->_matchedObjects))
      {
          $objects = craft()->myplugin_foo->find($this);
  
          $this->setMatchedObjects($objects);
      }
  
      return $this->_matchedObjects;
  }
  
  ```
  
  Then in `MyPlugin_FooService` I have this:
  
  ```
  public function query(MyPlugin_MyCriteriaModel $criteria)
  {
      $record = new MyPlugin_FooRecord();
  
      $query = craft()->db->createCommand()
          ->select('*')
          ->from($record->getTableName())
          ->limit($criteria->limit)
          ->offset($criteria->offset)
          ->order($criteria->order);
  
      if($criteria->id)
      {
          $query->where('id = :id', array(':id' => $criteria->id));
      }
  
      if($criteria->uid)
      {
          $query->where('uid = :uid', array(':uid' => $criteria->uid));
      }
  
      // More conditionals may go here
  
      return $query;
  }
  
  public function find(MyPlugin_MyCriteriaModel $criteria)
  {
      $query = $this->query($criteria);
  
      return $this->_populateModelsFromArray($query->queryAll());
  }
  
  protected function _populateModelsFromArray(Array $array)
  {
      $models = array();
  
      foreach($array as $row)
      {
          $models[] = MyPlugin_FooModel::populateModel($row);
      }
  
      return $models;
  }
  
  ```
  
  > **Comments:**
  > **username_1**: what does your MyPluginVariable class look like with the wrapper function?  
  > **username_1**: also are you extending ElementCriteriaModel in MyPlugin_MyCriteriaModel?  
  > **username_0**: `MyPlugin_MyCriteriaModel` is a class that extends `BaseModel`. It's just a regular model with some arbitrary attributes. I did base the logic off `ElementCriteriaModel`, but it does not extend it. The `MyPluginVariable` wrapping method looks like this: `public function parcels($criteria = array()) { return craft()->postmaster->parcels($criteria); }`  
  > **username_1**: so where your calling foo above, for your plugin your calling parcels?  
  > **username_0**: That's right. The logic is kinda confusing. You use the variables to call the criteria model, which returns a "chainable" object. Then the `find` method in the criteria model sends the model to the `ParcelService` instance, which actually runs the query.  
  > **username_0**: Feel free to download Postmaster to see the complete code I am referencing. https://github.com/objectivehtml/Postmaster-for-Craft-CMS  
  
  ---
  
  