SlideShare una empresa de Scribd logo
1 de 31
Descargar para leer sin conexión
INTRODUÇÃO AO
FRAMEWORK YII2
CLEIANE GONÇALVES OLIVEIRA
RODRIGO MARQUES CAMPOS
GUILHERME LUIS VIANA ALVES
X SIMPÓSIO DE INFORMÁTICA
Este material foi construído para o minicurso de Introdução ao Framework Yii2 ministrado no X
Simpósio de Informática do IFNMG - Campus Januária (novembro - 2018). Tem como objetivo divulgar o
framework YII2 para colaborar no desenvolvimento de software em qualquer contexto. O texto apresentado
a seguir propõe a construção de um sistema de gerenciamento de clinica genérica. Mesmo o texto
seguindo uma linha de raciocínio é possível usar o sumário para obter informações específicas sobre o
framework.
Espera-se que o leitor possua conhecimentos sobre a
linguagem PHP, o sistema gerenciador de banco de dados
MySQL e padrão de projeto MVC. Buscou-se utilizar
linguagem mais simples possível, fugindo de alguns
termos técnicos. O aprofundamento fica para o leitor
executar conforme sua necessidade.
1
1. Conhecimentos prévios
Para o bom entendimento dos passos descritos neste documento é interessante que o leitor possua
conhecimento nos tópicos abaixo:
● Linguagem PHP (conceitos como namespace);
● Orientação a objetos;
● Padrão MVC;
● Projeto de Banco de dados;
● SQL;
● Xampp (ou similar).
2. Proposta de software
Para o aprendizado do framework Yii2, propomos o desenvolvimento de um software simples de
gerenciamento de consultas de uma clínica médica. O diagrama de banco de dados que será
implementado é o apresentado na figura 1:
Figura 1: Diagrama Entidade e Relacionamento para o sistema Clínica
3. Ferramentas necessárias
As ferramentas necessárias são as mesmas para o desenvolvimento de qualquer sistema na
linguagem PHP:
● Ambiente de desenvolvimento: pode ser desde um editor de texto simples, com mais
recursos como o ​Visual Studio Code​, ou uma IDE robusta como o ​NetBeans​;
● Servidor PHP. Utilizamos integradores para facilitar a instalação. Nos nossos exemplos
utilizamos a ferramenta ​XAMPP na versão 7.2.7. Assim como vários outros, essa ferramenta
instala o servidor Apache e também o sgbd MySQL.
● Um SGBD. Nos nossos exemplos utilizamos o MySQL que já é instalado pelo XAMPP.
Recomendamos a utilização de uma interface para o gerenciamento da base de dados. O
XAMPP já instala o PhpMyAdmin. Sugerimos também a utilização do​ MySQL Workbench​.
Os exemplos deste texto foram executados no sistema operacional Windows. As únicas diferenças
em relação ao sistema operacional Linux serão na instalação do framework e permissão dos arquivos. Os
demais códigos serão independentes de sistema operacional.
2
4. Principais referências sobre o framework
Para a construção deste texto foram utilizadas várias referências entre livros, sites, canais do
YouTube e fóruns. Abaixo listamos os principais e buscamos, em cada subseção, indicar de onde foi tirado
aquele conteúdo.
● Livros:
○ Yii2 By Example:
https://www.amazon.com/Yii2-Example-Fabrizio-Caldarelli/dp/1785287419
● Sites:
○ Referência do framework Yii2: ​https://www.yiiframework.com
○ Yii academy: ​http://www.yiiacademy.com.br/
● Canais do YouTube:
○ DoingITeasyChannel: 
https://www.youtube.com/watch?v=z1xtFbO9jgQ&list=PLRd0zhQj3CBmusDbBzFgg3H20
VxLx2mkF  
○ William Martins: ​https://www.youtube.com/watch?v=WvvrnKaNcas
● E-book:
○ 8 motivos para usar o Yii 2:
http://www.yiiacademy.com.br/8-motivos-para-usar-o-yii-2/
5. Instalação do Yii2
A instalação do Yii2 pode ser realizada de duas formas: via composer ou manualmente.
5.1 Instalação via composer
É recomendado que a instalação seja realizada via ferramenta composer. O composer é um
gerenciador de dependências do php que facilita a instalação de vários outros componentes e módulos nos
projetos a serem construídos.
5.1.1 Instalando o composer
Para instalar o composer acesse o link
https://www.yiiframework.com/doc/guide/2.0/en/start-installation#installing-via-composer​. Baixe a
instalação para windows e a execute.
A figura 2 é a tela inicial do instalador. Basta selecionar next em todas as opções que o composer
será instalado com sucesso.
3
Figura 2 - Tela inicial da instalação do composer.
5.1.2 Instalando o Yii2 via composer
O Yii2 possui dois templates: o basic e o advanced. Trabalharemos com a opção basic.
Abra o prompt de comando do Windows e localize a pasta acessível pelo servidor web (no caso do
Xampp é a pasta c:xampphtdocs). Um comando que pode ser utilizado é o ​cd c:xampphtdocs​.
No prompt de comando digite o comando abaixo, observando que a palavra clinica será o nome da
pasta do seu projeto.
composer create-project yiisoft/yii2-app-basic clinica
A instalação demora alguns minutos e vai depender da sua conexão com a internet. A tela de
instalação se parecerá com o da figura 3.
Figura 3 - Tela parcial de instalação do Yii2
Pronto, seu projeto já está instalado. Abra o navegador no endereço ​http://localhost/clinica/web/​ e já
visualize seu projeto em funcionamento.
4
5.2 Instalação manual
Para a instalação manual é necessário baixar o pacote de arquivos diretamente do site do yii.
Acesse o link ​https://www.yiiframework.com/download​. Procure a sessão “Install from an Archive File” e
faça o download da opção “Yii2 with basic application template”. Um arquivo compactado será baixado.
Para seu projeto funcionar, crie a pasta ​clinica​(que usaremos nos nossos exemplos) dentro da
pasta acessível da web (a htdocs no caso do Xampp). Depois, descompacte o arquivo zipado dentro dessa
pasta.
Quando a instalação é feita manualmente é necessário fazer a seguinte configuração:
● Abra o arquivo config/web.php e preencha algum valor dentro de ​'cookieValidationKey'
=> ​'preenchaaqui'​,
Pronto, seu projeto já está instalado. Abra o navegador no endereço ​http://localhost/clinica/web/​ e já
visualize seu projeto em funcionamento.
Essa segunda forma tende a ser mais rápida que via composer, porém, não gerencia as
dependências que poderão ser utilizadas posteriormente. Mas, mesmo instalando manualmente, dá para
agregar o composer posteriormente.
5.3. Visualização do projeto inicial
Ao instalar o Yii2 no seu projeto já é instalado um template pronto (figura 4) como o visualizado ao
acessar o link ​http://localhost/clinica/web/​ em um navegador.
Figura 4 - Template pronto do Yii2 na instalação básica
Abra, em um gerenciador de arquivos, e visualize o que foi instalado dentro da pasta clinica. A figura
5 apresenta as pastas criadas.
5
Figura 5 - Pastas criadas dentro da pasta do projeto clinica
O Yii2 segue o padrão de projeto Modelo - Visão - Controlador (MVC). As pastas correspondentes
são models (Modelo), views (Visão), controllers (Controlador). Serão as pastas mais utilizadas. As demais
pastas serão exploradas conforme o sistema for sendo desenvolvido neste texto.
6. Banco de Dados
6.1 Criando o banco de dados
Vamos desenvolver o software proposto a partir de um banco de dados já existente. O diagrama do
banco de dados é o apresentado na figura ‘ (seção 2). O código SQL referente a esse banco é o que segue
abaixo. Execute o código abaixo no seu gerenciador de banco de dados. Nesse exemplo usamos o MySQL
e a interface MySQL Workbench.
No momento da criação do banco devem ser observados os seguintes detalhes:
● Escrever o código em letras minúsculas;
● Os campos definidos como NOT NULL já serão configurados como obrigatórios nos
formulários de inserção;
● Defina as chaves primárias com o nome id;
● As chaves estrangeiras não podem ter os nomes das mesmas tabelas as quais fazem
referência, a sugestão é que seja ‘medico_id’, por exemplo.
6
CREATE DATABASE clinica;
USE clinica;
CREATE TABLE IF NOT EXISTS `medico` (
`id` INT(11) NOT NULL,
`nome` VARCHAR(200) NULL DEFAULT NULL,
`especialidade` VARCHAR(100) NULL DEFAULT 'Clinico Geral',
`endereco` VARCHAR(250) NULL DEFAULT NULL,
`telefone` CHAR(14) NULL DEFAULT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `paciente` (
`id` INT(11) NOT NULL,
`nome` VARCHAR(200) NOT NULL,
`endereco` VARCHAR(250) NULL DEFAULT NULL,
`nascimento` DATE NULL DEFAULT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `consulta` (
`id` INT(11) NOT NULL,
`data` DATE NOT NULL,
`horario` TIME NOT NULL,
`medico_id` INT(11) NOT NULL,
`paciente_id` INT(11) NOT NULL,
`valor` DECIMAL(9,2) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`medico_id`)
REFERENCES `medico` (`id`),
FOREIGN KEY (`paciente_id`)
REFERENCES `paciente` (`id`))
ENGINE = InnoDB;
6.2 Configurando uma conexão com o banco de dados
O Yii2 oferece uma camada de alto nível para acesso aos bancos de dados construída a partir do
PDO (Php Data Objects). O framework permite que a manipulação dos dados das tabelas aconteça a partir
de objetos ActiveRecord. Estes objetos encapsulam os métodos para acessar um ou vários registros, assim
como filtrar, fazer junção e ordenar dados. É possível trabalhar com banco de dados usando simplesmente
código SQL, entretanto, considerando as diferenças entre os diferentes gerenciadores de banco de dados,
usar o código SQL perde as facilidades que o Yii2 proporciona [1].
Para configurar uma conexão com o banco abra o arquivo ​clinica/config/db.php e procure
pelo trecho de código:
<?php
return [
'class' => 'yiidbConnection',
'dsn' => 'mysql:host=localhost;dbname=​clinica​,
'username' => '​root​',
'password' => ​''​,
'charset' => 'utf8',
];
7
Altere os valores dos parâmetros dbname, username e password para os do seu SGBD. Observe
que a conexão na propriedade dsn é para o SGBD MySQL.
Outra conexões comuns são:
● MySQL and MariaDB: mysql:host=localhost;dbname=mydatabase
● SQLite: sqlite:/path/to/database/file
● PostgreSQL: pgsql:host=localhost;port=5432;dbname=mydatabase
● MS SQL Server (via mssql driver): mssql:host=localhost;dbname=mydatabase
● Oracle: oci:dbname=//localhost:1521/mydatabase
7. Usando o GII
O Yii2 possui uma poderosa ferramenta para gerar modelos, controladores, o CRUD (Create, Read,
Update e Delete), formulários, módulos e extensões: o Gii.
Para acessar esse recurso acesse o link:
http://localhost/clinica/web/index.php?r=gii
A figura 6 apresenta a tela inicial do Gii.
Figura 6 - Tela inicial do Gii
Caso essa tela não apareça é preciso habilitar o recurso no projeto.
7.1 Habilitando o Gii
Para habilitar esse recurso verifique se os seguintes trechos de código estão presentes nos
respectivos arquivos.
8
● Arquivo clinica/config/web.php: no trecho de código abaixo é verificado se o sistema está em
ambiente de desenvolvimento e habilita o recurso do Gii e indica qual sua classe.
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = ​'debug'​;
$config['modules']['debug'] = 'yiidebugModule';
$config['bootstrap'][] = ​'gii'​;
$config['modules']['gii'] = 'yiigiiModule';
}
● Arquivo clinica/web/index.php: nesse arquivo configuramos se o sistema está em produção,
em teste ou em desenvolvimento. O valor ​‘dev’ ​indica que o sistema está em
desenvolvimento. Para alterar o sistema para teste esse valor deve ser substituído por
‘test’​, e por ​‘prod’​ caso o sistema esteja em produção.
defined('YII_ENV') or define('YII_ENV', ​'dev'​);
7.2 Criando modelos
Modelos representam a lógica do software e são objetos da classe base ​yiibaseModel​. Essa
classe oferece muitas características como os atributos, label dos atributos, atribuições massivas (para
preencher atributos de objetos diretamente de um vetor), regras de validação e exportação de dados.
Normalmente, em aplicações comuns, um Model é gerado a partir de um banco de dados,
extendendo a classe yiidbActiveRecord que implementa o padrão de design Active Record que possui
muitos métodos para manipulação de dados.
O Yii oferece a ferramenta Gii para gerar automaticamente os modelos do sistema baseado no
banco de dados já configurado. Na tela inicial do Gii (​http://localhost/clinica/web/index.php?r=gii​) clique na
opção “Start” abaixo do título “Model Generator”. No formulário que é apresentado basta preencher o nome
da tabela (que já é carregada a partir do banco de dados configurado). O Model Class Name já é sugerido
com o mesmo nome da tabela, porém com a inicial maiúscula, sugere-se que seja mantido, como
apresentado na figura 7.
Figura 7 - Geração de modelos pelo Gii
As demais opções não precisam ser alteradas. Ao clicar em “Preview” é apresentado onde será
criado o código (dentro da pasta models) e qual será o nome do arquivo. Clique em Generate para o
arquivo ser criado onde foi indicado. Em seguida é apresentada a tela confirmando a criação do arquivo
como na figura 8.
9
Figura 8 - Criação de modelo a partir do Gii
Para facilitar essa tarefa basta escrever “*” no campo TableName que o Gii já gerará todos os
modelos de todas as tabelas do banco de dados. Ao clicar em Preview a imagem da figura 9 será
apresentada. O Gii indica quais arquivos de modelos serão criados e, no caso de Paciente que já havia sido
criado, que não houve alteração nenhuma no arquivo de modelo da tabela paciente. Clique em Generate
para efetuar a criação dos modelos.
Figura 9 - Geração de modelos usando o Gii
Abra a pasta models dentro da pasta do seu projeto (clinica) para visualizar os arquivos criados.
Dentro da pasta models são armazenados todos os arquivos relacionados aos modelos, isto é, às classes
que manipulam dados dentro da aplicação. Como exemplo, abra o arquivo Paciente.php para analisar seu
código. Para todos os modelos o Gii já cria automaticamente:
● Definição dos atributos da tabela;
● Criação da classe extendendo a classe ActiveRecord.
● Função tableName() que retorna o nome da tabela.
● Função rules() que definirá quais são os atributos obrigatórios e outras restrições.
● Função attributeLabels() que retorna o label para cada campo da tabela. Esses labels serão
usados para a geração de formulários, coloque o label mais adequado para sua interface.
● Se a tabela estiver do lado 1 de um relacionamento 1:N, é criada uma função
getTabelaRelacionada que irá retornar os elementos que se relacionam com determinado
item. Usando a tabela cliente como exemplo ela se relaciona com a tabela pedido de 1:N. O
Gii gera a função getConsultas() que irá retornar quais são os pedidos de um determinado
cliente passado por parâmetro.
● Se a tabela estiver do lado N de um relacionamento 1:N é criada uma função
getTabelaRelacionada que irá retornar qual elemento da outra tabela aquele item se
relaciona. Usando a tabela pedido como exemplo, ela se relaciona com a tabela Paciente de
1:N (estando do aldo N). O Gii gera a função getPaciente() que irá retornar qual Paciente
está relacionada com determinado produto.
Esses métodos são gerados automaticamente para agilizar o desenvolvimento. Porém, podem ser
alterados conforme a necessidade do seu projeto.
10
7.2.1 Alterando o método Rules() de um modelo
O método rules() de cada modelo define quais são as restrições de preenchimento de cada atributo.
Essas regras serão usadas para a geração de formulários de inserção e alteração de dados. Caso um
campo seja definido como required, no seu respectivo formulário já será apresentado que ele é um campo
obrigatório.
O Gii já gera o método rules() baseado no banco de dados. Os campos definidos como NOT NULL
recebem a regra de required(), os campos de tipo numérico recebem a regra de integer. O formulário que é
gerado automaticamente para o CRUD (seção 7.3) também seguirá essas restrições.
Um exemplo da função rules [2] é a apresentada abaixo:
public​​ ​function​​ ​rules​​()
{
​return​​ ​array​​(
​array​​('username, password', 'required'),
​array​​('password_repeat', 'required', 'on'=>'register'),
​array​​('password', 'compare', 'compareAttribute'=>'password_repeat', 'on'=>'register'),
);
}
A classe Model, que define os modelos, usa o método ​rules() para retornar um vetor com as regras
para validação. No vetor principal, cada linha é um outro vetor que declara uma nova regra de validação.
Essas regras são aplicadas no método validate() do modelo que retorna verdadeiro ou falso. Por padrão, o
método save(), da classe ActiveRecord (que é a responsável por gerenciar os dados do banco de dados),
chama o método validate() para proceder a inserção ou alteração dos dados [2]. Em outras palavras,
quando um novo objeto for inserido, ou alterado, as regras de validação definidas no método rules() serão
testadas.
A sintaxe dos vetores internos deve seguir o seguinte:
array​​(
// mandatory arguments
'attribute list'​,
'validator name'​,
// optional parameters
'on'​=>​'scenario name'​,
'message'​=>​'The attribute didn't validate!'​,
...validation parameters...
);
● Attribute list: especifica os atributos, separados por vírgula a serem validados. O mesmo
atributo pode aparecer em mais de uma linha.
● Validator name: especifica o validador que será usado. Assim, para cada tipo de validador
pode-se agrupar os atributos que possuem aquela regra.
● On: especifica os cenários em que a regra deve ser verificada. Vários cenários podem ser
definidos e devem ser separados por vírgula. Caso não seja definido, a regra será aplicada
em qualquer cenário.
● Message: substitui a mensagem de erro padrão se o atributo não for validado. Essa
mensagem que irá aparecer no formulário se o usuário preencher de forma errada o dado,
ou não preencher os campos obrigatório.
Os validadores podem ser de três tipos [2]:
● Um método da classe modelo com o mesmo nome do validador especificado, isto é, um
método de validação criado pelo programador;
11
● Um validador já embutido no Yii. Todos os validadores do Yii2 extendem a classe CValidator;
● Um caminho para uma classe criada, que extenda o CValidator, e que não é embutida ao Yii.
Exemplo da aplicação dos três tipos, tirada de [2]:
public​​ ​function​​ ​rules​​(){
return​​ ​array​​(
​array​​('password', 'validateLogin'), // Custom validation method in this object
​array​​('username, password', 'required'), // built-in alias for CRequiredValidator
​array​​('username', 'ext.MyValidators.MyLoginValidator'), // Custom validation class
);
}
public​​ ​function​​ ​validateLogin​​() {
// [...]
}
Cada objeto de um modelo tem uma propriedade chamada scenario. Alguns cenários já são
embutidos do próprio Yii e são atribuídos automaticamente, mas também é possível criar novos. Por
exemplo, a leitura de um banco de dados tem um cenario “update”, enquanto um novo registro tem o
cenário “insert” [2]. O código abaixo exemplifica esses cenários.
$modelA = User::model()->findByPk(1); // $model->scenario = 'update'
$modelB = ​new​​ User(); // $model->scenario = 'insert'
$modelB->scenario = 'light'; // custom scenario
if​​ ($modelB->validate()) { // will only apply rules of the "light" scenario
Como mostrado no primeiro exemplo dessa seção as regras podem ser restritas a um específico
cenário a partir do parâmetro “on”=>”scenario”.
Existe uma grande variedade de validadores do framework Yii. Alguns são listados abaixo. Para
cada um desses ainda existem algumas características que podem ser acrescentadas. Para buscar todas
as possibilidades sugerimos a consulta do link do ​documento de referência​ e da classe ​CValidator​.
● boolean
● captcha
● compare
● date
○ array(‘org_datetime’,’date’,’format’=>’yyyy-M-d H:m:s’)
● default
● email
● exist
● file
● filter
○ array(‘mycode’,’filter’,’filter’=>’strtoupper’)
● in
● length
● match
● numerical
○ array(‘quantity’,’numerical’,’integerOnly’=>true, ‘min’=>1, ‘max’=>250),
● required
● safe
● type
● unique
● unsafe
● url
12
Para exemplificar vamos alterar o método rules do modelo Paciente. Acrescentou-se uma
mensagem que será apresentada caso o usuário não preencha o campo e outra caso o usuário preencha
um nome com mais de 100 caracteres.
Observe o código abaixo:
public function rules(){
return [
[['nome'], 'required','message'=>'Preencha o nome do Paciente'],
[['nome'], 'string', 'max' => 100,'message'=>'O nome deve ter no máximo
100 caracteres'],
];
}
Utilizando as referências citadas acima, e analisando a necessidade do seu usuário final, é possível
customizar o modelo como for desejado.
7.3 Usando o Gii para gerar o CRUD
O Gii permite a geração automática do CRUD de qualquer modelo já existente. O CRUD
corresponde, respectivamente, à inserção (create), consulta (read), atualização (update) e exclusão (delete)
de itens do modelo.
Acesse a tela inicial do Gii e clique em “Start” abaixo do título “CRUD Generator”. É necessário gerar
o CRUD para cada modelo existente um de cada vez. Vamos fazer o primeiro exemplo do CRUD para a
tabela Paciente. No formulário que aparece preencha:
● Model Class = “appmodelspaciente”, indica o nome do modelo para o qual será feito o
CRUD. É necessário indicar todo o caminho. A palavra app indica o caminho da sua
aplicação / projeto.
● Search Model Class = “appmodelsPacienteSearch”. Criará mais um modelo para gerar
filtros para o modelo escolhido. A recomendação é colocar o nome do modelo seguido da
palavra Search, seguindo o padrão CamelCase.
● Controller Class = “appcontrollersPacienteController”. Criará a classe de Controller
relacionada ao modelo indicado dentro da pasta controllers. Também seguir o padrão
CamelCase.
● View Path = “@app/views/paciente”. Cria uma pasta Paciente dentro da pasta views que, por
sua vez, está dentro da pasta da aplicação (@app). Atenção para quando o controller tiver
mais de um nome, por exemplo: NotaFiscalEntrada. A pasta a ser criada deverá se chamar
nota-fiscal-entrada. Observe também que as pastas das views são escritas com letras
minúsculas.
Clique em Preview. Na página que é apresentada aparece a lista da figura 10 mostrando todos os
arquivos que serão criados.
13
Figura 10 - Arquivos que serão gerados no CRUD de Paciente
Clique na opção Generate para geração de todos os arquivos. Faça a mesma coisa para os outros
modelos listados anteriormente. Todas as telas de para o CRUD de cada um dos modelos serão criadas e
o sistema estará quase pronto.
7.4 Rotas
Toda requisição feita a um sistema do padrão MVC aciona um controlador. O controlador analisa a
requisição e apresenta a respectiva view. Por exemplo, quando acessamos:
http://localhost/clinica/web/index.php?r=paciente
estamos chamando um controlador chamado produto e a sua action Index. Na url o nome do
controlador sempre iniciará com letra minúscula. O framework procurará um arquivo na pasta controllers
com o nome passado no parâmetro “r”, que inicie com letra maiúscula e que tenha o sufixo Controller. No
exemplo acima o nome passado pelo parâmetro r é “produto”, o framework irá buscar o arquivo
ProdutoController dentro da pasta controller.
Dentro do controller existem várias actions, todas iniciadas com o prefixo action e finalizadas com o
nome da função em si. Por padrão, a actionIndex() será executada caso nenhuma action seja indicada. No
exemplo acima a actionIndex do controlador ProdutoController é executada. Caso se deseje chamar outra
action desse controlador basta adicionar o nome da action após o nome do controller na url precedido de
“/”. Exemplo:
http://localhost/clinica/web/index.php?r=paciente/create
A url acima executa a actionCreate do PacienteController que corresponde à view de inserção de
um novo paciente. Todos os métodos do controlador que são actionFunção podem ser chamados
diretamente via url.
Outro exemplo seria quando o nome do controller é composto por mais de uma palavra. Por
exemplo o modelo notafiscalentrada. Ao fazermos o CRUD para esse modelo seu controller se chama
NotaFiscalEntradaController e sua pasta de views se chama nota-fiscal-entrada. Para acessar esse
controller seu nome também deverá ser digitado em letras minúsculas e as palavras separadas por hífens:
http://localhost/clinica/web/index.php?r=nota-fiscal-entrada
Essa mesma regra se aplica para as actions caso elas possuam mais de uma palavra.
7.5 Analisando os controladores
Controllers, são a ponte entre a visão (view) e o modelo (model). São classes que estendem de
yiibaseController e são usados para processar requisições e gerar respostas.Controllers possuem
principalmente funções cujo nome começa com o prefixo action que permite o framework reconhecer as
rotas das funções que podem ser requisitadas.
14
Os controladores, dentro da pasta controllers, são o ponto de partida de qualquer função dentro do
sistema. A partir deles que são chamados os modelos e visões necessárias para o funcionamento de
qualquer função.
Os controllers também podem ser criados automaticamente usando a ferramenta Gii a partir de
modelos já existentes. O Yii cria os controllers com os seguintes métodos:
● actionCreate() - usado para criar um novo objeto (inserir) do modelo
● actionView() - usado para visualizar os detalhes do objeto do modelo
● actionUpdate() - usado para atualizar um objeto do modelo existente
● actionDelete() - usado para deletar um objeto do modelo existente
● actionIndex() - usado para mostrar, usando um grid, uma lista de objetos do modelo
● behaviors() - método para definir alguns comportamentos, como acesso de usuários, do
controlador. Não pode ser acessado via url.
● findModel() - encontra o modelo baseado em um valor de chave primária. Por exemplo,
encontra a Paciente de código 1. Se o modelo não for encontrado é retornado o erro http
404.
Outras actions podem ser acrescentadas a partir da necessidade do desenvolvedor, assim como as
que foram geradas automaticamente podem ser alteradas. Vamos analisar o código das actions criadas a
partir do modelo Paciente e localizadas no arquivo controllers/PacienteController.php.
7.5.1 actionIndex()
public function actionIndex()
{
$searchModel = new PacienteSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
Essa action pode ser acessada por ​http://localhost/clinica/web/index.php?r=paciente​, ou
http://localhost/clinica/web/index.php?r=paciente/index​ .
Ela é responsável por apresentar a tela inicial de gerenciamento dos modelos mostrando todos os
registros daquele modelo e o que pode ser feito com ele: criar um novo, alterar e excluir os existentes. No
código acima ele cria as variáveis $searchModel e $dataProvider que serão responsáveis por compor o
GridView na view index. O return renderiza a view index e passa como parâmetro essas duas variáveis.
7.5.2 actionView()
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
Essa action pode ser acessada por ​http://localhost/clinica/web/index.php?r=Paciente/view&id=1​.
Onde id=1 é a chave da Paciente que deseja ser visualizada.
15
Essa action recebe como parâmetro a chave do objeto a ser apresentado e renderiza a view
chamada ‘view’ passando como parâmetro o próprio (this) modelo daquele id. Em outras palavras, envia
para view os dados daquela Paciente selecionada.
7.5.3 actionCreate()
public function actionCreate()
{
$model = new Paciente();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
}
Essa action pode ser acessada pela url ​http://localhost/clinica/web/index.php?r=paciente/create​.
Inicialmente é criado um objeto do modelo Paciente. O if seguinte verifica se o usuário clicou no botão
salvar, isto é, já preencheu os dados do Paciente e clicou em Salvar. Caso o post tenha sido solicitado e o
modelo conseguir ser salvo (lembrando que o método save() busca o método rules() do modelo e valida
todos os dados informados), a action redireciona para a view ‘view’ onde mostra os detalhes do registro que
acabou de ser inserido. Caso queira redirecionar para outra view, altere essa linha de código.
Caso o if retorne falso, isso acontecerá quando a página for carregada e o botão salvar ainda não foi
clicado, a action renderiza a view create enviando como parâmetro o modelo. Isso permitirá que o modelo
receba os dados que forem preenchidos.
7.5.4 actionUpdate()
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
]);
}
Essa action pode ser acessada pela url
http://localhost/clinica/web/index.php?r=paciente/update&id=1​ .
Quase identica a actionCreate(), a actionUpdate se diferencia porque recebe a chave do elemento
que se deseja alterar. Ao criar o modelo, primeira linha, não se cria um novo objeto, se busca um já
existente com o método findModel. E ao renderizar, ele apresentará a view update, também passando
como parâmetro o modelo que foi encontrado.
16
7.5.5 actionDelete()
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
Essa action pode ser acessada pela url
http://localhost/clinica/web/index.php?r=paciente/delete&id=1​ .
A actionDelete recebe como parâmetro a chave do elemento que será excluído. É chamada a
função delete(), que é um método da classe ActiveRecord para excluir um registro. Após executado esse
código o sistema é redirecionado para a view index.
7.6 Analisando as visões
As views apresentam os resultados enviados pelos controllers. Ao usar o Gii para geração do CRUD
é criada uma pasta, dentro da pasta views, para aquele controlador. Dentro dessa nova pasta são criadas
as seguintes views:
● Create: página de inserção de dados, utiliza o formulário definido em _form;
● Index: apresenta todos os registros do modelo em um gridview e usando um filtro de
pesquisa padrão (a partir do _search);
● Update: tela para atualização dos dados, também utiliza o _form;
● View: visualização detalhada de um registro;
● _form: formulário para inserção e alteração dos dados de um modelo;
● _search: formulário para pesquisa de dados, é apresentado acima do gridview.
Arquivos de view iniciados com “_” são considerados no Yii2 como subviews, isto é, que são
chamadas por outras views. No caso de _form e _search, eles são chamados no arquivo create e update.
Os dois arquivos usam o mesmo _form para mostrar campos editáveis.
Observe que cada view corresponde a cada ação do controlador. Assim os nomes devem sempre
corresponder. Por exemplo: no PacienteController existe a actionIndex. Essa action renderiza uma view
chamada index.php. Essa view estará localizada dentro da pasta views/Paciente. Os arquivos sempre
iniciam com letras minúsculas.
Cada view recebe parâmetros do controlador que são acessadas via código php e possuem códigos
html que também podem ser manipulados conforme a necessidade do desenvolvedor. Por padrão o Yii já
implementa o framework Bootstrap.
As views são inseridas dentro do corpo de um layout pré-definido. Esse layout fica na pasta
views/layouts/main.php. Outros layouts podem ser utilizados, assim como o layout padrão pode ser
alterado.
A seguir apresentamos as views e comentamos os códigos para melhor análise.
7.6.1 _form.php
<?php
//quais classes serão usadas
use yiihelpersHtml; ​//classe responsável por inserir elementos ​HTML
use yiiwidgetsActiveForm; ​//widget para inserir um formulário
17
/* @var $this yiiwebView */
/* @var $model appmodelsPaciente */
/* @var $form yiiwidgetsActiveForm */
?>
// essa view recebe o modelo ($model) como parâmetro, ou do create.php ou do update.php
<div class="paciente-form">
<?php $form = ActiveForm::begin(); ?> ​//abertura do formulário
<?= $form->field($model, 'nome')->textInput(['maxlength' => true]) ?> ​//inserção de um campo
do tipo text que corresponderá ao campo nome do modelo. O campo texto terá a quantidade máxima
definida pela quantidade de caracteres definidas no banco de dados. Nesse exemplo a quantidade é
de 100 caracteres. O código html gerado é:
<input type="text" id="Paciente-nome" class="form-control" name="Paciente[nome]" maxlength="100"
aria-required="true">
A classe que define os campos dos formulários é a ​ActiveField​.
<div class="form-group">
<?= Html::submitButton('Salvar', ['class' => 'btn btn-success']) ?>
//um botão de submissão é colocado no formulário, em uma div separada, e é definida sua
respectiva classe bootstrap
</div>
<?php ActiveForm::end(); ?> ​//fechamento do formulário
</div>
7.6.2 create.php
<?php
use yiihelpersHtml;
/* @var $this yiiwebView */
/* @var $model appmodelsPaciente */
$this->title = 'Create Paciente'; ​//define o título da página
$this->params['breadcrumbs'][] = ['label' => 'Pacientes', 'url' => ['index']]; ​//define o
2° breadcrumbs para voltar para o index de Paciente
$this->params['breadcrumbs'][] = $this->title; ​//define o último breadcrumb que indica que
está no Create Paciente
?>
<div class="Paciente-create">
<h1><?= Html::encode($this->title) ?></h1>​//mostra o título da página
<?= $this->render('_form', [
'model' => $model,
]) ?> ​//renderiza o _form enviando o modelo recebido pelo controller. Como é a view de
inserção, esse modelo está vazio
</div>
18
7.6.3 update.php
<?php
use yiihelpersHtml;
/* @var $this yiiwebView */
/* @var $model appmodelsPaciente */
$this->title = 'Update Paciente: ' . $model->id; ​//define o título da página com o id do
elemento que está sendo atualizado
$this->params['breadcrumbs'][] = ['label' => 'Pacientes', 'url' => ['index']]; ​//define o
2° breadcrumb com link para o index de Paciente
$this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' =>
$model->id]];​//define o 3° breadcrumb que direciona para a view do elemento que está sendo
atualizado
$this->params['breadcrumbs'][] = 'Update';​//define o 4° breadcrumb que é a página que está
sendo apresentada
?>
<div class="paciente-update">
<h1><?= Html::encode($this->title) ?></h1>​//coloca o título da página
<?= $this->render('_form', [
'model' => $model,
]) ?>
//renderiza o _form enviando o modelo que foi enviado do controller. Nesse caso o modelo
possui os dados da Paciente selecionada
</div>
7.6.4 view.php
<?php
use yiihelpersHtml;
use yiiwidgetsDetailView;
/* @var $this yiiwebView */
/* @var $model appmodelsPaciente */
$this->title = 'Paciente '.$model->id;
$this->params['breadcrumbs'][] = ['label' => 'Pacientes', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="paciente-view">
<h1><?= Html::encode($this->title) ?></h1>
19
<p>
<?= Html::a('Update', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?>
//insere um link para a view update, passando como parâmetro o id e formatando com a classe do
bootstrap
<?= Html::a('Delete', ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
//insere um link para a view delete, passando como parâmetro o id e formatando com a classe do
bootstrap. Além disso pergunta ao usuário se tem certeza que deseja excluir aquele item antes de
confirmar a exclusão.
</p>
//o DetailView é um widget usado para apresentar dados de um modelo
<?= DetailView::widget([​//os parametros são
'model' => $model,​//o modelo
'attributes' => [​//quais atributos serão apresentados
'id',
'nome',
],
]) ?>​//para mais detalhes veja a referencia do ​DetailView
</div>
7.6.5 _search.php
<?php
//o _search cria um formulário de busca de registros e mostra o resultado no index.
Porém, se o widget GridView for utilizado o código que renderiza essa view é
comentado. No momento de gerar o Crud no Gii, se for escolhido o ListView, ao invés
do GridView, o _search será renderizado.
use yiihelpersHtml;
use yiiwidgetsActiveForm;
/* @var $this yiiwebView */
/* @var $model appmodelsPacienteSearch */
/* @var $form yiiwidgetsActiveForm */
?>
<div class="Paciente-search">
<?php $form = ActiveForm::begin([
'action' => ['index'],
'method' => 'get',
]); ?>​//inicia um formulário enviando os dados de busca via get
20
<?= $form->field($model, 'id') ?>​//coloca o campo id para filtro
<?= $form->field($model, 'nome') ?>​//coloca o campo de nome para o filtro
<div class="form-group">
<?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
<?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?>
</div>​//botões de submeter e resetar (ficam omitidos na página)
<?php ActiveForm::end(); ?> ​//finaliza o formulário
</div>
7.6.6 index.php
<?php
use yiihelpersHtml;
use yiigrid​GridView​;​//Widget para mostrar os dados dentro de um grid (tabela)
/* @var $this yiiwebView */
/* @var $searchModel appmodelsPacienteSearch */
/* @var $dataProvider yiidataActiveDataProvider */
$this->title = 'Pacientes';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="Paciente-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
//a renderização da view _search é comentada para usar o gridview
<p>
<?= Html::a('Nova Paciente', ['create'], ['class' => 'btn btn-success']) ?>
</p>​//link para a view create
<?= GridView::widget([​//parametros do GridView
'dataProvider' => $dataProvider,​//seleção de dados criada no Controller
'filterModel' => $searchModel,​//filtros enviados do Controller
'columns' => [
['class' => 'yiigridSerialColumn'],​//coluna de contagem de linhas
'id',​//colunas do objeto que está sendo apresentado
'nome',
21
['class' => 'yiigridActionColumn'],​//colunas de ações: view, update e
delete
],
]); ?>
</div>
7.7 Visualizando as funções do sistema
Para acessar as diversas funções que já estão funcionando no sistema use as seguintes rotas:
● http://localhost/clinica/web/index.php?r=paciente/index
● http://localhost/clinica/web/index.php?r=paciente/create
● http://localhost/clinica/web/index.php?r=paciente/update&id=1
● http://localhost/clinica/web/index.php?r=paciente/delete&id=1
● http://localhost/clinica/web/index.php?r=paciente/view
8. Alterações na Interface
8.1 Alterando o menu principal
Agora que já acessamos o sistema via ​http://localhost/clinica/ queremos acessar os CRUD’s criados
a partir do menu existente, sem precisar ficar digitando rotas. Iremos acrescentar opções de menu na barra
superior referente a cada CRUD que foi criado. Não é a melhor interface que pode ser criada, somente uma
sugestão.
Abra o arquivo views/layout/main.php e procure pelo seguinte trecho de código:
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => [
['label' => 'Home', 'url' => ['/site/index']],
['label' => 'About', 'url' => ['/site/about']],
['label' => 'Contact', 'url' => ['/site/contact']],
Acrescente imediatamente abaixo os seguintes itens:
['label' => 'Pacientes', 'url' => ['/paciente/index']],
['label' => 'Médicos', 'url' => ['/medico/index']],
['label' => 'Consultas', 'url' => ['/consulta/index']],
Observe que a url corresponde ao controlador e sua actionIndex.
8.2 Views = Create / Update _form
8.2.1 Alterar o título da página
Arquivo: create.php
Altere a seguinte linha de código para o valor que deseja que seja apresentado.
22
$this->title = 'Create Paciente';
Exemplo:
$this->title = 'Novo Paciente';
8.2.2 Campo do tipo data
Arquivo: _form.php
Na linha de código que insere o campo que tem que ser o tipo de data, acrescente a propriedade
['type'=> 'date'].
Exemplo, no cadastro de paciente temos o campo nascimento, o código gerado automaticamente é:
<?= $form->field($model, 'nascimento')->textInput() ?>
O código para aparecer o formato de data é:
<?= $form->field($model, 'nascimento')->textInput(['type'=> 'date']) ?>
O código [‘type’=>’date’] pode ser alterado para qualquer tipo existente no HTML5.
8.2.3 Campo do tipo select / dropdown (com dados estáticos)
Arquivo: _form.php
Para fazer um select, que não busca dados do banco, acrescente a seguinte linha de código no seu
formulário. Esse código deve substituir o código criado automaticamente pelo gii para o campo escolhido.
No nosso exemplo vamos criar um select para o campo especialidade de médico. Vale observar que
o ideal nessa situação é que as especialidades estivessem cadastradas no banco de dados, e não de forma
estática como nesse exemplo.
<?=​ $form->field($model,​’especialidade’​)->dropDownList(
[
'1'​=>​'Clínico Geral',
'2'​=>​'Dermatologista',
'3'​=>​'Pediatria'​,
],
['prompt' => 'Selecione uma especialidade’] )
) ​?>
O código ​'1'​=>​'Clínico Geral' ​indica que será criado um option no select com o value=1 e o label
igual a Pediatria. O que é armazenado no banco de dados é o value, no exemplo, o valor 1. Caso se deseje
armazenar o texto, o código deve ser alterado para: ​'Clínico Geral'​=>​'Clínico Geral'. ​Observação:
os dados já devem ser colocados na ordem que serão apresentados.
8.2.4 Campo do tipo select / dropdown com dados de outra tabela
Fonte: ​Vídeo - aula
Arquivo: _form.php
No nosso exemplo, ao cadastrar uma nova consulta, deseja-se escolher qual é o paciente será
atendido. Os nomes dos pacientes estão na tabela paciente, e a chave estrangeira para eles é que é
armazenada na tabela consulta.
Para que apareça um select (ou dropdown) com os nomes dos pacientes substitua o código que
insere o campo do paciente pelo código abaixo:
Código original:
<?= $form->field($model, 'medico_id')->textInput() ?>
23
Código para gerar o select/dropdown:
<?= $form->field($model, 'medico_id')->
dropDownList(ArrayHelper::map(Medico::find()
->orderBy('nome')
->all(),'id','nome'),
['prompt' => 'Selecione um médico'])
?>
Ainda, é necessário acrescentar no topo do arquivo as classes que são usadas para fazer esse
trecho de código funcionar. Acrescente no início do documento:
use yiihelpersArrayHelper;
use appmodelsMedico;
O que esse código faz? Primeiro, o trecho Medico::find()->orderBy('nome')->all() retorna todos os
elementos da classe Medico ordenados pelo campo nome. O retorno desse código é uma lista (vetor) de
objetos ActiveQuery.
O código ArrayHelper::map(,'id','nome') constrói um mapa (pares de chave-valor) a partir de um
vetor dado. No caso o vetor passado é a lista dos fornecedores existentes e os parâmetros ‘id’ e ‘nome’
serão o par chave e valor do novo vetor.
O widget dropDownList tem que receber como parâmetro um vetor chave valor para associar às
options e valores do select. As chaves serão os values dos options, e os valores seus labels
correspondentes. Esse vetor é o que foi criado pela função map.
Outro item essencial é adicionar as bibliotecas no topo da view para que o código funcione. Nesse
exemplo devem ser adicionadas o endereço da classe ArrayHelper e do modelo Paciente.
8.2.5 Alterar as mensagens de erro do formulário
As mensagens de erro são alteradas no método rules() do modelo. Como exemplo temos que o
campo nome do paciente é obrigatório. Caso ele não seja preenchido uma mensagem de erro será
apresentada. Para alterar a mensagem deve ser colocado o seguinte código no models/Paciente.php:
public function rules()
{
return [
[['nome'], 'required','message'=>'Preencha o nome do paciente',],
[['nascimento'], 'safe'],
[['nome'], 'string', 'max' => 200],
[['endereco'], 'string', 'max' => 250],
];
}
Observe que a mensagem de erro deve ser no vetor que informa que o campo é ‘required’.
8.3 Views = View.php
8.3.1 Formatar uma data no detailview
Ao visualizar os dados do paciente, por padrão, é apresentada a data no formato americano. Para
alterar o formato da data é preciso refazer o código que apresenta o campo, no exemplo, de nascimento.
Localize no arquivo view.php (da pasta paciente) o seguinte código:
<?= DetailView::widget([
'model' => $model,
24
'attributes' => [
'id',
'data',
'horario',
'medico_id',
'paciente_id',
'valor',
],
]) ?>
Uma primeira forma de alterar o formato para data é acrescentar a propriedade ‘format’ para o
atributo. Além do format também deve ser informado o label e o atributo (ou valor) que será apresentado.
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'nome',
'endereco',
​[
'label' => 'Nascimento',
'attribute' => 'nascimento',
'format' => ['date', 'php:d/m/Y'],
]
],
]) ?>
O DetailView é um widget que apresenta os dados de um modelo, no exemplo, os dados do
paciente. Cada valor apresentado no vetor ‘attributes’ é um campo da tabela paciente. Para formatar a data
de nascimento em um formato diferente primeiro deve-se acrescentar o parâmetro formatter (em amarelo),
e nos atributos acrescentar ​:date​ ao campo que se deseja alterar o formato.
<?= DetailView::widget([
'model' => $model,
​'formatter' => [
'class' => 'yiii18nFormatter',
'dateFormat' => 'dd/MM/yyyy',
],
'attributes' => [
'id',
'nome',
'endereco',
​'nascimento:date',
],
]) ?>
25
Outra forma é somente alterar o atributo nascimento substituindo o campo nascimento pelo codigo
abaixo:
[
'label'=>'Nascimento',
'value'=> function ($model) {
return Yii::$app->formatter->asDateTime($model->nascimento,
'php:d/m/Y');
},
],
Este código define novamente qual será o label do campo e no value é executada uma função que
formata o campo do nascimento para o formato d/m/Y do php.
8.3.2 Alterar um valor na visualização (view.php) com if
De acordo com nosso exemplo, ao cadastrar um médico selecionamos sua especialidade em um
select que foi criado de forma estática (sem buscar no banco de dados). Na view que apresenta os dados
do médico, precisamos mostrar o nome da especialidade e não o número dela.
Seguindo o exemplo anterior, quando a pessoa escolhe no select colocado o que é guardado no
banco é o valor 1, 2 ou 3. No momento de visualizar o registro se deseja traduzir esses números para o
nome da especialidade.
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'nome',
'especialidade',
'endereco',
'telefone',
],
]) ?>
Acima é o código original da view.php que apresenta os dados do médico. Vamos alterar o campo
especialidade para apresentar os valores pré-definidos.
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'nome',
​[
'label'=>'Especialidade',
'value'=>function($model){
if($model->especialidade==1){
return "Pediatria";
}
if($model->especialidade==2){
26
return "Clínico Geral";
}
if($model->especialidade==3){
return "Dermatologista";
}
}
],
'endereco',
'telefone',
],
]) ?>
Mais detalhes sobre esse widget podem ser encontrados nos seguintes links:
● https://www.yiiframework.com/doc/guide/2.0/en/output-data-widgets
● https://www.yiiframework.com/doc/api/2.0/yii-widgets-detailview​.
8.3.3 Mostrar um dado de uma outra tabela
Ao visualizar a consulta queremos mostrar o nome do médico e o nome do paciente, e não os seus
códigos. Para isso é necessário substituir os campos medico_id e paciente_id por outros códigos.
Para o médico:
[
'label'=>'Médico',
'attribute'=>'medico.nome',
],
Para o paciente
[
'label'=>'Paciente',
'attribute'=>'paciente.nome',
],
Caso o campo seja substituído somente por paciente.nome, por exemplo, o label do campo será o
do modelo Paciente. Por isso é necessário redefinir o label para cada um dos campos.
8.3.4 Alterar mensagem de exclusão
No arquivo view.php é possível alterar a mensagem que é apresentada ao usuário caso ele clique
no botão ‘Delete’. Basta procurar pelo código abaixo e substituir a mensagem marcada em amarelo.
<?= Html::a('Delete', ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => '​Are you sure you want to delete this item?​',
'method' => 'post',
],
]) ?>
27
8.4 Views = Index.php
8.4.1 Formatar uma data no gridview
O gridview é o widget utilizado no index.php e apresenta vários recursos para sumarização dos
dados. Por padrão ele seleciona todos os registros da tabela que são carregados na variável $dataProvider,
o recurso de busca no início de cada coluna, e as funções de visualizar, excluir e alterar para cada registro.
Assim como no detailview, o gridview também mostra o formato de data no formato americano. Para
alterar o formato basta substituir o campo desejado pelo código abaixo:
[
'attribute'=> 'nascimento',
'format' => ['date', 'php:d/m/Y'],
],
8.4.2 Alterar um valor no index.php com if
No nosso exemplo, ao buscar a especialidade do médico é retornado valores numéricos e não o
nome da especialidade. Como os valores são estáticos, é preciso fazer um if para verificar o valor do
número retornado. O código do gridview fica da seguinte forma:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yiigridSerialColumn'],
'id',
'nome',
​[
'label'=>'Especialidade',
'attribute'=>'especialidade',
'value'=>function($model){
if($model->especialidade==1){
return "Pediatria";
}
if($model->especialidade==2){
return "Clínico Geral";
}
if($model->especialidade==3){
return "Dermatologista";
}
},
'format' => 'html',
'filter' => [1 => 'Pediatria', 2 => 'Clínico Geral', 3 =>
'Dermatologista'],
],
'endereco',
'telefone',
28
['class' => 'yiigridActionColumn'],
],
]); ?>
8.4.3 Mostrar um dado de uma outra tabela na view index.php
Ao visualizar as consultas são retornados os códigos dos médicos e paciente. Os nomes, que seria
o adequado de ser apresentado, estão em suas respectivas tabelas. Para apresentar o nome destes itens
deve-se fazer as alterações a seguir.
O primeiro passo é substituir ​‘medico_id’ ​por:
[
'attribute'=>'medico.nome',
'label'=>'Médico',
'filter'=>ArrayHelper::map(Medico::find()->asArray()->all(),'id',
'nome'),
],
Ao visualizar o resultado observe que a coluna Medico está com a ordenação e o filtro desabilitados.
É necessário alterar o modelo ConsultaSearch para adicionar essas funcionalidades. Abra o respectivo
arquivo e adicione os códigos que estão grifados em amarelo:
<?php
namespace appmodels;
use Yii;
use yiibaseModel;
use yiidataActiveDataProvider;
use appmodelsConsulta;
/**
* ConsultaSearch represents the model behind the search form of `appmodelsConsulta`.
*/
class ConsultaSearch extends Consulta
{
/**
* {@inheritdoc}
*/
​public function attributes()
{
// add related fields to searchable attributes
return array_merge(parent::attributes(), ['medico.nome','paciente.nome']);
}
public function rules()
{
return [
[['id'], 'integer'], ​//os campos medico_id e paciente_id foram retirados
[['data', 'horario',​'medico.nome','paciente.nome'​], 'safe'],
[['valor'], 'number'],
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
29
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$query = Consulta::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
​ $query->joinWith(['medico']);
$dataProvider->sort->attributes['medico.nome']=[
'asc'=>['medico.nome'=>SORT_ASC],
'desc'=>['medico.nome'=>SORT_DESC],
];
$query->joinWith(['paciente']);
$dataProvider->sort->attributes['paciente.nome']=[
'asc'=>['paciente.nome'=>SORT_ASC],
'desc'=>['paciente.nome'=>SORT_DESC],
];
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'data' => $this->data,
'horario' => $this->horario,
'medico_id' => $this->medico_id,
'paciente_id' => $this->paciente_id,
'valor' => $this->valor,
]);
​$query->andFilterWhere(['=', 'medico.id',$this->getAttribute('medico.nome')]);
$query->andFilterWhere(['=', 'paciente.id',$this->getAttribute('paciente.nome')]);
return $dataProvider;
}
}
30

Más contenido relacionado

Similar a Minicurso Yii2

NoSQL com Zend Framework 2
NoSQL com Zend Framework 2NoSQL com Zend Framework 2
NoSQL com Zend Framework 2Flávio Lisboa
 
Curso de Java (Parte 5)
Curso de Java (Parte 5)Curso de Java (Parte 5)
Curso de Java (Parte 5)Mario Sergio
 
Palestra - Symfony Framework MVC PHP 5
Palestra - Symfony Framework MVC PHP 5Palestra - Symfony Framework MVC PHP 5
Palestra - Symfony Framework MVC PHP 5Lucas Augusto Carvalho
 
Introdução ao zend framework
Introdução ao zend frameworkIntrodução ao zend framework
Introdução ao zend frameworkMarcos Oliveira
 
Analise frameworks php
Analise frameworks phpAnalise frameworks php
Analise frameworks phpIgor Moura
 
hibernate annotation
hibernate annotationhibernate annotation
hibernate annotationeduardo dias
 
Entendendo Frameworks web com Python
Entendendo Frameworks web com PythonEntendendo Frameworks web com Python
Entendendo Frameworks web com PythonLuiz Aldabalde
 
Entendendo Framework Web com Python
Entendendo Framework Web com PythonEntendendo Framework Web com Python
Entendendo Framework Web com PythonPythOnRio
 
Aula 1 -_ambiente_visual_studio_2012
Aula 1 -_ambiente_visual_studio_2012Aula 1 -_ambiente_visual_studio_2012
Aula 1 -_ambiente_visual_studio_2012Laís Vidal
 
Phalcon FrameWork - Considerações Iniciais
Phalcon FrameWork - Considerações IniciaisPhalcon FrameWork - Considerações Iniciais
Phalcon FrameWork - Considerações IniciaisPauloRobertoBolsanel
 
Iniciando com o_zend_framework
Iniciando com o_zend_frameworkIniciando com o_zend_framework
Iniciando com o_zend_frameworkMilton Rodrigues
 
Bancos de dados e jdbc java para desenvolvimento web
Bancos de dados e jdbc   java para desenvolvimento webBancos de dados e jdbc   java para desenvolvimento web
Bancos de dados e jdbc java para desenvolvimento websilvio_sas
 
ZF Básico - 1. Introdução
ZF Básico - 1. IntroduçãoZF Básico - 1. Introdução
ZF Básico - 1. IntroduçãoMarcos Bezerra
 
Apostila Zend Framework
Apostila Zend FrameworkApostila Zend Framework
Apostila Zend FrameworkFernando Palma
 
Code Igniter & Zend Framework Uma UniãO De Sucesso
Code Igniter & Zend Framework   Uma UniãO De SucessoCode Igniter & Zend Framework   Uma UniãO De Sucesso
Code Igniter & Zend Framework Uma UniãO De SucessoJose Wilker
 

Similar a Minicurso Yii2 (20)

NoSQL com Zend Framework 2
NoSQL com Zend Framework 2NoSQL com Zend Framework 2
NoSQL com Zend Framework 2
 
Curso de Java (Parte 5)
Curso de Java (Parte 5)Curso de Java (Parte 5)
Curso de Java (Parte 5)
 
Palestra - Symfony Framework MVC PHP 5
Palestra - Symfony Framework MVC PHP 5Palestra - Symfony Framework MVC PHP 5
Palestra - Symfony Framework MVC PHP 5
 
Introdução ao zend framework
Introdução ao zend frameworkIntrodução ao zend framework
Introdução ao zend framework
 
Analise frameworks php
Analise frameworks phpAnalise frameworks php
Analise frameworks php
 
Cake Php
Cake PhpCake Php
Cake Php
 
hibernate annotation
hibernate annotationhibernate annotation
hibernate annotation
 
Entendendo Frameworks web com Python
Entendendo Frameworks web com PythonEntendendo Frameworks web com Python
Entendendo Frameworks web com Python
 
Entendendo Framework Web com Python
Entendendo Framework Web com PythonEntendendo Framework Web com Python
Entendendo Framework Web com Python
 
Aula 1 -_ambiente_visual_studio_2012
Aula 1 -_ambiente_visual_studio_2012Aula 1 -_ambiente_visual_studio_2012
Aula 1 -_ambiente_visual_studio_2012
 
Phalcon FrameWork - Considerações Iniciais
Phalcon FrameWork - Considerações IniciaisPhalcon FrameWork - Considerações Iniciais
Phalcon FrameWork - Considerações Iniciais
 
Crud
CrudCrud
Crud
 
Iniciando com o_zend_framework
Iniciando com o_zend_frameworkIniciando com o_zend_framework
Iniciando com o_zend_framework
 
Iniciando com django
Iniciando com djangoIniciando com django
Iniciando com django
 
Palestra
PalestraPalestra
Palestra
 
Bancos de dados e jdbc java para desenvolvimento web
Bancos de dados e jdbc   java para desenvolvimento webBancos de dados e jdbc   java para desenvolvimento web
Bancos de dados e jdbc java para desenvolvimento web
 
ZF Básico - 1. Introdução
ZF Básico - 1. IntroduçãoZF Básico - 1. Introdução
ZF Básico - 1. Introdução
 
Apostila Zend Framework
Apostila Zend FrameworkApostila Zend Framework
Apostila Zend Framework
 
Oracle
OracleOracle
Oracle
 
Code Igniter & Zend Framework Uma UniãO De Sucesso
Code Igniter & Zend Framework   Uma UniãO De SucessoCode Igniter & Zend Framework   Uma UniãO De Sucesso
Code Igniter & Zend Framework Uma UniãO De Sucesso
 

Minicurso Yii2

  • 1. INTRODUÇÃO AO FRAMEWORK YII2 CLEIANE GONÇALVES OLIVEIRA RODRIGO MARQUES CAMPOS GUILHERME LUIS VIANA ALVES X SIMPÓSIO DE INFORMÁTICA
  • 2. Este material foi construído para o minicurso de Introdução ao Framework Yii2 ministrado no X Simpósio de Informática do IFNMG - Campus Januária (novembro - 2018). Tem como objetivo divulgar o framework YII2 para colaborar no desenvolvimento de software em qualquer contexto. O texto apresentado a seguir propõe a construção de um sistema de gerenciamento de clinica genérica. Mesmo o texto seguindo uma linha de raciocínio é possível usar o sumário para obter informações específicas sobre o framework. Espera-se que o leitor possua conhecimentos sobre a linguagem PHP, o sistema gerenciador de banco de dados MySQL e padrão de projeto MVC. Buscou-se utilizar linguagem mais simples possível, fugindo de alguns termos técnicos. O aprofundamento fica para o leitor executar conforme sua necessidade. 1
  • 3. 1. Conhecimentos prévios Para o bom entendimento dos passos descritos neste documento é interessante que o leitor possua conhecimento nos tópicos abaixo: ● Linguagem PHP (conceitos como namespace); ● Orientação a objetos; ● Padrão MVC; ● Projeto de Banco de dados; ● SQL; ● Xampp (ou similar). 2. Proposta de software Para o aprendizado do framework Yii2, propomos o desenvolvimento de um software simples de gerenciamento de consultas de uma clínica médica. O diagrama de banco de dados que será implementado é o apresentado na figura 1: Figura 1: Diagrama Entidade e Relacionamento para o sistema Clínica 3. Ferramentas necessárias As ferramentas necessárias são as mesmas para o desenvolvimento de qualquer sistema na linguagem PHP: ● Ambiente de desenvolvimento: pode ser desde um editor de texto simples, com mais recursos como o ​Visual Studio Code​, ou uma IDE robusta como o ​NetBeans​; ● Servidor PHP. Utilizamos integradores para facilitar a instalação. Nos nossos exemplos utilizamos a ferramenta ​XAMPP na versão 7.2.7. Assim como vários outros, essa ferramenta instala o servidor Apache e também o sgbd MySQL. ● Um SGBD. Nos nossos exemplos utilizamos o MySQL que já é instalado pelo XAMPP. Recomendamos a utilização de uma interface para o gerenciamento da base de dados. O XAMPP já instala o PhpMyAdmin. Sugerimos também a utilização do​ MySQL Workbench​. Os exemplos deste texto foram executados no sistema operacional Windows. As únicas diferenças em relação ao sistema operacional Linux serão na instalação do framework e permissão dos arquivos. Os demais códigos serão independentes de sistema operacional. 2
  • 4. 4. Principais referências sobre o framework Para a construção deste texto foram utilizadas várias referências entre livros, sites, canais do YouTube e fóruns. Abaixo listamos os principais e buscamos, em cada subseção, indicar de onde foi tirado aquele conteúdo. ● Livros: ○ Yii2 By Example: https://www.amazon.com/Yii2-Example-Fabrizio-Caldarelli/dp/1785287419 ● Sites: ○ Referência do framework Yii2: ​https://www.yiiframework.com ○ Yii academy: ​http://www.yiiacademy.com.br/ ● Canais do YouTube: ○ DoingITeasyChannel:  https://www.youtube.com/watch?v=z1xtFbO9jgQ&list=PLRd0zhQj3CBmusDbBzFgg3H20 VxLx2mkF   ○ William Martins: ​https://www.youtube.com/watch?v=WvvrnKaNcas ● E-book: ○ 8 motivos para usar o Yii 2: http://www.yiiacademy.com.br/8-motivos-para-usar-o-yii-2/ 5. Instalação do Yii2 A instalação do Yii2 pode ser realizada de duas formas: via composer ou manualmente. 5.1 Instalação via composer É recomendado que a instalação seja realizada via ferramenta composer. O composer é um gerenciador de dependências do php que facilita a instalação de vários outros componentes e módulos nos projetos a serem construídos. 5.1.1 Instalando o composer Para instalar o composer acesse o link https://www.yiiframework.com/doc/guide/2.0/en/start-installation#installing-via-composer​. Baixe a instalação para windows e a execute. A figura 2 é a tela inicial do instalador. Basta selecionar next em todas as opções que o composer será instalado com sucesso. 3
  • 5. Figura 2 - Tela inicial da instalação do composer. 5.1.2 Instalando o Yii2 via composer O Yii2 possui dois templates: o basic e o advanced. Trabalharemos com a opção basic. Abra o prompt de comando do Windows e localize a pasta acessível pelo servidor web (no caso do Xampp é a pasta c:xampphtdocs). Um comando que pode ser utilizado é o ​cd c:xampphtdocs​. No prompt de comando digite o comando abaixo, observando que a palavra clinica será o nome da pasta do seu projeto. composer create-project yiisoft/yii2-app-basic clinica A instalação demora alguns minutos e vai depender da sua conexão com a internet. A tela de instalação se parecerá com o da figura 3. Figura 3 - Tela parcial de instalação do Yii2 Pronto, seu projeto já está instalado. Abra o navegador no endereço ​http://localhost/clinica/web/​ e já visualize seu projeto em funcionamento. 4
  • 6. 5.2 Instalação manual Para a instalação manual é necessário baixar o pacote de arquivos diretamente do site do yii. Acesse o link ​https://www.yiiframework.com/download​. Procure a sessão “Install from an Archive File” e faça o download da opção “Yii2 with basic application template”. Um arquivo compactado será baixado. Para seu projeto funcionar, crie a pasta ​clinica​(que usaremos nos nossos exemplos) dentro da pasta acessível da web (a htdocs no caso do Xampp). Depois, descompacte o arquivo zipado dentro dessa pasta. Quando a instalação é feita manualmente é necessário fazer a seguinte configuração: ● Abra o arquivo config/web.php e preencha algum valor dentro de ​'cookieValidationKey' => ​'preenchaaqui'​, Pronto, seu projeto já está instalado. Abra o navegador no endereço ​http://localhost/clinica/web/​ e já visualize seu projeto em funcionamento. Essa segunda forma tende a ser mais rápida que via composer, porém, não gerencia as dependências que poderão ser utilizadas posteriormente. Mas, mesmo instalando manualmente, dá para agregar o composer posteriormente. 5.3. Visualização do projeto inicial Ao instalar o Yii2 no seu projeto já é instalado um template pronto (figura 4) como o visualizado ao acessar o link ​http://localhost/clinica/web/​ em um navegador. Figura 4 - Template pronto do Yii2 na instalação básica Abra, em um gerenciador de arquivos, e visualize o que foi instalado dentro da pasta clinica. A figura 5 apresenta as pastas criadas. 5
  • 7. Figura 5 - Pastas criadas dentro da pasta do projeto clinica O Yii2 segue o padrão de projeto Modelo - Visão - Controlador (MVC). As pastas correspondentes são models (Modelo), views (Visão), controllers (Controlador). Serão as pastas mais utilizadas. As demais pastas serão exploradas conforme o sistema for sendo desenvolvido neste texto. 6. Banco de Dados 6.1 Criando o banco de dados Vamos desenvolver o software proposto a partir de um banco de dados já existente. O diagrama do banco de dados é o apresentado na figura ‘ (seção 2). O código SQL referente a esse banco é o que segue abaixo. Execute o código abaixo no seu gerenciador de banco de dados. Nesse exemplo usamos o MySQL e a interface MySQL Workbench. No momento da criação do banco devem ser observados os seguintes detalhes: ● Escrever o código em letras minúsculas; ● Os campos definidos como NOT NULL já serão configurados como obrigatórios nos formulários de inserção; ● Defina as chaves primárias com o nome id; ● As chaves estrangeiras não podem ter os nomes das mesmas tabelas as quais fazem referência, a sugestão é que seja ‘medico_id’, por exemplo. 6
  • 8. CREATE DATABASE clinica; USE clinica; CREATE TABLE IF NOT EXISTS `medico` ( `id` INT(11) NOT NULL, `nome` VARCHAR(200) NULL DEFAULT NULL, `especialidade` VARCHAR(100) NULL DEFAULT 'Clinico Geral', `endereco` VARCHAR(250) NULL DEFAULT NULL, `telefone` CHAR(14) NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB; CREATE TABLE IF NOT EXISTS `paciente` ( `id` INT(11) NOT NULL, `nome` VARCHAR(200) NOT NULL, `endereco` VARCHAR(250) NULL DEFAULT NULL, `nascimento` DATE NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB; CREATE TABLE IF NOT EXISTS `consulta` ( `id` INT(11) NOT NULL, `data` DATE NOT NULL, `horario` TIME NOT NULL, `medico_id` INT(11) NOT NULL, `paciente_id` INT(11) NOT NULL, `valor` DECIMAL(9,2) NULL DEFAULT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`medico_id`) REFERENCES `medico` (`id`), FOREIGN KEY (`paciente_id`) REFERENCES `paciente` (`id`)) ENGINE = InnoDB; 6.2 Configurando uma conexão com o banco de dados O Yii2 oferece uma camada de alto nível para acesso aos bancos de dados construída a partir do PDO (Php Data Objects). O framework permite que a manipulação dos dados das tabelas aconteça a partir de objetos ActiveRecord. Estes objetos encapsulam os métodos para acessar um ou vários registros, assim como filtrar, fazer junção e ordenar dados. É possível trabalhar com banco de dados usando simplesmente código SQL, entretanto, considerando as diferenças entre os diferentes gerenciadores de banco de dados, usar o código SQL perde as facilidades que o Yii2 proporciona [1]. Para configurar uma conexão com o banco abra o arquivo ​clinica/config/db.php e procure pelo trecho de código: <?php return [ 'class' => 'yiidbConnection', 'dsn' => 'mysql:host=localhost;dbname=​clinica​, 'username' => '​root​', 'password' => ​''​, 'charset' => 'utf8', ]; 7
  • 9. Altere os valores dos parâmetros dbname, username e password para os do seu SGBD. Observe que a conexão na propriedade dsn é para o SGBD MySQL. Outra conexões comuns são: ● MySQL and MariaDB: mysql:host=localhost;dbname=mydatabase ● SQLite: sqlite:/path/to/database/file ● PostgreSQL: pgsql:host=localhost;port=5432;dbname=mydatabase ● MS SQL Server (via mssql driver): mssql:host=localhost;dbname=mydatabase ● Oracle: oci:dbname=//localhost:1521/mydatabase 7. Usando o GII O Yii2 possui uma poderosa ferramenta para gerar modelos, controladores, o CRUD (Create, Read, Update e Delete), formulários, módulos e extensões: o Gii. Para acessar esse recurso acesse o link: http://localhost/clinica/web/index.php?r=gii A figura 6 apresenta a tela inicial do Gii. Figura 6 - Tela inicial do Gii Caso essa tela não apareça é preciso habilitar o recurso no projeto. 7.1 Habilitando o Gii Para habilitar esse recurso verifique se os seguintes trechos de código estão presentes nos respectivos arquivos. 8
  • 10. ● Arquivo clinica/config/web.php: no trecho de código abaixo é verificado se o sistema está em ambiente de desenvolvimento e habilita o recurso do Gii e indica qual sua classe. if (YII_ENV_DEV) { // configuration adjustments for 'dev' environment $config['bootstrap'][] = ​'debug'​; $config['modules']['debug'] = 'yiidebugModule'; $config['bootstrap'][] = ​'gii'​; $config['modules']['gii'] = 'yiigiiModule'; } ● Arquivo clinica/web/index.php: nesse arquivo configuramos se o sistema está em produção, em teste ou em desenvolvimento. O valor ​‘dev’ ​indica que o sistema está em desenvolvimento. Para alterar o sistema para teste esse valor deve ser substituído por ‘test’​, e por ​‘prod’​ caso o sistema esteja em produção. defined('YII_ENV') or define('YII_ENV', ​'dev'​); 7.2 Criando modelos Modelos representam a lógica do software e são objetos da classe base ​yiibaseModel​. Essa classe oferece muitas características como os atributos, label dos atributos, atribuições massivas (para preencher atributos de objetos diretamente de um vetor), regras de validação e exportação de dados. Normalmente, em aplicações comuns, um Model é gerado a partir de um banco de dados, extendendo a classe yiidbActiveRecord que implementa o padrão de design Active Record que possui muitos métodos para manipulação de dados. O Yii oferece a ferramenta Gii para gerar automaticamente os modelos do sistema baseado no banco de dados já configurado. Na tela inicial do Gii (​http://localhost/clinica/web/index.php?r=gii​) clique na opção “Start” abaixo do título “Model Generator”. No formulário que é apresentado basta preencher o nome da tabela (que já é carregada a partir do banco de dados configurado). O Model Class Name já é sugerido com o mesmo nome da tabela, porém com a inicial maiúscula, sugere-se que seja mantido, como apresentado na figura 7. Figura 7 - Geração de modelos pelo Gii As demais opções não precisam ser alteradas. Ao clicar em “Preview” é apresentado onde será criado o código (dentro da pasta models) e qual será o nome do arquivo. Clique em Generate para o arquivo ser criado onde foi indicado. Em seguida é apresentada a tela confirmando a criação do arquivo como na figura 8. 9
  • 11. Figura 8 - Criação de modelo a partir do Gii Para facilitar essa tarefa basta escrever “*” no campo TableName que o Gii já gerará todos os modelos de todas as tabelas do banco de dados. Ao clicar em Preview a imagem da figura 9 será apresentada. O Gii indica quais arquivos de modelos serão criados e, no caso de Paciente que já havia sido criado, que não houve alteração nenhuma no arquivo de modelo da tabela paciente. Clique em Generate para efetuar a criação dos modelos. Figura 9 - Geração de modelos usando o Gii Abra a pasta models dentro da pasta do seu projeto (clinica) para visualizar os arquivos criados. Dentro da pasta models são armazenados todos os arquivos relacionados aos modelos, isto é, às classes que manipulam dados dentro da aplicação. Como exemplo, abra o arquivo Paciente.php para analisar seu código. Para todos os modelos o Gii já cria automaticamente: ● Definição dos atributos da tabela; ● Criação da classe extendendo a classe ActiveRecord. ● Função tableName() que retorna o nome da tabela. ● Função rules() que definirá quais são os atributos obrigatórios e outras restrições. ● Função attributeLabels() que retorna o label para cada campo da tabela. Esses labels serão usados para a geração de formulários, coloque o label mais adequado para sua interface. ● Se a tabela estiver do lado 1 de um relacionamento 1:N, é criada uma função getTabelaRelacionada que irá retornar os elementos que se relacionam com determinado item. Usando a tabela cliente como exemplo ela se relaciona com a tabela pedido de 1:N. O Gii gera a função getConsultas() que irá retornar quais são os pedidos de um determinado cliente passado por parâmetro. ● Se a tabela estiver do lado N de um relacionamento 1:N é criada uma função getTabelaRelacionada que irá retornar qual elemento da outra tabela aquele item se relaciona. Usando a tabela pedido como exemplo, ela se relaciona com a tabela Paciente de 1:N (estando do aldo N). O Gii gera a função getPaciente() que irá retornar qual Paciente está relacionada com determinado produto. Esses métodos são gerados automaticamente para agilizar o desenvolvimento. Porém, podem ser alterados conforme a necessidade do seu projeto. 10
  • 12. 7.2.1 Alterando o método Rules() de um modelo O método rules() de cada modelo define quais são as restrições de preenchimento de cada atributo. Essas regras serão usadas para a geração de formulários de inserção e alteração de dados. Caso um campo seja definido como required, no seu respectivo formulário já será apresentado que ele é um campo obrigatório. O Gii já gera o método rules() baseado no banco de dados. Os campos definidos como NOT NULL recebem a regra de required(), os campos de tipo numérico recebem a regra de integer. O formulário que é gerado automaticamente para o CRUD (seção 7.3) também seguirá essas restrições. Um exemplo da função rules [2] é a apresentada abaixo: public​​ ​function​​ ​rules​​() { ​return​​ ​array​​( ​array​​('username, password', 'required'), ​array​​('password_repeat', 'required', 'on'=>'register'), ​array​​('password', 'compare', 'compareAttribute'=>'password_repeat', 'on'=>'register'), ); } A classe Model, que define os modelos, usa o método ​rules() para retornar um vetor com as regras para validação. No vetor principal, cada linha é um outro vetor que declara uma nova regra de validação. Essas regras são aplicadas no método validate() do modelo que retorna verdadeiro ou falso. Por padrão, o método save(), da classe ActiveRecord (que é a responsável por gerenciar os dados do banco de dados), chama o método validate() para proceder a inserção ou alteração dos dados [2]. Em outras palavras, quando um novo objeto for inserido, ou alterado, as regras de validação definidas no método rules() serão testadas. A sintaxe dos vetores internos deve seguir o seguinte: array​​( // mandatory arguments 'attribute list'​, 'validator name'​, // optional parameters 'on'​=>​'scenario name'​, 'message'​=>​'The attribute didn't validate!'​, ...validation parameters... ); ● Attribute list: especifica os atributos, separados por vírgula a serem validados. O mesmo atributo pode aparecer em mais de uma linha. ● Validator name: especifica o validador que será usado. Assim, para cada tipo de validador pode-se agrupar os atributos que possuem aquela regra. ● On: especifica os cenários em que a regra deve ser verificada. Vários cenários podem ser definidos e devem ser separados por vírgula. Caso não seja definido, a regra será aplicada em qualquer cenário. ● Message: substitui a mensagem de erro padrão se o atributo não for validado. Essa mensagem que irá aparecer no formulário se o usuário preencher de forma errada o dado, ou não preencher os campos obrigatório. Os validadores podem ser de três tipos [2]: ● Um método da classe modelo com o mesmo nome do validador especificado, isto é, um método de validação criado pelo programador; 11
  • 13. ● Um validador já embutido no Yii. Todos os validadores do Yii2 extendem a classe CValidator; ● Um caminho para uma classe criada, que extenda o CValidator, e que não é embutida ao Yii. Exemplo da aplicação dos três tipos, tirada de [2]: public​​ ​function​​ ​rules​​(){ return​​ ​array​​( ​array​​('password', 'validateLogin'), // Custom validation method in this object ​array​​('username, password', 'required'), // built-in alias for CRequiredValidator ​array​​('username', 'ext.MyValidators.MyLoginValidator'), // Custom validation class ); } public​​ ​function​​ ​validateLogin​​() { // [...] } Cada objeto de um modelo tem uma propriedade chamada scenario. Alguns cenários já são embutidos do próprio Yii e são atribuídos automaticamente, mas também é possível criar novos. Por exemplo, a leitura de um banco de dados tem um cenario “update”, enquanto um novo registro tem o cenário “insert” [2]. O código abaixo exemplifica esses cenários. $modelA = User::model()->findByPk(1); // $model->scenario = 'update' $modelB = ​new​​ User(); // $model->scenario = 'insert' $modelB->scenario = 'light'; // custom scenario if​​ ($modelB->validate()) { // will only apply rules of the "light" scenario Como mostrado no primeiro exemplo dessa seção as regras podem ser restritas a um específico cenário a partir do parâmetro “on”=>”scenario”. Existe uma grande variedade de validadores do framework Yii. Alguns são listados abaixo. Para cada um desses ainda existem algumas características que podem ser acrescentadas. Para buscar todas as possibilidades sugerimos a consulta do link do ​documento de referência​ e da classe ​CValidator​. ● boolean ● captcha ● compare ● date ○ array(‘org_datetime’,’date’,’format’=>’yyyy-M-d H:m:s’) ● default ● email ● exist ● file ● filter ○ array(‘mycode’,’filter’,’filter’=>’strtoupper’) ● in ● length ● match ● numerical ○ array(‘quantity’,’numerical’,’integerOnly’=>true, ‘min’=>1, ‘max’=>250), ● required ● safe ● type ● unique ● unsafe ● url 12
  • 14. Para exemplificar vamos alterar o método rules do modelo Paciente. Acrescentou-se uma mensagem que será apresentada caso o usuário não preencha o campo e outra caso o usuário preencha um nome com mais de 100 caracteres. Observe o código abaixo: public function rules(){ return [ [['nome'], 'required','message'=>'Preencha o nome do Paciente'], [['nome'], 'string', 'max' => 100,'message'=>'O nome deve ter no máximo 100 caracteres'], ]; } Utilizando as referências citadas acima, e analisando a necessidade do seu usuário final, é possível customizar o modelo como for desejado. 7.3 Usando o Gii para gerar o CRUD O Gii permite a geração automática do CRUD de qualquer modelo já existente. O CRUD corresponde, respectivamente, à inserção (create), consulta (read), atualização (update) e exclusão (delete) de itens do modelo. Acesse a tela inicial do Gii e clique em “Start” abaixo do título “CRUD Generator”. É necessário gerar o CRUD para cada modelo existente um de cada vez. Vamos fazer o primeiro exemplo do CRUD para a tabela Paciente. No formulário que aparece preencha: ● Model Class = “appmodelspaciente”, indica o nome do modelo para o qual será feito o CRUD. É necessário indicar todo o caminho. A palavra app indica o caminho da sua aplicação / projeto. ● Search Model Class = “appmodelsPacienteSearch”. Criará mais um modelo para gerar filtros para o modelo escolhido. A recomendação é colocar o nome do modelo seguido da palavra Search, seguindo o padrão CamelCase. ● Controller Class = “appcontrollersPacienteController”. Criará a classe de Controller relacionada ao modelo indicado dentro da pasta controllers. Também seguir o padrão CamelCase. ● View Path = “@app/views/paciente”. Cria uma pasta Paciente dentro da pasta views que, por sua vez, está dentro da pasta da aplicação (@app). Atenção para quando o controller tiver mais de um nome, por exemplo: NotaFiscalEntrada. A pasta a ser criada deverá se chamar nota-fiscal-entrada. Observe também que as pastas das views são escritas com letras minúsculas. Clique em Preview. Na página que é apresentada aparece a lista da figura 10 mostrando todos os arquivos que serão criados. 13
  • 15. Figura 10 - Arquivos que serão gerados no CRUD de Paciente Clique na opção Generate para geração de todos os arquivos. Faça a mesma coisa para os outros modelos listados anteriormente. Todas as telas de para o CRUD de cada um dos modelos serão criadas e o sistema estará quase pronto. 7.4 Rotas Toda requisição feita a um sistema do padrão MVC aciona um controlador. O controlador analisa a requisição e apresenta a respectiva view. Por exemplo, quando acessamos: http://localhost/clinica/web/index.php?r=paciente estamos chamando um controlador chamado produto e a sua action Index. Na url o nome do controlador sempre iniciará com letra minúscula. O framework procurará um arquivo na pasta controllers com o nome passado no parâmetro “r”, que inicie com letra maiúscula e que tenha o sufixo Controller. No exemplo acima o nome passado pelo parâmetro r é “produto”, o framework irá buscar o arquivo ProdutoController dentro da pasta controller. Dentro do controller existem várias actions, todas iniciadas com o prefixo action e finalizadas com o nome da função em si. Por padrão, a actionIndex() será executada caso nenhuma action seja indicada. No exemplo acima a actionIndex do controlador ProdutoController é executada. Caso se deseje chamar outra action desse controlador basta adicionar o nome da action após o nome do controller na url precedido de “/”. Exemplo: http://localhost/clinica/web/index.php?r=paciente/create A url acima executa a actionCreate do PacienteController que corresponde à view de inserção de um novo paciente. Todos os métodos do controlador que são actionFunção podem ser chamados diretamente via url. Outro exemplo seria quando o nome do controller é composto por mais de uma palavra. Por exemplo o modelo notafiscalentrada. Ao fazermos o CRUD para esse modelo seu controller se chama NotaFiscalEntradaController e sua pasta de views se chama nota-fiscal-entrada. Para acessar esse controller seu nome também deverá ser digitado em letras minúsculas e as palavras separadas por hífens: http://localhost/clinica/web/index.php?r=nota-fiscal-entrada Essa mesma regra se aplica para as actions caso elas possuam mais de uma palavra. 7.5 Analisando os controladores Controllers, são a ponte entre a visão (view) e o modelo (model). São classes que estendem de yiibaseController e são usados para processar requisições e gerar respostas.Controllers possuem principalmente funções cujo nome começa com o prefixo action que permite o framework reconhecer as rotas das funções que podem ser requisitadas. 14
  • 16. Os controladores, dentro da pasta controllers, são o ponto de partida de qualquer função dentro do sistema. A partir deles que são chamados os modelos e visões necessárias para o funcionamento de qualquer função. Os controllers também podem ser criados automaticamente usando a ferramenta Gii a partir de modelos já existentes. O Yii cria os controllers com os seguintes métodos: ● actionCreate() - usado para criar um novo objeto (inserir) do modelo ● actionView() - usado para visualizar os detalhes do objeto do modelo ● actionUpdate() - usado para atualizar um objeto do modelo existente ● actionDelete() - usado para deletar um objeto do modelo existente ● actionIndex() - usado para mostrar, usando um grid, uma lista de objetos do modelo ● behaviors() - método para definir alguns comportamentos, como acesso de usuários, do controlador. Não pode ser acessado via url. ● findModel() - encontra o modelo baseado em um valor de chave primária. Por exemplo, encontra a Paciente de código 1. Se o modelo não for encontrado é retornado o erro http 404. Outras actions podem ser acrescentadas a partir da necessidade do desenvolvedor, assim como as que foram geradas automaticamente podem ser alteradas. Vamos analisar o código das actions criadas a partir do modelo Paciente e localizadas no arquivo controllers/PacienteController.php. 7.5.1 actionIndex() public function actionIndex() { $searchModel = new PacienteSearch(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); return $this->render('index', [ 'searchModel' => $searchModel, 'dataProvider' => $dataProvider, ]); } Essa action pode ser acessada por ​http://localhost/clinica/web/index.php?r=paciente​, ou http://localhost/clinica/web/index.php?r=paciente/index​ . Ela é responsável por apresentar a tela inicial de gerenciamento dos modelos mostrando todos os registros daquele modelo e o que pode ser feito com ele: criar um novo, alterar e excluir os existentes. No código acima ele cria as variáveis $searchModel e $dataProvider que serão responsáveis por compor o GridView na view index. O return renderiza a view index e passa como parâmetro essas duas variáveis. 7.5.2 actionView() public function actionView($id) { return $this->render('view', [ 'model' => $this->findModel($id), ]); } Essa action pode ser acessada por ​http://localhost/clinica/web/index.php?r=Paciente/view&id=1​. Onde id=1 é a chave da Paciente que deseja ser visualizada. 15
  • 17. Essa action recebe como parâmetro a chave do objeto a ser apresentado e renderiza a view chamada ‘view’ passando como parâmetro o próprio (this) modelo daquele id. Em outras palavras, envia para view os dados daquela Paciente selecionada. 7.5.3 actionCreate() public function actionCreate() { $model = new Paciente(); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('create', [ 'model' => $model, ]); } Essa action pode ser acessada pela url ​http://localhost/clinica/web/index.php?r=paciente/create​. Inicialmente é criado um objeto do modelo Paciente. O if seguinte verifica se o usuário clicou no botão salvar, isto é, já preencheu os dados do Paciente e clicou em Salvar. Caso o post tenha sido solicitado e o modelo conseguir ser salvo (lembrando que o método save() busca o método rules() do modelo e valida todos os dados informados), a action redireciona para a view ‘view’ onde mostra os detalhes do registro que acabou de ser inserido. Caso queira redirecionar para outra view, altere essa linha de código. Caso o if retorne falso, isso acontecerá quando a página for carregada e o botão salvar ainda não foi clicado, a action renderiza a view create enviando como parâmetro o modelo. Isso permitirá que o modelo receba os dados que forem preenchidos. 7.5.4 actionUpdate() public function actionUpdate($id) { $model = $this->findModel($id); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('update', [ 'model' => $model, ]); } Essa action pode ser acessada pela url http://localhost/clinica/web/index.php?r=paciente/update&id=1​ . Quase identica a actionCreate(), a actionUpdate se diferencia porque recebe a chave do elemento que se deseja alterar. Ao criar o modelo, primeira linha, não se cria um novo objeto, se busca um já existente com o método findModel. E ao renderizar, ele apresentará a view update, também passando como parâmetro o modelo que foi encontrado. 16
  • 18. 7.5.5 actionDelete() public function actionDelete($id) { $this->findModel($id)->delete(); return $this->redirect(['index']); } Essa action pode ser acessada pela url http://localhost/clinica/web/index.php?r=paciente/delete&id=1​ . A actionDelete recebe como parâmetro a chave do elemento que será excluído. É chamada a função delete(), que é um método da classe ActiveRecord para excluir um registro. Após executado esse código o sistema é redirecionado para a view index. 7.6 Analisando as visões As views apresentam os resultados enviados pelos controllers. Ao usar o Gii para geração do CRUD é criada uma pasta, dentro da pasta views, para aquele controlador. Dentro dessa nova pasta são criadas as seguintes views: ● Create: página de inserção de dados, utiliza o formulário definido em _form; ● Index: apresenta todos os registros do modelo em um gridview e usando um filtro de pesquisa padrão (a partir do _search); ● Update: tela para atualização dos dados, também utiliza o _form; ● View: visualização detalhada de um registro; ● _form: formulário para inserção e alteração dos dados de um modelo; ● _search: formulário para pesquisa de dados, é apresentado acima do gridview. Arquivos de view iniciados com “_” são considerados no Yii2 como subviews, isto é, que são chamadas por outras views. No caso de _form e _search, eles são chamados no arquivo create e update. Os dois arquivos usam o mesmo _form para mostrar campos editáveis. Observe que cada view corresponde a cada ação do controlador. Assim os nomes devem sempre corresponder. Por exemplo: no PacienteController existe a actionIndex. Essa action renderiza uma view chamada index.php. Essa view estará localizada dentro da pasta views/Paciente. Os arquivos sempre iniciam com letras minúsculas. Cada view recebe parâmetros do controlador que são acessadas via código php e possuem códigos html que também podem ser manipulados conforme a necessidade do desenvolvedor. Por padrão o Yii já implementa o framework Bootstrap. As views são inseridas dentro do corpo de um layout pré-definido. Esse layout fica na pasta views/layouts/main.php. Outros layouts podem ser utilizados, assim como o layout padrão pode ser alterado. A seguir apresentamos as views e comentamos os códigos para melhor análise. 7.6.1 _form.php <?php //quais classes serão usadas use yiihelpersHtml; ​//classe responsável por inserir elementos ​HTML use yiiwidgetsActiveForm; ​//widget para inserir um formulário 17
  • 19. /* @var $this yiiwebView */ /* @var $model appmodelsPaciente */ /* @var $form yiiwidgetsActiveForm */ ?> // essa view recebe o modelo ($model) como parâmetro, ou do create.php ou do update.php <div class="paciente-form"> <?php $form = ActiveForm::begin(); ?> ​//abertura do formulário <?= $form->field($model, 'nome')->textInput(['maxlength' => true]) ?> ​//inserção de um campo do tipo text que corresponderá ao campo nome do modelo. O campo texto terá a quantidade máxima definida pela quantidade de caracteres definidas no banco de dados. Nesse exemplo a quantidade é de 100 caracteres. O código html gerado é: <input type="text" id="Paciente-nome" class="form-control" name="Paciente[nome]" maxlength="100" aria-required="true"> A classe que define os campos dos formulários é a ​ActiveField​. <div class="form-group"> <?= Html::submitButton('Salvar', ['class' => 'btn btn-success']) ?> //um botão de submissão é colocado no formulário, em uma div separada, e é definida sua respectiva classe bootstrap </div> <?php ActiveForm::end(); ?> ​//fechamento do formulário </div> 7.6.2 create.php <?php use yiihelpersHtml; /* @var $this yiiwebView */ /* @var $model appmodelsPaciente */ $this->title = 'Create Paciente'; ​//define o título da página $this->params['breadcrumbs'][] = ['label' => 'Pacientes', 'url' => ['index']]; ​//define o 2° breadcrumbs para voltar para o index de Paciente $this->params['breadcrumbs'][] = $this->title; ​//define o último breadcrumb que indica que está no Create Paciente ?> <div class="Paciente-create"> <h1><?= Html::encode($this->title) ?></h1>​//mostra o título da página <?= $this->render('_form', [ 'model' => $model, ]) ?> ​//renderiza o _form enviando o modelo recebido pelo controller. Como é a view de inserção, esse modelo está vazio </div> 18
  • 20. 7.6.3 update.php <?php use yiihelpersHtml; /* @var $this yiiwebView */ /* @var $model appmodelsPaciente */ $this->title = 'Update Paciente: ' . $model->id; ​//define o título da página com o id do elemento que está sendo atualizado $this->params['breadcrumbs'][] = ['label' => 'Pacientes', 'url' => ['index']]; ​//define o 2° breadcrumb com link para o index de Paciente $this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]];​//define o 3° breadcrumb que direciona para a view do elemento que está sendo atualizado $this->params['breadcrumbs'][] = 'Update';​//define o 4° breadcrumb que é a página que está sendo apresentada ?> <div class="paciente-update"> <h1><?= Html::encode($this->title) ?></h1>​//coloca o título da página <?= $this->render('_form', [ 'model' => $model, ]) ?> //renderiza o _form enviando o modelo que foi enviado do controller. Nesse caso o modelo possui os dados da Paciente selecionada </div> 7.6.4 view.php <?php use yiihelpersHtml; use yiiwidgetsDetailView; /* @var $this yiiwebView */ /* @var $model appmodelsPaciente */ $this->title = 'Paciente '.$model->id; $this->params['breadcrumbs'][] = ['label' => 'Pacientes', 'url' => ['index']]; $this->params['breadcrumbs'][] = $this->title; ?> <div class="paciente-view"> <h1><?= Html::encode($this->title) ?></h1> 19
  • 21. <p> <?= Html::a('Update', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?> //insere um link para a view update, passando como parâmetro o id e formatando com a classe do bootstrap <?= Html::a('Delete', ['delete', 'id' => $model->id], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => 'Are you sure you want to delete this item?', 'method' => 'post', ], ]) ?> //insere um link para a view delete, passando como parâmetro o id e formatando com a classe do bootstrap. Além disso pergunta ao usuário se tem certeza que deseja excluir aquele item antes de confirmar a exclusão. </p> //o DetailView é um widget usado para apresentar dados de um modelo <?= DetailView::widget([​//os parametros são 'model' => $model,​//o modelo 'attributes' => [​//quais atributos serão apresentados 'id', 'nome', ], ]) ?>​//para mais detalhes veja a referencia do ​DetailView </div> 7.6.5 _search.php <?php //o _search cria um formulário de busca de registros e mostra o resultado no index. Porém, se o widget GridView for utilizado o código que renderiza essa view é comentado. No momento de gerar o Crud no Gii, se for escolhido o ListView, ao invés do GridView, o _search será renderizado. use yiihelpersHtml; use yiiwidgetsActiveForm; /* @var $this yiiwebView */ /* @var $model appmodelsPacienteSearch */ /* @var $form yiiwidgetsActiveForm */ ?> <div class="Paciente-search"> <?php $form = ActiveForm::begin([ 'action' => ['index'], 'method' => 'get', ]); ?>​//inicia um formulário enviando os dados de busca via get 20
  • 22. <?= $form->field($model, 'id') ?>​//coloca o campo id para filtro <?= $form->field($model, 'nome') ?>​//coloca o campo de nome para o filtro <div class="form-group"> <?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?> <?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?> </div>​//botões de submeter e resetar (ficam omitidos na página) <?php ActiveForm::end(); ?> ​//finaliza o formulário </div> 7.6.6 index.php <?php use yiihelpersHtml; use yiigrid​GridView​;​//Widget para mostrar os dados dentro de um grid (tabela) /* @var $this yiiwebView */ /* @var $searchModel appmodelsPacienteSearch */ /* @var $dataProvider yiidataActiveDataProvider */ $this->title = 'Pacientes'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="Paciente-index"> <h1><?= Html::encode($this->title) ?></h1> <?php // echo $this->render('_search', ['model' => $searchModel]); ?> //a renderização da view _search é comentada para usar o gridview <p> <?= Html::a('Nova Paciente', ['create'], ['class' => 'btn btn-success']) ?> </p>​//link para a view create <?= GridView::widget([​//parametros do GridView 'dataProvider' => $dataProvider,​//seleção de dados criada no Controller 'filterModel' => $searchModel,​//filtros enviados do Controller 'columns' => [ ['class' => 'yiigridSerialColumn'],​//coluna de contagem de linhas 'id',​//colunas do objeto que está sendo apresentado 'nome', 21
  • 23. ['class' => 'yiigridActionColumn'],​//colunas de ações: view, update e delete ], ]); ?> </div> 7.7 Visualizando as funções do sistema Para acessar as diversas funções que já estão funcionando no sistema use as seguintes rotas: ● http://localhost/clinica/web/index.php?r=paciente/index ● http://localhost/clinica/web/index.php?r=paciente/create ● http://localhost/clinica/web/index.php?r=paciente/update&id=1 ● http://localhost/clinica/web/index.php?r=paciente/delete&id=1 ● http://localhost/clinica/web/index.php?r=paciente/view 8. Alterações na Interface 8.1 Alterando o menu principal Agora que já acessamos o sistema via ​http://localhost/clinica/ queremos acessar os CRUD’s criados a partir do menu existente, sem precisar ficar digitando rotas. Iremos acrescentar opções de menu na barra superior referente a cada CRUD que foi criado. Não é a melhor interface que pode ser criada, somente uma sugestão. Abra o arquivo views/layout/main.php e procure pelo seguinte trecho de código: echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 'items' => [ ['label' => 'Home', 'url' => ['/site/index']], ['label' => 'About', 'url' => ['/site/about']], ['label' => 'Contact', 'url' => ['/site/contact']], Acrescente imediatamente abaixo os seguintes itens: ['label' => 'Pacientes', 'url' => ['/paciente/index']], ['label' => 'Médicos', 'url' => ['/medico/index']], ['label' => 'Consultas', 'url' => ['/consulta/index']], Observe que a url corresponde ao controlador e sua actionIndex. 8.2 Views = Create / Update _form 8.2.1 Alterar o título da página Arquivo: create.php Altere a seguinte linha de código para o valor que deseja que seja apresentado. 22
  • 24. $this->title = 'Create Paciente'; Exemplo: $this->title = 'Novo Paciente'; 8.2.2 Campo do tipo data Arquivo: _form.php Na linha de código que insere o campo que tem que ser o tipo de data, acrescente a propriedade ['type'=> 'date']. Exemplo, no cadastro de paciente temos o campo nascimento, o código gerado automaticamente é: <?= $form->field($model, 'nascimento')->textInput() ?> O código para aparecer o formato de data é: <?= $form->field($model, 'nascimento')->textInput(['type'=> 'date']) ?> O código [‘type’=>’date’] pode ser alterado para qualquer tipo existente no HTML5. 8.2.3 Campo do tipo select / dropdown (com dados estáticos) Arquivo: _form.php Para fazer um select, que não busca dados do banco, acrescente a seguinte linha de código no seu formulário. Esse código deve substituir o código criado automaticamente pelo gii para o campo escolhido. No nosso exemplo vamos criar um select para o campo especialidade de médico. Vale observar que o ideal nessa situação é que as especialidades estivessem cadastradas no banco de dados, e não de forma estática como nesse exemplo. <?=​ $form->field($model,​’especialidade’​)->dropDownList( [ '1'​=>​'Clínico Geral', '2'​=>​'Dermatologista', '3'​=>​'Pediatria'​, ], ['prompt' => 'Selecione uma especialidade’] ) ) ​?> O código ​'1'​=>​'Clínico Geral' ​indica que será criado um option no select com o value=1 e o label igual a Pediatria. O que é armazenado no banco de dados é o value, no exemplo, o valor 1. Caso se deseje armazenar o texto, o código deve ser alterado para: ​'Clínico Geral'​=>​'Clínico Geral'. ​Observação: os dados já devem ser colocados na ordem que serão apresentados. 8.2.4 Campo do tipo select / dropdown com dados de outra tabela Fonte: ​Vídeo - aula Arquivo: _form.php No nosso exemplo, ao cadastrar uma nova consulta, deseja-se escolher qual é o paciente será atendido. Os nomes dos pacientes estão na tabela paciente, e a chave estrangeira para eles é que é armazenada na tabela consulta. Para que apareça um select (ou dropdown) com os nomes dos pacientes substitua o código que insere o campo do paciente pelo código abaixo: Código original: <?= $form->field($model, 'medico_id')->textInput() ?> 23
  • 25. Código para gerar o select/dropdown: <?= $form->field($model, 'medico_id')-> dropDownList(ArrayHelper::map(Medico::find() ->orderBy('nome') ->all(),'id','nome'), ['prompt' => 'Selecione um médico']) ?> Ainda, é necessário acrescentar no topo do arquivo as classes que são usadas para fazer esse trecho de código funcionar. Acrescente no início do documento: use yiihelpersArrayHelper; use appmodelsMedico; O que esse código faz? Primeiro, o trecho Medico::find()->orderBy('nome')->all() retorna todos os elementos da classe Medico ordenados pelo campo nome. O retorno desse código é uma lista (vetor) de objetos ActiveQuery. O código ArrayHelper::map(,'id','nome') constrói um mapa (pares de chave-valor) a partir de um vetor dado. No caso o vetor passado é a lista dos fornecedores existentes e os parâmetros ‘id’ e ‘nome’ serão o par chave e valor do novo vetor. O widget dropDownList tem que receber como parâmetro um vetor chave valor para associar às options e valores do select. As chaves serão os values dos options, e os valores seus labels correspondentes. Esse vetor é o que foi criado pela função map. Outro item essencial é adicionar as bibliotecas no topo da view para que o código funcione. Nesse exemplo devem ser adicionadas o endereço da classe ArrayHelper e do modelo Paciente. 8.2.5 Alterar as mensagens de erro do formulário As mensagens de erro são alteradas no método rules() do modelo. Como exemplo temos que o campo nome do paciente é obrigatório. Caso ele não seja preenchido uma mensagem de erro será apresentada. Para alterar a mensagem deve ser colocado o seguinte código no models/Paciente.php: public function rules() { return [ [['nome'], 'required','message'=>'Preencha o nome do paciente',], [['nascimento'], 'safe'], [['nome'], 'string', 'max' => 200], [['endereco'], 'string', 'max' => 250], ]; } Observe que a mensagem de erro deve ser no vetor que informa que o campo é ‘required’. 8.3 Views = View.php 8.3.1 Formatar uma data no detailview Ao visualizar os dados do paciente, por padrão, é apresentada a data no formato americano. Para alterar o formato da data é preciso refazer o código que apresenta o campo, no exemplo, de nascimento. Localize no arquivo view.php (da pasta paciente) o seguinte código: <?= DetailView::widget([ 'model' => $model, 24
  • 26. 'attributes' => [ 'id', 'data', 'horario', 'medico_id', 'paciente_id', 'valor', ], ]) ?> Uma primeira forma de alterar o formato para data é acrescentar a propriedade ‘format’ para o atributo. Além do format também deve ser informado o label e o atributo (ou valor) que será apresentado. <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'id', 'nome', 'endereco', ​[ 'label' => 'Nascimento', 'attribute' => 'nascimento', 'format' => ['date', 'php:d/m/Y'], ] ], ]) ?> O DetailView é um widget que apresenta os dados de um modelo, no exemplo, os dados do paciente. Cada valor apresentado no vetor ‘attributes’ é um campo da tabela paciente. Para formatar a data de nascimento em um formato diferente primeiro deve-se acrescentar o parâmetro formatter (em amarelo), e nos atributos acrescentar ​:date​ ao campo que se deseja alterar o formato. <?= DetailView::widget([ 'model' => $model, ​'formatter' => [ 'class' => 'yiii18nFormatter', 'dateFormat' => 'dd/MM/yyyy', ], 'attributes' => [ 'id', 'nome', 'endereco', ​'nascimento:date', ], ]) ?> 25
  • 27. Outra forma é somente alterar o atributo nascimento substituindo o campo nascimento pelo codigo abaixo: [ 'label'=>'Nascimento', 'value'=> function ($model) { return Yii::$app->formatter->asDateTime($model->nascimento, 'php:d/m/Y'); }, ], Este código define novamente qual será o label do campo e no value é executada uma função que formata o campo do nascimento para o formato d/m/Y do php. 8.3.2 Alterar um valor na visualização (view.php) com if De acordo com nosso exemplo, ao cadastrar um médico selecionamos sua especialidade em um select que foi criado de forma estática (sem buscar no banco de dados). Na view que apresenta os dados do médico, precisamos mostrar o nome da especialidade e não o número dela. Seguindo o exemplo anterior, quando a pessoa escolhe no select colocado o que é guardado no banco é o valor 1, 2 ou 3. No momento de visualizar o registro se deseja traduzir esses números para o nome da especialidade. <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'id', 'nome', 'especialidade', 'endereco', 'telefone', ], ]) ?> Acima é o código original da view.php que apresenta os dados do médico. Vamos alterar o campo especialidade para apresentar os valores pré-definidos. <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'id', 'nome', ​[ 'label'=>'Especialidade', 'value'=>function($model){ if($model->especialidade==1){ return "Pediatria"; } if($model->especialidade==2){ 26
  • 28. return "Clínico Geral"; } if($model->especialidade==3){ return "Dermatologista"; } } ], 'endereco', 'telefone', ], ]) ?> Mais detalhes sobre esse widget podem ser encontrados nos seguintes links: ● https://www.yiiframework.com/doc/guide/2.0/en/output-data-widgets ● https://www.yiiframework.com/doc/api/2.0/yii-widgets-detailview​. 8.3.3 Mostrar um dado de uma outra tabela Ao visualizar a consulta queremos mostrar o nome do médico e o nome do paciente, e não os seus códigos. Para isso é necessário substituir os campos medico_id e paciente_id por outros códigos. Para o médico: [ 'label'=>'Médico', 'attribute'=>'medico.nome', ], Para o paciente [ 'label'=>'Paciente', 'attribute'=>'paciente.nome', ], Caso o campo seja substituído somente por paciente.nome, por exemplo, o label do campo será o do modelo Paciente. Por isso é necessário redefinir o label para cada um dos campos. 8.3.4 Alterar mensagem de exclusão No arquivo view.php é possível alterar a mensagem que é apresentada ao usuário caso ele clique no botão ‘Delete’. Basta procurar pelo código abaixo e substituir a mensagem marcada em amarelo. <?= Html::a('Delete', ['delete', 'id' => $model->id], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => '​Are you sure you want to delete this item?​', 'method' => 'post', ], ]) ?> 27
  • 29. 8.4 Views = Index.php 8.4.1 Formatar uma data no gridview O gridview é o widget utilizado no index.php e apresenta vários recursos para sumarização dos dados. Por padrão ele seleciona todos os registros da tabela que são carregados na variável $dataProvider, o recurso de busca no início de cada coluna, e as funções de visualizar, excluir e alterar para cada registro. Assim como no detailview, o gridview também mostra o formato de data no formato americano. Para alterar o formato basta substituir o campo desejado pelo código abaixo: [ 'attribute'=> 'nascimento', 'format' => ['date', 'php:d/m/Y'], ], 8.4.2 Alterar um valor no index.php com if No nosso exemplo, ao buscar a especialidade do médico é retornado valores numéricos e não o nome da especialidade. Como os valores são estáticos, é preciso fazer um if para verificar o valor do número retornado. O código do gridview fica da seguinte forma: <?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yiigridSerialColumn'], 'id', 'nome', ​[ 'label'=>'Especialidade', 'attribute'=>'especialidade', 'value'=>function($model){ if($model->especialidade==1){ return "Pediatria"; } if($model->especialidade==2){ return "Clínico Geral"; } if($model->especialidade==3){ return "Dermatologista"; } }, 'format' => 'html', 'filter' => [1 => 'Pediatria', 2 => 'Clínico Geral', 3 => 'Dermatologista'], ], 'endereco', 'telefone', 28
  • 30. ['class' => 'yiigridActionColumn'], ], ]); ?> 8.4.3 Mostrar um dado de uma outra tabela na view index.php Ao visualizar as consultas são retornados os códigos dos médicos e paciente. Os nomes, que seria o adequado de ser apresentado, estão em suas respectivas tabelas. Para apresentar o nome destes itens deve-se fazer as alterações a seguir. O primeiro passo é substituir ​‘medico_id’ ​por: [ 'attribute'=>'medico.nome', 'label'=>'Médico', 'filter'=>ArrayHelper::map(Medico::find()->asArray()->all(),'id', 'nome'), ], Ao visualizar o resultado observe que a coluna Medico está com a ordenação e o filtro desabilitados. É necessário alterar o modelo ConsultaSearch para adicionar essas funcionalidades. Abra o respectivo arquivo e adicione os códigos que estão grifados em amarelo: <?php namespace appmodels; use Yii; use yiibaseModel; use yiidataActiveDataProvider; use appmodelsConsulta; /** * ConsultaSearch represents the model behind the search form of `appmodelsConsulta`. */ class ConsultaSearch extends Consulta { /** * {@inheritdoc} */ ​public function attributes() { // add related fields to searchable attributes return array_merge(parent::attributes(), ['medico.nome','paciente.nome']); } public function rules() { return [ [['id'], 'integer'], ​//os campos medico_id e paciente_id foram retirados [['data', 'horario',​'medico.nome','paciente.nome'​], 'safe'], [['valor'], 'number'], ]; } /** * {@inheritdoc} */ public function scenarios() { // bypass scenarios() implementation in the parent class return Model::scenarios(); } 29
  • 31. /** * Creates data provider instance with search query applied * * @param array $params * * @return ActiveDataProvider */ public function search($params) { $query = Consulta::find(); // add conditions that should always apply here $dataProvider = new ActiveDataProvider([ 'query' => $query, ]); ​ $query->joinWith(['medico']); $dataProvider->sort->attributes['medico.nome']=[ 'asc'=>['medico.nome'=>SORT_ASC], 'desc'=>['medico.nome'=>SORT_DESC], ]; $query->joinWith(['paciente']); $dataProvider->sort->attributes['paciente.nome']=[ 'asc'=>['paciente.nome'=>SORT_ASC], 'desc'=>['paciente.nome'=>SORT_DESC], ]; $this->load($params); if (!$this->validate()) { // uncomment the following line if you do not want to return any records when validation fails // $query->where('0=1'); return $dataProvider; } // grid filtering conditions $query->andFilterWhere([ 'id' => $this->id, 'data' => $this->data, 'horario' => $this->horario, 'medico_id' => $this->medico_id, 'paciente_id' => $this->paciente_id, 'valor' => $this->valor, ]); ​$query->andFilterWhere(['=', 'medico.id',$this->getAttribute('medico.nome')]); $query->andFilterWhere(['=', 'paciente.id',$this->getAttribute('paciente.nome')]); return $dataProvider; } } 30