Neste tutorial vamos criar um pequeno #sistema #crud de gerenciamento de #tarefas mais conhecido como #todolist utilizando o Codeigniter 4 (CI4), Mysql e #Boostrap 5. Vamos, também, fazer algumas validações no client side e no server side utilizando a biblioteca validation do CI4.
Para acessar o código fonte: https://www.codesnippets.dev.br/post/crud-bootstrap-5-mysql-e-codeigniter-4-lista-de-tarefas-download
Se você deseja ir para a parte 2 - CRUD Codeigniter 4 - Parte 2
Não colocaremos nossos códigos no diretório /app, para isso vamos montrar uma estrutura de módulos.
Ex. modules/auth modules/todo, modules/main.
Nossos endereços terão este formato: http://localhost:8080/todo/tasks
A versão utilizado no Tutorial é 4.3.6 => https://www.codeigniter.com/user_guide/changelogs/v4.3.6.html
Depois que você instalou o CI4 no seu ambiente faça as seguintes alterações utilizando seu editor preferido.
2 - Dentro de modules, crie Auth e Todo (aqui ficará nossa área protegida por filters)
3 - Dentro de Auth coloque a estrutura (controller model e view) padrão do CI4. Vamos utilizar este módulo para a parte de login e logout.
4 - Dentro de Todo crie os seguintes diretórios, cada um com a estrutura padrão sugerida. Nesta parte a diferença é que dentro de Config teremos o arquivo Routes.php, onde configuraremos as rotas. Repita a estrutura acima (Controllers, Models e Views) para cada uma (Não para a Config).
Dashboard, Main e Tasks terão a mesma estrutura que Auth.
Agora nós vamos fazer alguns ajustes para fazer os testes iniciais.
Acesse app/Config/App.php e faça os ajustes conforme se ambiente e endereço do seu sistema
app/Config/App.php
public string $baseURL = 'http://localhost/curso-ci4/curso-todo/public/';
// retire index.php
public string $indexPage = '';
Se você estiver utilizando o arquivo .env faça os ajustes necessários colocando o ambiente para o modo desenvolvimento.
CI_ENVIRONMENT = development
E aproveite para ajustar outras configurações como baseURL e dados de conexão com o banco de dados. Vamos utilizar o #Mysql
app.baseURL = ''
// descomente as linhas abaixo e insira as informações pedidas conforme a sua conexão
database.default.hostname = localhost
database.default.database = ci4_todo_list
database.default.username = root
database.default.password = root
database.default.DBDriver = MySQLi
database.default.DBPrefix =
database.default.port = 3306
Vamos fazer uma simples configuração de filters e rotas para nos ajudar na navegação do sistema.
Acesse app/Filters/ e crie um arquivo #php chamado MyFilter.php.
Essa PRIVATE_KEY é opcional, mas pode ser criada em app/Config/Constants.php
/*
|
|Key única para checagem no login
*/
define('PRIVATE_KEY', '321daDsd3w505eDwFq5eswq5eqx065H');
Conteúdo do before em app/Filters/MyFilter.php
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class MyFilter implements FilterInterface
{
public $ip;
private $auth;
public function before(RequestInterface $request, $arguments = null)
{
$this->auth = service('session')->get();
$this->ip = $request->getIPAddress();
if (!$this->isLoggedIn() or ($this->auth['key'] != PRIVATE_KEY) or ($this->ip != $this->auth['ip_login'])) {
service('session')->destroy();
return redirect()->to(base_url('auth/logout'));
}
}
// --------------------------------------------------------------------
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Do something here
}
/**
* Checks whether a user is logged in.
*
* @return bool if a user is logged in
*/
private function isLoggedIn(): bool
{
if (!isset($this->auth['isLoggedIn']) or !isset($this->auth['ip_login'])) {
return false;
}
return (null !== $this->auth['isLoggedIn'] && $this->auth['userData'] !== null && $this->ip === $this->auth['ip_login']);
}
}
Acesse app/Config/Filters.php e configure como mostra este código.
Estamos chamando o nosso filtro use \App\Filters\MyFilter;
Criando um alias para ele 'auth' => MyFilter::class,
E utilizando antes todas as rotas todo 'auth' => ['before' => ['todo*']],
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
use CodeIgniter\Filters\InvalidChars;
use CodeIgniter\Filters\SecureHeaders;
use \App\Filters\MyFilter;
class Filters extends BaseConfig
{
/**
* Configures aliases for Filter classes to
* make reading things nicer and simpler.
*/
public array $aliases = [
'auth' => MyFilter::class,
'csrf' => CSRF::class,
'toolbar' => DebugToolbar::class,
'honeypot' => Honeypot::class,
'invalidchars' => InvalidChars::class,
'secureheaders' => SecureHeaders::class,
];
/**
* List of filter aliases that are always
* applied before and after every request.
*/
public array $globals = [
'before' => [
// 'honeypot',
// 'csrf',
// 'invalidchars',
],
'after' => [
'toolbar',
// 'honeypot',
// 'secureheaders',
],
];
/**
* List of filter aliases that works on a
* particular HTTP method (GET, POST, etc.).
*
* Example:
* 'post' => ['foo', 'bar']
*
* If you use this, you should disable auto-routing because auto-routing
* permits any HTTP method to access a controller. Accessing the controller
* with a method you don’t expect could bypass the filter.
*/
public array $methods = [];
/**
* List of filter aliases that should run on any
* before or after URI patterns.
*
* Example:
* 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
*/
public array $filters = [
'auth' => ['before' => ['todo*']],
];
}
<?php
namespace Config;
// Create a new instance of our RouteCollection class.
$routes = Services::routes();
/*
* --------------------------------------------------------------------
* Router Setup
* --------------------------------------------------------------------
*/
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->setAutoRoute(false); // Vamos utilizar rotas definidas
if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
/**
* --------------------------------------------------------------------
* Definições de rotas em \Modules\Todo\Config
* --------------------------------------------------------------------
*/
if (file_exists(ROOTPATH . 'modules')) {
$modulesPath = ROOTPATH . 'modules/';
$modules = scandir($modulesPath);
foreach ($modules as $module) {
if ($module === '.' || $module === '..')
continue;
if (is_dir($modulesPath) . '/' . $module) {
$routesPath = $modulesPath . $module . '/Config/Routes.php';
if (file_exists($routesPath)) {
require($routesPath);
} else {
continue;
}
}
}
}
Acesse modules/Todo/Config/Routes.php e insira este código.
<?php
// Páginas fora do controle de login
$routes->group('/', ['namespace' => '\Modules\Auth\Controllers'], function ($routes) {
$routes->get('', 'Auth::index');
$routes->group('auth', function ($routes) {
$routes->get('', 'Auth::index');
// login e logout
$routes->get('logout', 'Auth::logout');
$routes->get('login', 'Auth::login');
});
});
// rotas protegidas
$routes->group('todo', ['namespace' => '\Modules\Todo'], function ($routes) {
// painel principal
$routes->get('/', 'Dashboard\Controllers\Dashboard::index');
$routes->get('dashboard', 'Dashboard\Controllers\Dashboard::index');
// nossa lista de tarefas
$routes->group('tasks', function ($routes) {
$routes->get('', 'Auth::index');
});
});
Alterando os controller para testes iniciais. Vamos verificar se está tudo certo com as rotas.
Acesse modules/Todo/Dashboard/Controllers/Dashboard.php e faça algumas alterações (apenas para testes iniciais)
<?php
namespace Modules\Todo\Dashboard\Controllers;
use Modules\Todo\Main\Controllers\BaseController;
class Dashboard extends BaseController
{
public function __construct()
{
//...
}
public function index()
{
echo 'dashboard em rota protegida pelo filter';
}
}
Agora, se acessarmos o endereço http://localhost:8080/todo/ (verifique o endereço de acordo com sua url base)
Veremos algo parecido com isso
Isso aconteceu porque a nossa rota está protegida e não permitiu acesso sem um login realizado.
Para testarmos se o filtro está realmente funcionando vamos fazer um pequeno debug.
Acesse app/Filters/MyFilter.php e adicione um dei('caiu no filtro') logo após a abertura do método before
public function before(RequestInterface $request, $arguments = null)
{
die(' caiu no filtro');
$this->auth = service('session')->get();
$this->ip = $request->getIPAddress();
if (!$this->isLoggedIn() or ($this->auth['key'] != PRIVATE_KEY) or ($this->ip != $this->auth['ip_login'])) {
service('session')->destroy();
return redirect()->to(base_url('auth/logout'));
}
}
E veremos o seguinte.
Com isso concluímos que o filtro está protegendo as rotas.
A partir deste ponto vamos iniciar a construção do sistema. Vamos configurar nossas dependencias CSS e #templates.
Ir para o próximo passo. CRUD Codeigniter 4 - Parte 2