Este código cria um sistema web administrativo com controle de acesso e nivel, utilizando Bootstrap 5.3.

Para iniciar você precisa instalar o #codeigniter 4.7 em seu ambiente com o #composer

composer create-project codeigniter4/appstarter nome-do-seu-projeto

Este sistema trabalha com arquiterura de módulos, entidades de domínio e serviços e utilizará url amigável para acesso as páginas.

Em breve o link para o git do projeto será disponibilizado.

O cadastros testados são: empresas, usuários, grupos e departamentos.

1 - Configurar o .env para espelhar um ambiente de desenvolvimento e conectar a um banco de dados. É necessário uma conexão com um banco de dados.

Informações ou código fonte: gilbmg@gmail.com assunto: título do post.

Demonstração: www.codesnippets.dev.br/web/ci4 (usuário: admin@admin.com e senha admin123)

Você pode querer ajustar o app.baseURL também.

A estrutura base dos módules será basicamente com esta.

Utilizaremos doi templates principais: para logados e não logados. /app/Views/layouts

Tela de listagem de empresas.

Acessos.

Categorias e subcategorias

Demonstração: www.codesnippets.dev.br/web/ci4 (usuário: admin@admin.com e senha admin123)

modules/Subcategorias/Controllers/Subcategorias.php

<?php

namespace Modules\Subcategorias\Controllers;

use App\Controllers\BaseController;
use CodeIgniter\Exceptions\FrameworkException;
use Modules\Subcategorias\Application\SubcategoriaService;

class Subcategorias extends BaseController
{
 protected SubcategoriaService $subcategoriaService;

 public function __construct()
 {
 $this->subcategoriaService = service('subcategoriaService');
 }

 public function index(): string
 {
 $pagina = (int) $this->request->getGet('page') ?: 1;
 $termo = $this->request->getGet('termo') ?? '';
 $status = $this->request->getGet('status') ?? '';
 $categoriaId = (int) $this->request->getGet('categoria_id') ?: 0;

 $resultado = $this->subcategoriaService->listar($pagina, $termo, $status, $categoriaId);

 // Obter lista de categorias para o filtro
 $categoriaService = service('categoriaService');
 $categorias = $categoriaService->listarAtivas();

 $data = [
 'subcategorias' => $resultado['dados'],
 'paginacao' => $resultado['paginacao'],
 'termo' => $termo,
 'status' => $status,
 'categoriaId' => $categoriaId,
 'categorias' => $categorias,
 ];

 return view('Modules\Subcategorias\Views\index', $data);
 }

 public function create(): string
 {
 $categoriaService = service('categoriaService');
 $categorias = $categoriaService->listarAtivas();

 return view('Modules\Subcategorias\Views\form', [
 'subcategoria' => null,
 'categorias' => $categorias,
 'titulo' => 'Nova Subcategoria',
 ]);
 }

 public function store()
 {
 if (!$this->request->is('post')) {
 return redirect()->back();
 }

 try {
 $categoria_id = $this->request->getPost('categoria_id');
 $nome = $this->request->getPost('nome');
 $status = $this->request->getPost('status') ?? 'ativo';

 log_message('info', '[Subcategorias::store] Recebido: categoria_id=' . $categoria_id . ', nome=' . $nome . ', status=' . $status);

 $this->subcategoriaService->criar([
 'categoria_id' => $categoria_id,
 'nome' => $nome,
 'status' => $status,
 ]);

 log_message('info', '[Subcategorias::store] Subcategoria criada com sucesso');
 session()->setFlashdata('success', 'Subcategoria criada com sucesso!');
 return redirect()->to('cadastros/subcategorias');
 } catch (FrameworkException $e) {
 log_message('error', '[Subcategorias::store] FrameworkException: ' . $e->getMessage());
 session()->setFlashdata('error', $e->getMessage());
 return redirect()->back()->withInput();
 } catch (\Exception $e) {
 log_message('error', '[Subcategorias] Erro ao criar: ' . $e->getMessage());
 session()->setFlashdata('error', 'Erro ao criar subcategoria. Tente novamente.');
 return redirect()->back()->withInput();
 }
 }

 public function edit(int $id): string
 {
 $subcategoria = $this->subcategoriaService->obterPorId($id);

 if (!$subcategoria) {
 throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
 }

 $categoriaService = service('categoriaService');
 $categorias = $categoriaService->listarAtivas();

 return view('Modules\Subcategorias\Views\form', [
 'subcategoria' => $subcategoria,
 'categorias' => $categorias,
 'titulo' => 'Editar Subcategoria',
 ]);
 }

 public function update(int $id)
 {
 if (!$this->request->is('post')) {
 return redirect()->back();
 }

 try {
 $categoria_id = $this->request->getPost('categoria_id');
 $nome = $this->request->getPost('nome');
 $status = $this->request->getPost('status');

 log_message('info', '[Subcategorias::update] ID=' . $id . ', categoria_id=' . $categoria_id . ', nome=' . $nome . ', status=' . $status);

 $this->subcategoriaService->atualizar($id, [
 'categoria_id' => $categoria_id,
 'nome' => $nome,
 'status' => $status,
 ]);

 log_message('info', '[Subcategorias::update] Subcategoria atualizada com sucesso');
 session()->setFlashdata('success', 'Subcategoria atualizada com sucesso!');
 return redirect()->to('cadastros/subcategorias');
 } catch (FrameworkException $e) {
 log_message('error', '[Subcategorias::update] FrameworkException: ' . $e->getMessage());
 session()->setFlashdata('error', $e->getMessage());
 return redirect()->back()->withInput();
 } catch (\Exception $e) {
 log_message('error', '[Subcategorias] Erro ao atualizar: ' . $e->getMessage());
 session()->setFlashdata('error', 'Erro ao atualizar subcategoria. Tente novamente.');
 return redirect()->back()->withInput();
 }
 }

 public function delete(int $id)
 {
 try {
 $this->subcategoriaService->deletar($id);
 session()->setFlashdata('success', 'Subcategoria deletada com sucesso!');
 } catch (FrameworkException $e) {
 session()->setFlashdata('error', $e->getMessage());
 } catch (\Exception $e) {
 log_message('error', '[Subcategorias] Erro ao deletar: ' . $e->getMessage());
 session()->setFlashdata('error', 'Erro ao deletar subcategoria. Tente novamente.');
 }

 return redirect()->to('cadastros/subcategorias');
 }

 public function buscarPorCategoria(int $categoriaId = 0)
 {
 if ($categoriaId <= 0) {
 return $this->response->setJSON(['success' => false, 'message' => 'Categoria inválida']);
 }

 try {
 $subcategorias = $this->subcategoriaService->buscarPorCategoria($categoriaId);

 return $this->response->setJSON([
 'success' => true,
 'data' => $subcategorias,
 ]);
 } catch (\Exception $e) {
 log_message('error', '[Subcategorias] Erro ao buscar por categoria: ' . $e->getMessage());
 return $this->response->setJSON([
 'success' => false,
 'message' => 'Erro ao buscar subcategorias',
 ]);
 }
 }
}