How to raise the relation join?

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 ?

$ModelAObj->clients should give you automatically the needed related object.

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 ?>

These are some simple examples when it works and when not:

  1. in the show view of the model it works well $model->servizio. I can access to all the attributes of the servizio model.

  2. 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…



<?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' ),


      );


   }


up

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.

how can I turn it on? ( you mean yii log? how can I see it? I leave all debug config on default settings )

check  this http://www.yiiframew…8.html#msg10468

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:

Posted Image

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?

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.

Like I explained that lazy loading are raised from $anagraficaServizi = AnagraficaTipologiaStrutturaServizio::model()->findAll($criteria);

and not from $strutturaServizio->anagraficaTipologiaStrutturaServizioId = $s->id;

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.

I will do some tests after I finish to study :D

Damn it :D

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

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.