Mini-Crud com CodeIgniter 3 e Bootstrap

Olá. Hoje você vai aprender a fazer um mini-crud com o CodeIgniter 3 e Bootstrap.

Se você não sabe o que é CRUD eu explico, signica: Create, Retrieve, Update, Delete. Ou seja, é basicamente o que todo sistema que trabalha com banco de dados deve ter.

No post de hoje eu mostro como que você pode fazer um CRUD básico usando o CodeIgniter 3.0 e também o Bootstrap.

Inclusive, eu uso o modal de confirmação do Bootstrap para perguntar ao usuário se ele deseja excluir o registro.

Autoload

O primeiro passo é configurarmos o CodeIgniter devidamente para carregar automaticamente algumas bibliotecas.

Abra o arquivo application/config/autoload.php e mude a linha 63 para carregar automaticamente o banco de dados.

$autoload['libraries'] = array('database');

Vamos precisar também de alguns helpers, então, deixe a linha 91 como segue abaixo:

$autoload['helper'] = array('url', 'html', 'form');

E por último, vamos pedir ao CodeIgniter para sempre carregar o model que é responsável pelas transações com o Banco de Dados. Neste caso, é a última linha, a 140:

$autoload['model'] = array('m_cadastros');

Feito, neste arquivo não precisamos mais mexer, pode salvar as alterações e fechá-lo.

Configurações

Neste arquivo vamos apenas mudar o idioma do CodeIgniter para português. Para isto, vá até a linha 74 e deixe assim:

$config['language'] = 'portuguese-brazilian';

Lembrando que você deve ter esta pasta dentro do diretório application/languages para que isto funcione. No download no final do post, o CodeIgniter já vem traduzido.

A tradução é referente às mensagens de erro na validação do formulário e algumas outras coisas a mais.

Pode salvar e fechar o arquivo.

Banco de Dados

Abra o arquivo application/config/database.php e configure o seu banco de dados. Neste caso, ficou assim:

$active_group = 'default';
$query_builder = TRUE;

$db['default'] = array(
	'dsn'	=> '',
	'hostname' => 'localhost',
	'username' => 'root',
	'password' => '',
	'database' => 'mini-crud',
	'dbdriver' => 'mysqli',
	'dbprefix' => '',
	'pconnect' => FALSE,
	'db_debug' => TRUE,
	'cache_on' => FALSE,
	'cachedir' => '',
	'char_set' => 'utf8',
	'dbcollat' => 'utf8_general_ci',
	'swap_pre' => '',
	'encrypt' => FALSE,
	'compress' => FALSE,
	'stricton' => FALSE,
	'failover' => array(),
	'save_queries' => TRUE
);

Salve e feche o arquivo.

Rotas

Por último, vamos alterar o nome do controller padrão que o CodeIgniter irá carregar ao ser iniciado. Abra o arquivo em application/config/routes.php e altere a linha 52 como segue abaixo:

$route['default_controller'] = 'home';

Salve e feche o arquivo.

Muito bem, dentro da pasta application/config não precisamos mais fazer nada.

Controllers

O sistema tem 2 controllers. Um chamado Home.php que carrega a página inicial com os registros do banco de dados e outro controller chamado Cadastro.php que tem as funções que serão responsáveis por tratar as requisições do navegador e também inserir e recuperar os registros do model.

O controller Home.php tem somente um método. Veja;

class Home extends CI_Controller {

	/**
	 * Método principal do mini-crud
	 * @param nenhum
	 * @return view
	 */
	
	public function index()
	{
		
		$variaveis['cadastros'] = $this->m_cadastros->get();
		$this->load->view('v_home', $variaveis);
	}
}

Este método simplesmente recupera todos os registros cadastrados no banco através do método get() dentro do model, e passa isso para a view.

O controller Cadastro.php é um pouco maior e tem 4 métodos.

  • create()
  • store()
  • edit()
  • delete()

Método create()

Este método tem como função apenas chamar o formulário para a inserção dos dados no banco e também alterar o título da página, pois estou usando o mesmo formulário tanto pra inserir quando pra editar os dados, assim, dependendo de onde vier a requisição, altero o título da página. Veja o código:

	/**
	 * Carrega o formulário para novo cadastro
	 * @param nenhum
	 * @return view
	 */
	public function create()
	{
		$variaveis['titulo'] = 'Novo Cadastro';
		$this->load->view('v_cadastro', $variaveis);
	}

Método store()

Este é o local para onde o formulário irá fazer o post. Aqui devemos fazer a validação dos dados e em seguida enviá-los para o model fazer a inserção no banco de dados. Veja o código:

	/**
	 * Salva o registro no banco de dados.
	 * Caso venha o valor id, indica uma edição, caso contrário, um insert.
	 * @param campos do formulário
	 * @return view
	 */
	public function store(){
		
		$this->load->library('form_validation');
		
		$regras = array(
		        array(
		                'field' => 'nome',
		                'label' => 'Nome',
		                'rules' => 'required'
		        ),
		        array(
		                'field' => 'telefone',
		                'label' => 'telefone',
		                'rules' => 'required'		                
		        ),
		        array(
		                'field' => 'email',
		                'label' => 'E-mail',
		                'rules' => 'required|valid_email'
		        ),
		        array(
		                'field' => 'observacoes',
		                'label' => 'Observações',
		                'rules' => 'required'
		        )
		);
		
		$this->form_validation->set_rules($regras);

		if ($this->form_validation->run() == FALSE) {
			$variaveis['titulo'] = 'Novo Registro';
			$this->load->view('v_cadastro', $variaveis);
		} else {
			
			$id = $this->input->post('id');
			
			$dados = array(
			
				"nome" => $this->input->post('nome'),
				"telefone" => $this->input->post('telefone'),
				"email" => $this->input->post('email'),
				"observacoes" => $this->input->post('observacoes')
			
			);
			if ($this->m_cadastros->store($dados, $id)) {
				$variaveis['mensagem'] = "Dados gravados com sucesso!";
				$this->load->view('v_sucesso', $variaveis);
			} else {
				$variaveis['mensagem'] = "Ocorreu um erro. Por favor, tente novamente.";
				$this->load->view('errors/html/v_erro', $variaveis);
			}
				
		}
	}

O primeiro passo é carregarmos a biblioteca de validação do CodeIgniter através da linha:

$this->load->library('form_validation');

Em seguida, definimos as regras através de um array. Esta configuração indica que todos os campos serão de preenchimento obrigatório e além disso, também é feita a validação do e-mail. Veja:

$regras = array(
		        array(
		                'field' => 'nome',
		                'label' => 'Nome',
		                'rules' => 'required'
		        ),
		        array(
		                'field' => 'telefone',
		                'label' => 'telefone',
		                'rules' => 'required'		                
		        ),
		        array(
		                'field' => 'email',
		                'label' => 'E-mail',
		                'rules' => 'required|valid_email'
		        ),
		        array(
		                'field' => 'observacoes',
		                'label' => 'Observações',
		                'rules' => 'required'
		        )
		);

Em seguida, atribuo esta configuração à biblioteca form_validation através da linha:

$this->form_validation->set_rules($regras);

A validação consiste em analisar o resultado desta linha:

$this->form_validation->run() == FALSE

Caso ela retorne FALSE, então indica que houve algum problema na validação e a tela de cadastro é mostrada novamente ao usuário.

Caso contrário, prosseguimos com a inserção no banco de dados.

Nos códigos seguinte eu recupero via post os campos que vêm do formulário, inclusive o campo id, que é responsável por me indicar se o usuário está fazendo uma inserção ou uma edição do registro no banco de dados.

Então, vinculo os valores aos seus respectivos campos através da array $dados e envio para o método store() dentro do model m_cadastros.

Este método retornará TRUE caso os dados tenham sido inseridos com sucesso e FALSE caso ocorra algum erro.

Dependendo do retorno, eu chamo uma view de resposta correspondente, que pode ser v_sucesso.php ou v_erro.php, que está dentro da pasta errors na pasta views.

Método edit()

Este método tem como função chamar o formulário e preencher os campos para que o usuário faça a edição.

Quando este método é chamado, é preciso informar o ID do registro que pretende ser editado, e com este ID em mãos, faço uma busca no banco de dados e o passo como parâmetro, para que seja retornado somente um registro.

/**
	 * Chama o formulário com os campos preenchidos pelo registro selecioando.
	 * @param $id do registro
	 * @return view
	 */
	public function edit($id = null){
		
		if ($id) {
			
			$cadastros = $this->m_cadastros->get($id);
			
			if ($cadastros->num_rows() > 0 ) {
				$variaveis['titulo'] = 'Edição de Registro';
				$variaveis['id'] = $cadastros->row()->id;
				$variaveis['nome'] = $cadastros->row()->nome;
				$variaveis['telefone'] = $cadastros->row()->telefone;
				$variaveis['email'] = $cadastros->row()->email;
				$variaveis['observacoes'] = $cadastros->row()->observacoes;
				$this->load->view('v_cadastro', $variaveis);
			} else {
				$variaveis['mensagem'] = "Registro não encontrado." ;
				$this->load->view('errors/html/v_erro', $variaveis);
			}
			
		}
		
	}

Repare que para recuperar a informação de somente um campo, usa-se a função row()->nome_do_campo do CodeIgniter.

Quando você for usar a função row()->nome_do_campo é sempre importante que você verifique antes se existe algum registro, caso contrário um erro será gerado. Por isso, no IF eu verifico se algum dado foi retornado do banco, caso sim, recupero as informações do cadastro, caso não, carrego a view de erro.

Em seguida, vinculo o valor de cada campo em sua respectiva variável e passo para a view.

Aqui existe uma etapa importante. Repare que devo passar obrigatoriamente para a view o ID do registro, para que quando o formulário for postado, a existência desta informação indique é uma edição e não uma inserção.

Vou explicar melhor isso quando analisarmos o formulário.

Método delete()

Este é o último método deste controller. Ele simplesmente solicita a exclusão ao model do registro passado como parâmetro, e retorna TRUE ou FALSE dependendo do resultado.

Caso retorne TRUE, envio uma mensagem de sucesso ao usuário.

Models

O sistema possui apenas um model que faz as transações com a tabela cadastros. O model se chama M_cadastros.

Eu gosto de colocar a letra na frente do model ou da view para facilitar a localização dos arquivos na minha IDE, já que estes nomes de arquivos não irão aparecer no navegador.

Dentro do model há 3 métodos: store(), get() e delete()

Método store()

Este método tem como função salvar os registros na tabela. Repare que falei salvar, não falei inserir ou atualizar, pois este método faz as duas coisas.

Por isso que é importante o valor do ID no formulário. Caso o ID seja passado, entendo que será um UPDATE, caso contrário faço um INSERT.

Eu acho isso realmente uma mão na roda, pois facilita muito e economiza código. Com somente um método você consegue resolver as duas situações. Veja o código:

	/**
	 * Grava os dados na tabela.
	 * @param $dados. Array que contém os campos a serem inseridos
	 * @param Se for passado o $id via parâmetro, então atualizo o registro em vez de inseri-lo.
	 * @return boolean
	 */
	public function store($dados = null, $id = null) {
		
		if ($dados) {
			if ($id) {
				$this->db->where('id', $id);
				if ($this->db->update("cadastros", $dados)) {
					return true;
				} else {
					return false;
				}
			} else {
				if ($this->db->insert("cadastros", $dados)) {
					return true;
				} else {
					return false;
				}
			}
		}
		
	}

Sempre que este método for chamado, deve-se obrigatoriamente passar os campos através do parâmetro $dados. Repare que se existir algo dentro do parâmetro $id, faço o update, tomando o cuidado de usar a cláusula WHERE no banco de dados, se não todos os registros seriam atualizados, e em seguida uso o comando UPDATE para atualizar os registros.

Caso o parâmetro $id esteja vazio, simplesmente faço um INSERT  dos valores contidos em $dados na tabela.

Método get()

Este método apenas retorna os registros do banco de dados. Ele recebe o parâmetro $id, que se for passado, entendo que está sendo solicitada a informação de somente um registro. Caso não seja passado, então retorno todos os registros ordenando pelo campo id.

	/**
	 * Recupera o registro do banco de dados
	 * @param $id - Se indicado, retorna somente um registro, caso contário, todos os registros.
	 * @return objeto da banco de dados da tabela cadastros
	 */
	public function get($id = null){
		
		if ($id) {
			$this->db->where('id', $id);
		}
		$this->db->order_by("id", 'desc');
		return $this->db->get('cadastros');
	}

Método delete()

Este método simplesmente exclui um registro do banco de dados. É obrigatória a passagem do parâmetro $id que informa qual registro será excluído.

	/**
	 * Deleta um registro.
	 * @param $id do registro a ser deletado
	 * @return boolean;
	 */
	public function delete($id = null){
		if ($id) {
			return $this->db->where('id', $id)->delete('cadastros');
		}
	}

Views

O sistema possui 4 views: v_cadastro.php, v_home.php, v_sucesso.php e v_erro.php que está dentro da pasta errors/html.

View v_home.php

Esta é a view principal do sistema, que mostra os registros cadastrados no banco de dados.

Uma etapa importante nesta view é a parte de exclusão do registro, pois é onde eu uso o modal do bootstrap para o usuário deletar um cadastro.

Esta é  uma etapa bem crítica, pois, para fins didáticos, decidi mostrar no modal o nome da pessoa que está sendo excluída e pra fazer isso funcionar, tive que usar a função data() do jquery.

O funcionamento da função data() é bem simples de entender. Basicamente esta função vincula a um objeto no DOM o valor de alguma variável que você deseja recuperar depois. É como se ele pendurasse a informação e depois você pudesse recuperá-la.

Seu funcionamento é basicamente assim. Para atribuir um valor eu digito:

 $('#objeto').data("nome", "valor");

E para recuperar este valor, basta eu digitar assim:

var nome = $('#objeto').data("nome");

Com isso, eu consigo passar a informação para qualquer lugar do meu HTML.

Para fazer a exclusão do registro, eu preciso de 2 valores do banco de dados. O primeiro é nome da pessoa que está sendo excluído, que será mostrado na janela modal, e o segundo é o ID do registro, para que eu possa excluí-lo no banco de dados.

Vamos analisar a linha que gera o link Excluir na tabela onde os registros são mostrados:

<a href="#" class='confirma_exclusao' data-id="<?= $cadastro->id ?>" data-nome="<?= $cadastro->nome ?>" />Excluir</a>

Repare que neste link eu vinculo uma classe chamada “confirma_exclusao” que neste caso tem a função de somente ser um meio de transporte das variáveis.

Depois, através dos atributos data-id e data-nome, eu vinculo à classe “confirma_exclusao” os valores que preciso para poder recuperar posteriormente via java-script.

Vamos analisar agora os códigos JavaScript responsáveis por fazer as coisas funcionarem:

var base_url = "<?= base_url(); ?>";

Nesta linha eu apenas vinculo à uma variável global no javascript o endereço base do meu sistema, para facilitar a criação dos caminhos.

$('.confirma_exclusao').on('click', function(e) {
			    e.preventDefault();
			    
			    var nome = $(this).data('nome');
			    var id = $(this).data('id');
			    
			    $('#modal_confirmation').data('nome', nome);
			    $('#modal_confirmation').data('id', id);
			    $('#modal_confirmation').modal('show');
			});

Esta é a linha onde a mágica acontece.

Eu vinculo à classe “confirma_exclusao” o evento click do mouse. Quando alguém clica no link, eu evito que o link seja seguido através da função:  e.preventDefault(), assim a página não será carregada quando alguém clicar no link Excluir.

Em seguida eu recupero o valor de cada parâmetro criado dentro do link através das linhas:

 var nome = $(this).data('nome');
 var id = $(this).data('id');

Repare que estou usando this para acessar o método data(), pois estou dentro do escopo que faz referência à classe “confirma_exclusao”.

Com isto eu vinculo às variáveis nome e id os valores que preciso.

Em seguida eu uso novamente a função data(), mas agora pra vincular estas informações à janela modal exatamente como mostrei no exemplo a algumas linhas acima.

Depois de fazer a vinculação, mostro a janela modal através da função: modal(‘show’);

O código abaixo é responsável por monitorar um evento da janela modal, neste caso ‘show.bs.modal’ que é disparado assim que a janela é aberta.

Com isto, eu consigo preencher com o nome do usuário um bloco dentro da janela modal, e assim mostrar ao usuário qual registro ele está excluindo.

			$('#modal_confirmation').on('show.bs.modal', function () {
			  var nome = $(this).data('nome');
			  $('#nome_exclusao').text(nome);
			});

E a última função é a que realmente faz a exclusão do registro:

$('#btn_excluir').click(function(){
				var id = $('#modal_confirmation').data('id');
				document.location.href = base_url + "index.php/cadastro/delete/"+id;
			});

Nesta linha vinculo função click no botão excluir, que é o botão vermelho que aparece na janela modal, que quando clicado simplesmente chama uma URL que invoca o método delete dentro do controller cadastro, passando como parâmetro o id do registro.

View v_cadastro.php

Esta view é a que tem dupla função, pois é a view que traz o formulário tanto pra inserção quanto pra edição do registro.

Repare que há alguns códigos PHP dentro deste HTML.

O primeiro código é o que aparece ao lado de cada label, que tem como função mostrar o erro de campo não preenchido, que quem controla é o form_validation do CodeIgniter.

Assim, quando o usuário não preenche os campos requeridos, o erro é mostrado ao lado de cada campo.

Note também o atributo value dentro de cada campo. Ali existem dois operadores ternários do PHP, um dentro do outro.

O motivo de fazer isto é o seguinte: a biblioteca form_validation do CodeIgniter tem uma funcionalidade de repopular os campos já preenchidos quando o formulário é recarregado em caso de erro do usuário que esqueceu de preencher algum outro campo.

Esta funcionalidade é acessada através da função set_value(‘nome_do_campo’) que deve ser colocada dentro do atributo value de cada campo.

O problema é que no caso de uma edição de registro, eu também devo preencher o atributo value do cada campo com o seu valor respectivo, porém como já existe a função set_value() ali dentro, ocorreu este problema.

O que fiz então foi o seguinte: Dentro do atributo value eu faço duas verificações: se existir algo dentro da função set_value() então eu a mostro, caso contrário eu verifico então se existe uma variável chamada $nome, para o caso do campo Nome. Se existir então a imprimo, caso não, imprimo um valor vazio.

No modelo tradicional o código seria assim:

if (set_value('nome')) {
  echo set_value('nome');
} elseif(isset($nome)){
  echo $nome;
} else
  echo "";

O código acima pode ser resumido da seguinte maneira:

set_value('nome') ? : (isset($nome) ? $nome : '')

Se você não está familiarizado com operadores ternários, clique aqui.

Veja como o tamanho da economia que ele gera.

Um item importante nesta view é o campo do tipo hidden que armazena o ID do registro.

É ele que é responsável por informar ao sistema ser o registro está sendo editado ou se um novo está sendo inserido.

Quando eu chamo a v_cadastro através do botão Editar, eu também preencho este campo hidden com o ID do registro, pois quando o usuário postar os dados, ele irá junto no post.

Então, dentro do controller eu verifico se está vindo algum valor pelo campo ID. Caso esteja, então entendo que é uma edição, caso não, entendo que é uma inserção como já expliquei lá em cima.

E por último, mas também importante é a variável $titulo que tem como função apenas mudar o titulo da página de acordo com o link que a está chamando, que pode ser Novo Registro ou Edição de Registro.

View v_sucesso.php

A última view do sistema é uma página que simplesmente mostra uma mensagem ao usuário.

Aqui não tem nada de mais, é basicamente uma página HTML comum onde há uma variável PHP que é preenchida com a mensagem de erro quando a view é chamada.

A v_erro.php funciona da mesma maneira, porém, está dentro da pasta errors/html.

Quando finalizar o seu sistema e colocá-lo em produção, não se esqueça de acessar o arquivo index.php na raiz do CodeIgniter e alterar o conteúdo da linha 56 para production, assim os erros mais graves não irão aparecer ao usuário.

Abaixo você pode baixar o código fonte do sistema e também testá-lo funcionando.

Clique aqui para testar o mini-crud com CodeIgniter 3.0

Clique aqui para baixar o código fonte.

Espero que o post tenha sido útil, um grande abraço.

Fábio

Fábio S. Reszko

Sou Programador PHP desde 2006 e eu acredito sinceramente que programar usando um Framework PHP é a solução para os problemas de códigos desorganizados, difíceis de entender e de dar manutenção no futuro. Se você também acredita nisto, então fique à vontade em explorar meu blog.