How To Run Relations In Activerecord

There are two table:

tbl_project:

[sql]id: int, PK

name : varchar

description: varchar[/sql]

tbl_issue:

[sql]id: int, PK

name: varchar

description: varchar

project_id: int[/sql]

and relation between those:

[sql]ALTER TABLE ‘tbl_issue’ ADD CONSTRAINT ‘FK_issue_project’ FOREIGN KEY

(‘project_id’) REFERENCES ‘tbl_project’ (‘id’) ON DELETE CASCADE ON

UPDATE RESTRICT;[/sql]

For this 2 tables there are 2 models, one is Project and other is Issue.

The following is existing Relations at this 2 models:

Project:




public function relations()

{

return array(

'issues' => array(self::HAS_MANY, 'Issue', 'project_id'),

);

}

Issue:


public function relations()

{

return array(

'project' => array(self::BELONGS_TO, 'Project', 'project_id'),

);

}

There is this code for run:


$model = Issue::model()->findbypk(1);

My question is that when the above code is executed, the existing Relations in Issue model also to be run?

In total when we dont need to Relations, and we just have an intract with a single table, do to be run Relations?

You have mistake in this piece of code




//your code

$model = Issue::model()findbypk(1);

//must be

$model = Issue::model()->findbypk(1);



Answer to question:

Relations wouldn’t be use, if you wouldn’t call project fields (like $model->project->name)

Hi msoa

When use AR model, the findbypk or any other fetching execute gives you only the data of single table.

If you set relations into model, their load only when Invoke any AR relation like

Issue::model()->findbypk(1)->project (or anything same Issue::model()->findbypk(1)->project->name etc)

before of that nothing of related AR loads

And,

When ActiveRecord after the once executed, do the Relation for next queries uses the Results as offline? If this is true, what time the ActiveRecord invoke the fresh results?

up

If you call some column for projects from Issue model




echo Issue::model()->findbypk(1)->project->name;

//or

$model = Issue::model()->findbypk(1);

echo $model->project->name;



Active record just add "Join" relations to your MySQL query.

It isn’t save anything in SESSION, COOKIES, etc. And it will update project info together with issue info updating

Your mean is when called following command:


echo Issue::model()->findbypk(1)->project->name;

ActiveRecord first generate the following query and then send it to database?

[sql]

select tbl_project.name

from tbl_project RIGHT JOIN

tbl_issue on tbl_project.id = tbl_issue.project_id

where tbl_issue.id = 1;

[/sql]

or vice versa,

ActiveRecord first fetches all records of tbl_issue and tbl_project tables from database and then joins the Relation?

there is no idea?

Of course ActiveRecord add JOIN selection to your SQL query, because you don’t need fecth all records. You take 1 row from Issue, and join all relation records to from project for this Issue.

So when we call following command:


echo Issue::model()->findbypk(1)->project->name;

and again required same command:


echo Issue::model()->findbypk(1)->project->name;

ActiveRecord again send query to database? its better i say: what when activerecord use from cache?

Yes, ActiveRecord send query to database again. You must sing the variable

$model = Issue::model()->findbypk(1);

And than use it

echo $model->project->name;

and again

echo $model->project->name;

And ActiveRecord send only one query on this example.

Some times, you need call one model in different pieces of code (in sidebar and content block for example)

And you can’t send variable from sidebar to content, and conversely.

On this case you can use static variable in your Issue model file




Issue extends CActiveRecord

{

    protected static $_issue = array();

...

    public static function getIssueByPk($id)

    {

        if(!isset(self::$_issue[$id])){

            self::$_issue[$id] = self::model()->findbypk($id);

        }

        return self::$_issue[$id];

    }

...

}



Wherever you use this

$model = Issue::getIssueByPk($id);

echo $model->project->name;

It send sql query just one time.

Another approach is to use query caching.