Relacionamento de Estado e Município

Olá a todos,

Estou abrindo este tópico, por que os demais estão bloqueado.

Na tabela do Cliente tenho ID do Município.

Na tabela do Município tenho o ‘uf_ibge’ que guarda o ID da tabela Estado.

Na tabela Estado tenho o ‘uf_ibge’ como chave primária.

Cliente -> codmunicipio(FK)

Municipio -> codmunicipio(PK), uf_ibge(FK)

Estado -> uf_ibge(PK)

Meu relacionamento:




class Cliente extends CActiveRecord {

	return array(

		'municipio' => array(self::BELONGS_TO, 'Municipio', 'codmunicipio',

			'together' => true,

			'joinType' => 'INNER JOIN'

		),

		'estado' => array(self::HAS_ONE, 'Estado', array('uf_ibge' => 'uf_ibge'),

			'through' => 'municipio'

		),

	);

}



Consigo resultados como:


$model->municipio->municipio /*Descrição da cidade*/

e


$model->estado->uf /*Sigla da unidade federativa*/

Onde estou querendo chegar.




class Veiculo extends CActiveRecord {


    public function relations() {

        return array(

            'cliente' => array(self::BELONGS_TO, 'Cliente', 'codcliente',

                'together' => true,

                'joinType' => 'INNER JOIN'

            ),

        );

    }


}



Eu tenho um model Veiculo que tem uma ID referêncial com a tabela do Cliente, que é para identificar de quem é o Veiculo.

E nesta tabela Cliente que como descrito acima tem os relacionamento.

O máximo que consegui chegar foi:


$model = $this->loadModel();

echo $model->cliente->municipio->municipio /*Descrição da cidade*/

Não consigo mostrar os dados do relacionamento do estado.

Já tentei:


echo $model->cliente->estado->descricao;

echo $model->cliente->estado->uf;

print_r($model->cliente->estado); /*Retorna 1(true)*/

var_dump($model->cliente->estado); /*Retorna NULL*/

Tem alguma solução para que eu não use:


$model->cliente->municipio->estado->uf

Ou esse relacionamento pode me trazer pouca performance?

Newerton,

já tive os mesmos problemas com relacionamentos,

e talvez consiga te ajudar com alguma solução em relação ao relacionamento através do que já passei.

Primeiro vamos ver se compreendi o seu raciocínio,

experimente assim para a exibição dos dados atráves do relacionamento estado:




 print_r($model->cliente[0]->estado->uf);



Utilizei a base de que como existem vários clientes esta variavel pode ser um array.

Caso a exibição dos dados seja válida, continuamos o processo, senão tente colocar a estrutura das tabelas

em forma gráfica pra ver se ajuda.

Segue a ilustração.

Vamos lá, pelo que entendi:




$model = new Veiculos;



as relações a seguir veiculos>clientes>municipio>estado são todas HAS_ONE?

O ideal seria que as relações estivessem assim:




class Veiculo extends CActiveRecord {

    public function relations() {

        return array(

            'cliente' => array(self::HAS_ONE, 'Cliente', 'codcliente'), // Sentido Correto

        );

    }

}


class Cliente extends CActiveRecord {

    public function relations() {

        return array(

            'municipio' => array(self::HAS_ONE, 'Municipio', 'codmunicipio'), // Sentido Correto

			'veiculo' => array(self::BELONGS_TO, 'Veiculo', 'codveiculo'), // Sentido Contrario

        );

    }

}


class Municipio extends CActiveRecord {

    public function relations() {

        return array(

            'estado' => array(self::HAS_ONE, 'Estado', 'uf_ibge'), // Sentido Correto

			'cliente' => array(self::BELONGS_TO, 'Cliente', 'codcliente'), // Sentido Contrario

        );

    }

}


class Estado extends CActiveRecord {

    public function relations() {

        return array(

            'municipio' => array(self::BELONGS_TO, 'Municipio', 'codmunicipio'), // Sentido Contrario

        );

    }

}



Partindo da tabela pai e percorrendo as filhas. Depois que estiver funcionando de forma básica começamos a adicionar a relação direta $model->estado;

Hans,

As relations() está parecidas, porem eu uso o BELONGS_TO, se fosse usar de forma inversa, as vezes quando utilizo a forma inversa coloco HAS_ONE, em muitos casos em relatórios.

Como está atualmente:


$model = new Veiculo;




class Veiculo extends CActiveRecord {

    public function relations() {

        return array(

            'cliente' => array(self::BELONGS_TO, 'Cliente', 'codcliente'),

        );

    }

}






$model->cliente->codmunicipio; /*Retorna id do municipio*/






class Cliente extends CActiveRecord {

    public function relations() {

        return array(

            'municipio' => array(self::BELONGS_TO, 'Municipio', 'codmunicipio'),

        );

    }

}






$model->cliente->municipio->titulo; /*Retorna o titulo do municipio*/






class Municipio extends CActiveRecord {

    public function relations() {

        return array(

            'estado' => array(self::HAS_ONE, 'Estado', 'uf_ibge'),

        );

    }

}






$model->cliente->municipio->estado->uf; /*Retorna a unidade federativa*/



A class Estado não tem relacionamento, por que no momento não estou usando o inverso.

O que pensei em fazer, mais não funciono.




class Cliente extends CActiveRecord {

    public function relations() {

        return array(

            'municipio' => array(self::BELONGS_TO, 'Municipio', 'codmunicipio'),

            'estado' => array(self::HAS_ONE, 'Estado', array('uf_ibge' => 'uf_ibge'),

                'through' => '_municipio'

            ),

        );

    }

}



Pensando da forma de como o ‘through’ funciona, pensei que chamando assim:


$model->cliente->estado->uf;

funcionava.

O through serve para fazer uma relação direta com outro model atraves de um outro model intermediario.

Ou seja, o que você pensou está correto.

Por exemplo, se o desejado fosse:




 $model->estado->uf



As relações com through no model devem se manter no mesmo sentido, da seguinte forma:




class Veiculo extends CActiveRecord


...


'cliente' => array(self::HAS_ONE, 'Cliente', 'codcliente'), // Sentido Correto

'municipio'=>array(self::HAS_ONE,'Municipio',array('codmunicipio'=>'codmunicipio'),'through'=>'cliente'),

'estado'=>array(self::HAS_ONE,'Estado',array('uf_ibge'=>'uf_ibge'),'through'=>'municipio'),



Por isso para evitar qualquer problema, penso que é melhor você trabalhar no sentido HAS_ONE do que no BELONGS_TO.

Hans,

Funciono as 3 relação, somente no cliente tive que colocar assim:




'_cliente' => array(self::HAS_ONE, 'Cliente', array('codcliente' => 'codcliente')),



Por que não estava relacionando direito e não mostrava os dados.

Valeu ae, essas dos relacionamento eu manjo pouco, sabia mais o básico por causa da documentação, mais com o tempo vamos aprendendo.