CRUD de duas Tabelas Um formulário, Um controller, dois Models, p/ unir dados de 2 tabelas
#1
Posted 21 January 2011 - 02:17 PM
CREATE TABLE IF NOT EXISTS `pessoa` (
`idpessoa` int(11) NOT NULL AUTO_INCREMENT,
`nome` varchar(45) NOT NULL,
`idtipopessoa` int(11) NOT NULL,
PRIMARY KEY (`idpessoa`)
)
CREATE TABLE IF NOT EXISTS `email` (
`idemail` int(11) NOT NULL AUTO_INCREMENT,
`idpessoa` int(11) NOT NULL,
`email` varchar(100) NOT NULL,
PRIMARY KEY (`idemail`),
KEY `idpessoa` (`idpessoa`)
)
ALTER TABLE `email`
ADD CONSTRAINT `email_ibfk_1` FOREIGN KEY (`idpessoa`) REFERENCES `pessoa` (`idpessoa`) ON DELETE NO ACTION ON UPDATE NO ACTION;
Preciso criar um CRUD para esta estrutura, mas preciso que os campos da tabela pessoa e e-mail estejam juntos no mesmo form. Ou seja, na tela de cadastro (insert ou update) o usuário precisa ver os seguintes campos no formulário: Nome, Tipo de pessoa (que pega de um dropdown de outra tabela, mas que já esta ok) e e-mail (que esta na tabela de nome 'email').
Alguém sabe como posso fazer isso e pode me ajudar? Obrigado.
#2
Posted 21 January 2011 - 04:16 PM
//nas relations no seu segundo model return array( 'pessoa'=>array(self::BELONG_TO, 'Pessoa', 'idpessoa'), ); //nas relations do primeiro model return array( 'email'=>array(self::HAS_ONE, 'Email', 'idpessoa'), );
ae pra usar faça algo como o seguinte:
$pessoal_model->email->email; //ou $email_model->pessoa->nome;
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#3
Posted 21 January 2011 - 08:36 PM
Gustavo, on 21 January 2011 - 04:16 PM, said:
//nas relations no seu segundo model return array( 'pessoa'=>array(self::BELONG_TO, 'Pessoa, 'idpessoa'), ); //nas relations do primeiro model return array( 'email'=>array(self::HAS_ONE, 'Email', 'idpessoa'), );
ae pra usar faça algo como o seguinte:
$pessoal_model->email->email; //ou $email_model->pessoa->nome;
E ao gerar o crud pelo Gii ou Console o form vai aparecer com todos os campos? Não terei que fazer nada na View e nem no Controller?
#4
Posted 21 January 2011 - 09:45 PM
O codigo que passei estabelece relação estre as duas tabelas, assim na hora que você usar as variaveis definidas em relations(), essa variavel vai conter os dados gerados pelo relacionamento que passei no codigo acima
De uma olhada no manual de relacionamentos para maiores explicações
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#5
Posted 23 January 2011 - 08:08 AM
http://www.yiiframew...7093#entry77093
com ajuda dele consegui resolver com relação ao Insert, mas já com relação ao Update não tive sucesso ainda.
Alguém pode me dar uma dica?
Acredito que o problema esteja no controller, vejam como penso em fazer
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$usuario = new Usuario;
$email = new Email;
$telefone = new Telefone;
//$usuario = Usuario::model()->find(array('idpessoa'=>$id));
//$email = Email::model()->find(array('idpessoa'=>$id));
//$telefone = Telefone::model()->find(array('idpessoa'=>$id));
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation(array($model,$usuario,$email,$telefone));
if(isset($_POST['Pessoa']))
{
$model->attributes=$_POST['Pessoa'];
$model->save();
}
if (isset($_POST['Usuario']))
{
$usuario->attributes=$_POST['Usuario'];
$usuario->save();
}
if (isset($_POST['Email']))
{
$email->attributes=$_POST['Email'];
$email->save();
}
if (isset($_POST['Telefone']))
{
$telefone->attributes=$_POST['Telefone'];
$telefone->save();
}
if( isset($_POST['Pessoa']) || isset($_POST['Usuario']) || isset($_POST['Email']) || isset($_POST['Telefone']))
{
$this->redirect(array('view','id'=>$model->idpessoa));
}
$this->render('update',array(
'model'=>$model,
'usuario'=>$usuario,
'email'=>$email,
'telefone'=>$telefone,
));
}
Acredito que tenha que popular o objeto de cada tabela conforme tentei fazer lá no inicio do código, mas acredito que daquela forma esta errado.
Para a tabela principal ele utiliza a linha abaixo para popular o model principal.
$model=$this->loadModel($id);
Nas linhas comentadas tentei popular os outros models, mas não sei se esta certo.
Alguém pode me ajudar?
#6
Posted 23 January 2011 - 08:16 AM
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#7
Posted 23 January 2011 - 08:31 AM
public function actionCreate()
{
$model = new Pessoa;
$usuario = new Usuario;
$email = new Email;
$telefone = new Telefone;
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation(array($model,$usuario,$email,$telefone));
if( isset($_POST['Pessoa']) && isset($_POST['Usuario']) && isset($_POST['Email']) && isset($_POST['Telefone']))
{
$model->attributes=$_POST['Pessoa'];
$usuario->attributes=$_POST['Usuario'];
$email->attributes=$_POST['Email'];
$telefone->attributes=$_POST['Telefone'];
if ($model->validate())
{
$model->save();
}
if ($usuario->validate())
{
$usuario->idpessoa = $model->idpessoa;
$usuario->senha = md5($usuario->senha);
//$usuario->status = '1';
$usuario->save();
}
if ($email->validate())
{
$email->idpessoa = $model->idpessoa;
$email->save();
}
if ($telefone->validate())
{
$telefone->idpessoa = $model->idpessoa;
$telefone->save();
}
if ($model->validate() && $usuario->validate() && $email->validate() && $telefone->validate())
{
$this->redirect(array('view','id'=>$model->idpessoa));
}
}
$this->render('create',array(
'model'=>$model,
'usuario'=>$usuario,
'email'=>$email,
'telefone'=>$telefone,
));
}
Esta parte esta funcionando perfeitamente, estou com dificuldade para fazer é o Update, se alguém tiver algum artigo que me ajude ou souber de algum topico que faça algo parecido vai ajudar demais.
O meu 'actionUpdate' esta assim:
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$usuario = new Usuario;
$email = new Email;
$telefone = new Telefone;
//$usuario = Usuario::model()->find(array('idpessoa'=>$id));
//$email = Email::model()->find(array('idpessoa'=>$id));
//$telefone = Telefone::model()->find(array('idpessoa'=>$id));
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation(array($model,$usuario,$email,$telefone));
if(isset($_POST['Pessoa']))
{
$model->attributes=$_POST['Pessoa'];
$model->save();
}
if (isset($_POST['Usuario']))
{
$usuario->attributes=$_POST['Usuario'];
$usuario->save();
}
if (isset($_POST['Email']))
{
$email->attributes=$_POST['Email'];
$email->save();
}
if (isset($_POST['Telefone']))
{
$telefone->attributes=$_POST['Telefone'];
$telefone->save();
}
if( isset($_POST['Pessoa']) || isset($_POST['Usuario']) || isset($_POST['Email']) || isset($_POST['Telefone']))
{
$this->redirect(array('view','id'=>$model->idpessoa));
}
$this->render('update',array(
'model'=>$model,
'usuario'=>$usuario,
'email'=>$email,
'telefone'=>$telefone,
));
}
O meu problema acredito estar neste trecho:
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$usuario = new Usuario;
$email = new Email;
$telefone = new Telefone;
//$usuario = Usuario::model()->find(array('idpessoa'=>$id));
//$email = Email::model()->find(array('idpessoa'=>$id));
//$telefone = Telefone::model()->find(array('idpessoa'=>$id));
Preciso carregar o $usuario,$email e $telefone da mesma forma que foi carregado o $model na linha:
$model=$this->loadModel($id);
#8
Posted 23 January 2011 - 08:43 AM
Tambem me mostra a função loadModel
tambem seria uma boa fazer uma validação antes de redirecionar, algo como :
$valid=true;
em cada if algo como
$valid = $model->save() && $valid;
dae no final se valid for true é pq deu tudo certo, se for false deu algum erro no caminho
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#9
Posted 23 January 2011 - 11:52 AM
Gustavo, on 23 January 2011 - 08:43 AM, said:
Tambem me mostra a função loadModel
tambem seria uma boa fazer uma validação antes de redirecionar, algo como :
$valid=true;
em cada if algo como
$valid = $model->save() && $valid;
dae no final se valid for true é pq deu tudo certo, se for false deu algum erro no caminho
Bom, na verdade o $id esta retornando o valor correto sim, no formulário os unicos campos que são resgatados também são os relacionados ao $model, já os campos relacionados a $usuario,$email e $telefone vem em branco.
Ao editar todos os campos os unicos que alteram são os relacionados ao $model também.
Esta questão da validação realmente é importante, obrigado por ter lembrado, eu ia sem dúvidas me esquecer disso.
esta função loadModel foi criada pelo próprio Yii, acho que ela serve para carregar nos inputs os valores de cada campo a partir da busca do id, mas não tenho certeza, vou procurar sobre ela e colocar aqui.
#10
Posted 23 January 2011 - 12:40 PM
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$email = new Email;
$telefone = new Telefone;
$usuario = new Usuario;
$email = Email::model()->find(array('condition'=>'idpessoa=:idpessoa','params'=>array(':idpessoa'=>$id)));
$telefone = Telefone::model()->find(array('condition'=>'idpessoa=:idpessoa','params'=>array(':idpessoa'=>$id)));
$usuario = Usuario::model()->find(array('condition'=>'idpessoa=:idpessoa','params'=>array(':idpessoa'=>$id)));
Apenas um campo não esta preenchido conforme recuperação no banco, é o campo da Cidade, mas deve ser pq fiz um dropdown dinamico que muda as cidades de acordo com a escolha do estado. Como estado não tem valor do banco preciso achar uma forma de fazer o dropdown dinâmico funcionar de forma reversa.
#11
Posted 23 January 2011 - 12:56 PM
Depois que fiz isso resolveu o problema.
Agora o único problema é para fazer resgatar o campo da cidade no Dropdown que fiz dinâmico, você ou alguém pode me dar um caminho para fazer com que a cidade cadastrada no banco apareça no update?
#12
Posted 23 January 2011 - 08:46 PM
echo CHtml::dropDownList('estado_id','', CHtml::listData(Estados::model()->findAll()),
array(
'ajax' => array(
'type'=>'POST', //request type
'url'=>CController::createUrl('controller/getcidades'), //url de pegar cidades.
'replace'=>'#cidade_id', //onde colocar o resultado
//poderia ser 'update' ao inves de replace, ae você só retornaria os options nao todo o select
)
);
echo CHtml::dropDownList('cidade_id','', array());e então faça uma action, algo como :
public function actionGetcidades()
{
$model=Cidades::model();
$data=$model->findAll('estado_id=:estado_id',array(':estado_id'=>(int) $_POST['estado_id']));
echo CHtml::activeDropDownList($model,'cidade_id',CHtml::listData($data,'cidade_id','cidade_name'));
}
acredito que esta tudo certo apesar de ter escrito aqui no editor mesmo
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#13
Posted 24 January 2011 - 02:37 PM
#14
Posted 24 January 2011 - 08:09 PM
_form
<?php
$estado = Estado::model()->findAllEstado();
echo CHtml::dropDownList('estado','', $estado,
array(
'empty' => 'Selecione um estado',
'ajax' => array(
'type'=>'POST',
'url'=>CController::createUrl('pessoa/dynamiccities'),
'update'=>'#idcidade', //Quando coloco replace ele mostra corretamente os campos só que saindo de dentro do dropdown.
)));
?>
<?php echo CHtml::dropDownList('idcidade','', array(), array('empty' => 'Selecione uma cidade')); ?>
action dentro do controller
public function actionDynamiccities()
{
$idestado = $_POST['estado'];
$data=Cidade::model()->findPorEstado($idestado);
foreach($data as $value=>$name)
{
echo CHtml::tag('option',
array('value'=>$value),CHtml::encode($name),true);
}
}
função findPorEstado que esta dentro do model Cidade
public function findPorEstado($idestado)
{
//format models resulting using listData
return $list = CHtml::listData($models = Cidade::model()->findAll(
array(
'condition'=>'idestado=:idestado',
'params'=>array(':idestado'=>$idestado),
)), 'idcidade', 'nom_cidade');
} //Fiz esta função só pq como vou ter que usar-la em varios lugares fica mais facil chamar-la.
Este é meu código do Dropdown, ele esta funcionando corretamente, mas sempre quando abro a tela de update ele aparece zerado, como se o usuário não tivesse informado nada, o que preciso é fazer com que os campos estado e cidade dos dropdowns já estejam preenchidos com o que o usuário salvou no banco, e o detalhe é que só sei o id da cidade, ou seja, só o id da cidade que esta no banco, mas na tabela de cidades eu tenho o campo idestado para saber de qual estado é cada cidade.
Penso que preciso recuberar este valor de idcidade, por ele achar o idestado da cidade que o usuário é, marcar no dropdown o estado que encontramos, e pegar também a cidade e marcar-la.
#15
Posted 25 January 2011 - 12:00 PM
//model
function relations(){
return array(
'estado'=>array(self::BELONGS_TO,'Estado','estadoid');
);
}
//pra usar
$cidade=Cidade::model()->findByPk(1);
$cidade->estado->nome;//nome do estado
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#17
Posted 25 January 2011 - 08:40 PM
function getCidade(){
return $this->_model->idcidade;
}
/e pra buscar
Yii::app()->user->cidade
/ou
Yii::app()->user->getCidade();
depois use relações como falei acima pra buscar o estado
$cidadeId=Yii::app()->user->cidade; $cidade=Cidades::model()->findByPk($cidadeId); $estado=$cidade->estado->id;
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#18
Posted 25 January 2011 - 09:02 PM
#19
Posted 26 January 2011 - 07:45 AM
$form->dropDownList(
$model,'cidade',$data,
array(
array('options'=>array(
Yii::app()->user->cidade=>array('selected'=>'selected')
)
)
);
deve funcionar
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#20
Posted 26 January 2011 - 01:22 PM

Help














