I am building a REST-full API, but I think that question may apply even if you are building web application.
Here I will give you very simplified example of my real code, that is enough to backup my answer.
I have DocumentController responsible for allowing access to documents endpoint.
This is my relevant code there:
/**
* Declares external actions for the controller.
*/
public function actions()
{
$actions = parent::actions();
// disable the "delete", "create" and update actions
unset($actions['delete'], $actions['create'], $actions['update']);
// for index action, customize the data provider preparation with the "prepareDataProvider()" method
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider()
{
/** @var $query ActiveQuery */
$query = Document::find()->limit(5)->orderBy(['document.id' => SORT_DESC]);
// execute query or serve it from cache
$result = Document::getDb()->cache(function () use ($query) {
return $query->all();
});
return $result;
}
And I have my models: Document and DocumentContent.
Here is the code of Document model:
public function fields()
{
$fields = parent::fields();
$fields[] = 'documentContent';
return $fields;
}
/**
* Relation with document_content table.
*
* @return DocumentContent
*/
public function getDocumentContent()
{
return $this->hasMany(DocumentContent::className(), ['document_id' => 'id']);
}
As you can see I am declaring in fields() method that I always want documentContent relation returned in output.
By the way, I do not like this approach but I didn’t knew how to return documentContent in JSON output if I execute some relational query manually, and do not write in fields() that I want that relation returned. it seems to me that if I do not declare relation in fields() I can not get it in JSON response, even if I made my mega object myself that has documentContent property inside.
And my DocumentContent model has just relation with Document.
/**
* Relation with document table.
*
* @return Document
*/
public function getDocument()
{
return $this->hasOne(Document::className(), ['id' => 'document_id']);
}
Because of these lines of code in my DocumentController, the query executed directly on document table will be cached and that is fine:
$result = Document::getDb()->cache(function () use ($query) {
return $query->all();
});
But because of my relation with documentContent, there will be X ( where X is a limit ) SELECT queries executed all the time. For example:
SELECT * FROM `document_content` WHERE `document_id`=2347715
My question is: how can I get these SELECT by ID queries cached ? It seems to me that Yii is executing them on its own, because of $fields[] = ‘documentContent’; and I do not know how to get in control of that.
For me, it would be perfect if I can execute all the queries myself, and still be able to see relations in output. If not, I would like to get these SELECT queries, executed by Yii, cached.
Any idea how to do this ?
EDIT: can any moderator please fix the title of this topic ? It is not "relataion" it is "relation", I made a type and cant fix it on my own.