I recently started learning plugin development for Craft CMS. I'm creating a plugin that deals with video content. For this example I'll use two models: MyPlugin_ChannelModel
and MyPlugin_VideoModel
. I've also setup two record classes that mirror the model's properties (MyPlugin_ChannelRecord
and MyPlugin_VideoRecord
).
The two record classes have a many to many relationship with each other. So, a channel can have multiple videos and a video can be in multiple channels.
I can create, delete and modify records. So far, so good. Now, this next part confuses me. I want to use these records in my templates. Ideally, I'd like to do something like:
{% for video in channel.videos %}
{{ video.someProperty }}
{% endfor %}
However, I think the "rule" is that only services can interact with records. Models should be used in all other parts of a plugin to pass data (like passing data from a service to a template).
Since models do not have the relationship properties, I've written some getter methods on those models to help me get to my channels/videos from the opposite end of the relationship. An example for MyPlugin_ChannelModel
:
public function getVideos()
{
if ($this->_videos === null && $this->id !== null)
{
// Helper method that gets the record for this model
$channelRecord = craft()->myPlugin_helpers->findRecordForModel($this);
// Convert each related record back to a model
$videoModels = array();
foreach ($channelRecord->videos as $videoRecord) {
$videoModel = new MyPlugin_VideoModel($videoRecord);
$videoModels[] = $videoModel;
}
$this->_videos = $videoModels;
}
return $this->_videos;
}
It's nice that these getter methods automatically map to their corresponding property names ($model->getVideos()
becomes model.videos
in Twig), but this means I have to write each of these helper methods by hand on all my model classes to get the related models. Am I missing something, is there an easier way?