Relacionamento entre Models, HtmlHelper e Finalização do CRUD - Introdução ao CakePHP
Veja nesse artigo a continuação a serie de artigos sobre a introdução no CakePHP . Nesse artigo vou falar um pouco sobre relacionamentos de Models, vamos finalizar o nosso CRUD e veremos um pouco do HtmlHelper.
Relacionamentos entre Models.
No final do artigo anterior deixei um relacionamento entre os models Autor e Receita assim como o seguinte.
Veja o post anterior nesse link Views, FormHelper e Actions - Introdução ao CakePHP.
Listagem 1: relacionamento entre Receita e Autor
public $hasOne = array(
'Autor' => array(
'className' => 'Autor',
)
);
A Listagem 1 não faz nada mais do que mapear o relacionamento que já existe no banco de dados.
Assim como, na modelagem, Receita tem um Autor devemos também indicar para o model que existe esse relacionamento.
O mapeamento dos relacionamentos nos permite economizar bastante código das consultas em SQL, também nos dá acesso a um objeto do model relacionado tanto dentro do próprio model ou de um controller que o mesmo pertença.
No Cake podemos mapear os seguintes tipos de relacionamentos:
1 para 1 | hasOne | Uma Receita tem um Autor |
1 para muitos | hasMany | Uma Receita tem muitos Autores |
Muitas para 1 | belongsTo | Muitas Receitas pertencem a um Autor |
Muitos para Muitas | hasAndBelongsToMany | Receita tem, e pertencem a muitos Autores. |
Um model pode conter mais de um relacionamento, do mesmo tipo ou não. Aqui, como sempre, estamos usando as normalizações do Cake, isso vai diminuir ainda mais a quantidade de escrita de código.
As configurações dos relacionamentos seguem o mesmo padrão para todos os tipos. Veja os exemplos:
Listagem 2: Relacionamento do tipo hasOne
<?php
class Usuario extends AppModel {
/*
O trecho de código abaixo está relacionando o model Usuario ao
model Perfil e com a condição do campo ativo do perfil seja igual a 1
*/
public $hasOne = array(
//Alias do relacionamento, geralmente usamos o nome do model
'Perfil' => array(
//nome do model a ser relacionado
'className' => 'Perfil',
//condições para a recuperação
'conditions' => array('Perfil.ativo' => '1'),
//quando setado para true e o metodo delete() é chamado com
//cascaded igual a true todas as dependências serão excluídas também
'dependent ' => false,
//Array com o nome dos campos que deve ser recuperados
'fields' => array('Perfil.nome','Perfil.ativo'),
//campo da chave estrangeira, por padrão esse campo deve ser o
//model mais _id
'foreignkey' => “perfil_id”,
//array com a ordem
'order' => array('Perfil.nome'=>'asc')
)
);
}
?>
Listagem 3: Relacionamento do tipo belongsTo
<?php
class Perfil extends AppModel {
/*
Relacionamento onde um perfil pertence a um usuario
*/
public $belongsTo = array(
'Usuario' => array(
'className' => 'Usuario',
//chave que representa o campo do outro model
'foreignKey' => 'usuario_id',
//tipo de join, left é o padrão
'type' => 'left'
)
);
}
As mesmas opções do relacionamento hasOne estão presentes no belongsTo acrescidas de type, counterCache, counterScope, essas duas ultimas não são interessantes para essa serie de introdução.
Vejamos agora os relacionamentos hasMany e hasAndBelongsToMany.
Listagem 4: Relacionamentos de tipo hasMany e hasAndBelongsToMany.
<?php
class Receita extends AppModel {
public $hasMany = array(
'Receita' => array(
'className' => 'Receita',
// limite de linhas que serão retornadas.
'limit' => '5',
)
);
public $hasAndBelongsToMany = array(
'Ingrediente' =>
array(
'className' => 'Ingrediente',
//tabela do relacionamento
'joinTable' => 'ingredientes_receitas',
'foreignKey' => 'receita_id',
//chave de associação
'associationForeignKey' => 'ingrediente_id',
)
);
}
?>
Nesses dois relacionamentos as opções são também praticamente as mesmas, na listagem 4 destaquei aquelas que na minha opinião são as mais importantes, as outras veremos nos próximos posts. E estivermos usando as normas “cakerianas” só precisaremos mudar alguma coisa aqui quando a regra de negócios exigir.
Agora vamos dar continuidade ao nosso CRUD.
Novas Actions para o CRUD
Nós já temos nosso cadastro pronto e acredito que vocês devem ter cadastrado algumas receitas. Vamos fazer agora uma função listagem e uma para deletar.
Voltemos ao nosso Controlador de Receita
Listagem 5: Action de listagem dos registros.
<?php
class ReceitaController extends AppController(){
/* outros métodos aqui em cima */
public function lista(){
/*
chamamos o métodos find('all') do model para retornar todos os registros
*/
$receitas = $this->Receita->find('all');
/*
enviamos a variável receitas para a view pelo metodo set do controller
*/
$this->set('receitas',$receitas);
}
}
?>
Na Listagem 5 fizemos uso do método find($type,$options) do model, desta vez com o tipo “all”, para recuperar todos os registros previamente cadastrados, depois usamos o método set($one,$two) para enviarmos para a view a variável $receitas.
Espera aí que agente já faz a view, vamos contruir nossa action para deletar aí agente já faz tudo de uma vez.
Listagem 6: Action para deletar
<?php
class ReceitaController extends AppController(){
/* outros métodos aqui em cima */
public function deletar($id = null){
/*
verificamos se o id é igual a null e caso ele seja chamamos
o método redirect do controller para redirecionar a requisição
junto com uma mensagem de aviso.
*/
if(!isset($id))
/*Uso do component Session, coisa de outros posts*/
$this->Session->setFlash('Erro!');
/*redireciona para a acton listar*/
$this->redirect->(“/receitas/listar”);
/*
Criamos um novo objeto do tipo receita Isso é necessário
aqui porquê vamos setar propriedades para o objeto manipular.
*/
$this->Receita->create();
/*setamos o id da receita*/
$this->Receita->id = $id
/*chamamos a função delete do model que retorna true ou false*/
if($this->Receita->delete())
/*Uso do component Session, coisa de outros posts*/
$this->Session->setFlash('Arquivo deletado!');
}else{
$this->Session->setFlash('Não foi possível deletar!');
}
/*redireciona para a acton listar*/
$this->redirect->(“/receitas/listar”);
}
?>
Note que a action delete termina com um redirecionamento, dessa forma ela nunca vai renderizar uma action própria, isso significa que não precisaremos criar uma view para essa action, o que é muito natural.
View da action listar.
Para essa view temos o array que enviamos da action, então faremos um foreach para varrermos o seu conteúdo, e para esse exemplo usaremos uma table HTML.
Listagem 7: View listar
<table>
<tr>
<th>id</th>
<th>titulo</th>
<th>texto</th>
<th>autor</th>
</tr>
<?php foreach($receitas as $receita){ ?>
<tr>
<td><?php echo $receita['Receita']['id'] ?></td>
<td><?php echo $receita['Receita']['title'] ?></td>
<td><?php echo $receita['Receita']['texto'] ?></td>
<td><?php echo $receita['Autor']['name'] ?></td>
</tr>
<?php } ?>
</table>
O padrão de arrays é o padrão do cake [Model][campo] dessa forma sempre temos uma forma intuitiva e organizada de recuperar os dados, todas as funções que recuperam dados retornam dessa forma.
Vamos implementar na listagem anterior um link para chamar na action delete, utilizando o HtmlHelper que já vem habilitado por padrão.
Listagem 7: implementação de link para a action delete
<table>
<tr>
<th>id</th>
<th>titulo</th>
<th>texto</th>
<th>autor</th>
<th>ação</th>
</tr>
<?php foreach($receitas as $receita){ ?>
<tr>
<td><?php echo $receita['Receita']['id'] ?></td>
<td><?php echo $receita['Receita']['title'] ?></td>
<td><?php echo $receita['Receita']['texto'] ?></td>
<td><?php echo $receita['Autor']['name'] ?></td>
<td><?php
/* Html:link($string,$url,$options), similar a uma tag <a></a>
A url pode ser passada como um array com o controlador, a action e as
variáveis que ficaram acessíveis como parametro ou uma string da
seguinte forma /controller/action/variavel
Vamos usar o array no exemplo
*/
echo
$this->Html->link('delelar',
array('controller'=>”receitas”,”action”=>”delete”,$receita['Receita']['id'])) ?>
</td>
</tr>
<?php } ?>
</table>
Bem pessoal por aqui terminamos nossa serie de introdução ao CakePHP. Tem muita coisa que ele faz que vai facilitar muito nossas vidas, mas o intuito desses posts foi o de deixar claro a divisão das camadas do Bolo(Cake) , das responsabilidade de cada uma delas.
Nos próximos posts daremos focos a coisas mais especificas do cotidiano do programador que quiser enveredar-se no mundo do CakePHP.
Forte abraço e até a próxima.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo