StErMi
(Stermi)
May 17, 2009, 2:42pm
1
This is the scenario:
$ModelAObj = new ModelA;
$ModelAObj ->clienteId = $_GET['clienteId'];
Now, I've this in the ModelA model php file:
public function relations()
{
return array(
'cliente' => array( self::BELONGS_TO, 'Cliente', 'clienteId' ),
);
}
How can I raise the relation of this model object to have the Cliente object in $ModelAObj ->cliente ?
qiang
(Qiang Xue)
May 17, 2009, 10:41pm
2
$ModelAObj->clients should give you automatically the needed related object.
StErMi
(Stermi)
May 17, 2009, 10:57pm
3
really? Couse it seems to doesn't load the model object of the relation… I will take a test now…
Ok this is the real example:
AnagraficaTipologiaStrutturaServizio relation model:
<?php
public function relations()
{
return array(
'servizio' => array( self::BELONGS_TO, 'AnagraficaServizio', 'anagraficaServizioId' ),
);
}
actionListCreate function in the AnagraficaTipologiaStrutturaServizio Controller:
I know that $s->id is a real AnagraficaServizio id in the database.
<?php
public function actionListCreate()
{
$criteria = new CDbCriteria;
$servizi = AnagraficaServizio::model()->findAll($criteria);
$tipologieStrutturaServizi = array();
foreach ( $servizi as $k => $s ) {
$tipologieStrutturaServizi[$k] = new AnagraficaTipologiaStrutturaServizio;
$tipologieStrutturaServizi[$k]->anagraficaServizioId = $s->id;
}
$this->render('listCreate',array(
'anagraficatipologiastrutturaservizioList'=>$tipologieStrutturaServizi,
'update'=>false,
));
}
This is where i'm trying to use the $model->servizio->name_it in the listCreate.php view:
<?php foreach($anagraficatipologiastrutturaservizioList as $n => $model): ?>
<div class="simple">
<?php echo CHtml::activeLabelEx($model,'anagraficaServizioId'); ?>
<?php //echo CHtml::image($model->servizio->immagine); ?>
<?php //echo CHtml::activeLabelEx($model->servizio, 'nome_it'); ?>
<?php echo $model->servizio->nome_it ?>
<?php echo CHtml::activeTextField($model,"anagraficaServizioId[$n]"); ?>
</div>
<div class="simple">
<?php echo CHtml::activeLabelEx($model,'anagraficaTipologiaStrutturaId'); ?>
<?php echo CHtml::activeDropDownList($model,"anagraficaTipologiaStrutturaId[$n]", tipologieStruttura() ); ?>
</div>
<div class="simple">
<?php echo CHtml::activeLabelEx($model,'applicabilita'); ?>
<?php echo CHtml::activeDropDownList($model, "applicabilita[$n]", $model->applicabilitaOptions ); ?>
</div>
<?php endforeach; ?>
And this is the error reported:
Quote
Description
Trying to get property of non-object
Source File
/home/hoteltest/public_html/protected/views/anagraficaTipologiaStrutturaServizio/listCreate.php(39)
00039: <?php echo $model->servizio->nome_it ?>
StErMi
(Stermi)
May 18, 2009, 9:26am
4
These are some simple examples when it works and when not:
in the show view of the model it works well $model->servizio. I can access to all the attributes of the servizio model.
When I declare a new istance of the model
$model = new AnagraficaTipologiaStrutturaServizio;
$model->anagraficaServizioId = $service->id;
It wont load the relation between AnagraficaTipologiaStrutturaServizio and AnagraficaServizio.
Like I write before this is the relation defined in AnagraficaTipologiaStrutturaServizio model file:
<?php
public function relations()
{
return array(
'servizio' => array( self::BELONGS_TO, 'AnagraficaServizio', 'anagraficaServizioId' ),
);
}
Like I told before: is there a way to raise the relation method? Becouse I didn't find a way to load this relation when the record isn't loaded from the database…
StErMi
(Stermi)
May 18, 2009, 10:21am
5
<?php
$tipologieStrutturaServizi[$k] = new AnagraficaTipologiaStrutturaServizio;
$tipologieStrutturaServizi[$k]->anagraficaServizioId = $s->id;
this doesn't throw the relations() method couse If I try to access to $tipologieStrutturaServizi[$k]->servizio it tells:
La propietà "AnagraficaTipologiaStrutturaServizio"."servizio" non è definita.
But it's defined in the AnagraficaTipologiaStrutturaServizio model like this:
<?php
public function relations()
{
return array(
'servizio' => array( self::BELONGS_TO, 'AnagraficaServizio', 'anagraficaServizioId' ),
);
}
qiang
(Qiang Xue)
May 20, 2009, 12:32pm
7
This should work. Please turn on logging and see what the SQLs being executed.
Actually, it is bad practice to do this way because it would require an individual SQL execution for each object you are accessing.
Since you already have $servizi array, you only need a mapping from ID to the servizi objects.
StErMi
(Stermi)
May 20, 2009, 5:46pm
8
how can I turn it on? ( you mean yii log? how can I see it? I leave all debug config on default settings )
will
(Phpwindcn)
May 20, 2009, 6:37pm
9
StErMi
(Stermi)
May 21, 2009, 9:51am
10
I think that the lazy loading is only called when you call a findAll, findByPk and like this.
This my example:
if( !isset($_POST['StrutturaServizio']) ) {
$criteria = new CDbCriteria;
$criteria->join = 'LEFT JOIN "StrutturaServizio" ON "AnagraficaTipologiaStrutturaServizio"."id" = "StrutturaServizio"."anagraficaTipologiaStrutturaServizioId"';
$criteria->condition = '"StrutturaServizio".id IS NULL AND "anagraficaTipologiaStrutturaId"=:strutturaId AND ( applicabilita=:applicabilita OR applicabilita=:applicabilita1 )';
$criteria->condition = '"anagraficaTipologiaStrutturaId"=:strutturaId AND ( applicabilita=:applicabilita OR applicabilita=:applicabilita1 )';
$criteria->params = array (
':strutturaId' => $struttura->id,
':applicabilita' => 0,
':applicabilita1' => 1,
);
$criteria->select = '*, "AnagraficaTipologiaStrutturaServizio".id AS id';
$criteria->order = '"AnagraficaTipologiaStrutturaServizio".id';
//$criteria->order = 'id';
$anagraficaServizi = AnagraficaTipologiaStrutturaServizio::model()->findAll($criteria);
$serviziStruttura = array();
foreach ( $anagraficaServizi as $s ) {
$strutturaServizio = new StrutturaServizio;
$strutturaServizio->strutturaId = $struttura->id;
$strutturaServizio->anagraficaTipologiaStrutturaServizioId = $s->id;
$strutturaServizio->_tipologiaServizio = $s;
$strutturaServizio->tipoServizio = -1;
$serviziStruttura[] = $strutturaServizio;
}
}
This is the DB log:
Taking a look at the log the lazy loading is done only when I call
$anagraficaServizi = AnagraficaTipologiaStrutturaServizio::model()->findAll($criteria);
But it's not raised when I do:
$strutturaServizio->strutturaId = $struttura->id;
$strutturaServizio->anagraficaTipologiaStrutturaServizioId = $s->id;
On strutturaId and anagraficaTipologiaStrutturaServizioId for the StrutturaServizio are defined two relations like here:
public function relations()
{
return array(
'struttura' => array( self::BELONGS_TO, 'Struttura', 'strutturaId' ),
'tipologiaServizio' => array( self::BELONGS_TO, 'TipologiaStrutturaServizio', 'tipologiaStrutturaServizioId' ),
);
}
So my conclusion is: Yii doesn't raise the lazy loading when I put some value on a model attribute where a relation is defined.
Is it normal? Can I do something? Is it a bug? What could I do?
qiang
(Qiang Xue)
May 21, 2009, 12:41pm
11
Quote
This should work. Please turn on logging and see what the SQLs being executed.
Actually, it is bad practice to do this way because it would require an individual SQL execution for each object you are accessing.
Since you already have $servizi array, you only need a mapping from ID to the servizi objects.
From your log messages, you did have a lot of lazy loading. Please follow my advice above.
StErMi
(Stermi)
May 21, 2009, 12:47pm
12
Like I explained that lazy loading are raised from $anagraficaServizi = AnagraficaTipologiaStrutturaServizio::model()->findAll($criteria);
and not from $strutturaServizio->anagraficaTipologiaStrutturaServizioId = $s->id;
qiang
(Qiang Xue)
May 21, 2009, 12:52pm
13
You misunderstood lazy loading. It is impossible $anagraficaServizi = AnagraficaTipologiaStrutturaServizio::model()->findAll($criteria); would raise lazy loading.
Lazy loading is defined to be that when you access $object->relatedObject for the first time, it will execute a SQL to fetch the relatedObject.
StErMi
(Stermi)
May 21, 2009, 2:34pm
14
I will do some tests after I finish to study
Damn it
StErMi
(Stermi)
May 21, 2009, 5:40pm
15
You were right, not it's trying to do the lazy loading.
The problem is when I try to use that object to print some of it's attributes the php thorw an error saying: Trying to get property of non-object
qiang
(Qiang Xue)
May 21, 2009, 5:46pm
16
Try executing a "lazy loading" SQL manually using your DB client and see what the result it? The error means you don't have a related object.