Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

jribeirojr

Sugestão de como salvar menu dinâmico para o usuário

Recommended Posts

Pessoal gostaria de uma sugestão de vocês, caso já tenham passado por algo parecido

 

Hoje tenho uma aplicação que possui acesso restrito aos usuários, e cada usuário que realizar o acesso um menu é montado com base nos direitos que ele tem de acesso. Este menu é montado da seguinte maneira:

1 - o usuário ao se logar no sistema é atribuido um grupo de usuários a ele, com um nome, por exmeplo DIRETOR

2 - o meu sistema em PHP vai no diretório de MENUS e localiza o arquivo XML como nome diretor.xml e monta o menu para aquele usuário. Claro que a cada acesso do menu que ele faz eu capturo determinadas informações e valido se ele tem acesso aquele menu

 

Montando desta maneira eu tenho a vantagem de que a cada refresh da página eu não precise acessar o banco de dados e buscar os itens de menu que ele tem acesso, mas em compensação eu tenho que recarregar sempre o XML que monta o menu

 

Estava querendo desenvolver alguma outra forma para poder montar este menu dinâmico, e gostaria de sugestões , como por exemplo:

 

1 - Pensei em salvar em banco de dados o arquivo HTML do menu para cada usuário, mas isso consumiria espaço em banco de dados e também teria que acessar o banco a cada refresh da página, não sei se seria viável

 

2 - Pensei em salvar apenas o XML em banco de dados mas aí teria que consultar o banco de dados para pegar o XML e depois a função para ler o mesmo e montar o menu

 

3 - Pensei em deixar o menu livre para todos os usuários e validar apenas quando ele tivesse acesso, mas isso faria com que todos os usuário vissem todos os menus sendo que ele só tem acesso a 2 itens do menu por exemplo

 

4 - Já pensei em usar Angular para que toda o usuário ao trocar de página não fosse necessário recarregar o menu, mas isto neste momento é inviável porque teria que trocar muita coisa na minha aplicação, que já é bem grande

 

Pensei de tudo, mas não consigo chegar a uma conclusão ou solução saudável tanto para o sistema quanto para processamento e custo de armazenamento.

 

Sei que é complicado, mas se alguém pelo menos já tiver passado por isso, ou ter criado uma aplicação para resolver este tipo de problema e quiser compartilhar, agradeceria

 

Obrigado

 

 

 

 

 

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vou ate seguir este post xD para ver alguém apresenta alguma forma 100% eficiente. 

Ja fiz algo parecido com oque descreveu e também ja montei uma logica com cookies e também ja vi outros sistema com umas logicas muito louca para controlar isso. Ate hoje nunca cheguei em uma conclusão 100% eficiente.  

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu estou desenvolvendo alguma coisa parecida, mas por enquanto só estou usando menu com ícones para exibir módulos, eu criei uma tabela para os módulos e uma tabela para as permissões dos usuários.

 

Na tabela de módulos eu cadastro o nome de cada módulo (que também vai ser usado para chamar o ícone JPG) o nome do arquivo do módulo (ex: vendas.php) e o status do modulo (se ele está ativo ou não).

 

Na tabela de permissões (que será inerente a cada módulo) eu tenho os seguintes campos: id; modulo_id; usuário_id; ver; inserir; alterar; excluir; imprimir; exportar; (para os campos de ações ex: ver, inserir, alterar..., eu uso a codificação binária, 1 para verdadeiro e 0 para falso). 

 

A identificação do usuário é feita pela Session ID dele, então você pode criar uma função que não precisa nem passar parâmetros, basta fazer a consulta na tabela de módulos e permissões e trazer o resultado em forma de menu. Vou colocar abaixo o código do meu menu de ícones, acredito que a lógica seria a mesma.

 

header.php


<?php 

require_once("funcoes.php");
$modulos = modulos();

foreach($modulos as $menuitem) { 
?>
  <div class="col-1">
      <span class="centerbold top5">

          <img src="images/<?php echo $menuitem['modulo_nome'];?>.jpg" class="imenu" onClick="location.href='<?php echo $menuitem['modulo_arquivo'];?>';">

      </span>
      <span class="centerbold">

          <?php echo ucfirst($menuitem['modulo_nome']);?>

     </span>
  </div>    

  <?php
}
?>

 

funcoes.php


function modulos(){
  global $con;
 //A primeira id é a do index então ele é obrigatório e não entra na consulta

  $rs = $con->prepare("SELECT * FROM modulos WHERE modulo_status = 1 AND modulo_id <> 1");
  $rs->execute();
  $res = array();
  while($row = $rs->fetch(PDO::FETCH_ASSOC)){
    $res[]=$row;
  }
  return $res;
}
?>

 

Vou seguir a mesma lógica para os menus e opções que virão depois em cada módulo, consulto no banco de dados e com um while ou for eu monto os menus, talvez crie uma fução adicional para exibir os botões de ação dos módulos, mas não planejei esta parte ainda.

 

Como disse ainda estou implementando e isto pode parecer meio rudimentar e as revisões só virão depois de prontas as rotinas, então perdoem se tiver parecendo meio que "gambiarra" rsrsrsrs.
 

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

pq você escolheu carregar um xml ao invés de usar include com o menu correspondente de cada grupo de usuário?

são muitos grupos?

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Eletronic

 

Acabei usando XML porque nele guardo apenas os menus que o usuário tem acesso com o id do menu, texto, ícone e URL não então acessar o banco dados para consulta toda vez que a página é carregada 

Como os direitos de acesso de cada grupo pode mudar utilizar um include faria com que eu ainda continuasse a ter que acessar o banco para pegar a informação.

 

SERGIO

 

É exatamente assim que faço, tenho as tabelas no banco de dados que controlam cada módulo, o usuário ao clicar em um determinado link do menu passo o módulo daquele link e aí válido se aquele usuário tem ou não acesso ao link 

Meu problema está mesmo em como montar o menu de uma forma que economize processamento de banco de dados e servidor web

 

Estive pensando agora em uma ideia, levando em conta a utilização de include a como sugeriu o Eletronic o que acham?

 

1 - eu teria uma página Pho já com todo o código HTML do menu e teria um arquivo para cada grupo de usuário

 

2 - caso algum direito fosse alterado no banco de dados, via programação alteraria este include com as novas opções e o usuário ao se logar teria acesso ao novo menu

 

Não sei se é possível via PHP gerar um novo arquivo com extensão PHP mas talvez poderia ser a saída

 

O que acham?

 

Obrigado pelo compartilhamento das sugestões

 

Abs

Compartilhar este post


Link para o post
Compartilhar em outros sites

É possível sim criar um arquivo com o html dos menus gerado de forma dinâmica, daí você atrela o nome desse arquivo ao ID do usuário por exemplo, e em todas as páginas  onde deve aparecer o menu você coloca um include tipo assim "include($id_usuario."menu.html");"

Dessa forma somente na autenticação você faz a consulta e cria o arquivo de menu.

O único detalhe seria que cada usuário passaria a ter um arquivo de menu criado no servidor, mas você pode destruir esse arquivo também ao finalizar a sessão do usuário, e seria interessante fazer uma verificação antes do include para ver se o arquivo realmente existe para prevenir mensagens de erro caso dê algum b.o., além de ter um menu padrão para redirecionar em caso de erro.

Acho que assim dá pra fazer da maneira que você falou.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Pessoal,

 

Primeiramente quero agradecer a todos aqui pelas sugestões e compartilhamento das idéias, com elas acabei criando uma forma que chegou a economizar 80% de processamento no meu sistema de menu, vou tentar descrever um pouco mais sobre o que fiz, e se alguém quiser mais informações me avisem.

 

Minha aplicação foi desenvolvida em CodeIgniter 3.1.3.

 

Estrutura do Menu em banco de dados

Criei no meu banco de dados uma estrutura de menu onde tenho todos os dados do menu, com diversos campos que montam todo o menu, são eles:

  • id
  • idMenuPrincipal -> informa se o registro está vinculado a um MENU, portanto é um subMenu
  • txtIcone -> ícone do menu
  • txtMenu -> nome que aparece para o usuário
  • txtIdMenu -> serve para podermos colocar o ACTIVE no item, ou seja, o usuário ao acessar aquele menu e a página ser populado é inserido um active para informar ao mesmo em qual menu se encontra
  • txtUrl -> url do menu
  • intOrdem -> ordenação
  • bitCabecalho -> informa que este registro é apenas um cabeçalho, um teste separando os menus em grupos
  • txtButtonAction -> serve para poder inserir as ações que a página irá ter ao ser acessada, como por exemplo, editar, excluir, inserir, etc. Todos os botões que irão existir na página de diferentes funcionalidades, é um campo registrado como um array serializado

Com base nisso criei uma página onde lista todos estes menus em formato TREE VIEW, onde selecione o Menu Pai e ele automaticamente já seleciona os filhos dele (quem quiser posso enviar o código)

 

Toda vez que um usuário tem uma alteração nestes direitos, registros os direitos do mesmo em uma tabela que tem os seguintes campos:

  • idGrupoAccess -> id do grupo que o usuário pertence
  • idMenuAdmin ->chave estrangeria da tabela explicada acima
  • txtPermissoes -> as permissões que foram registradas no campo txtButtonAcion acima

Aqui está a alteração que fiz para economizar processamento.

Ao realizar a alteração, faço a leitura destes menus criando um array multidimensional com todas as informações e salvo este array em um arquivo criptografado, segue o código como nome do grupo do usuário

$serializedData = serialize($this->template->gera_array_menu_final($this->dataMenu['menu']));
write_file('assets/menu/' . $objData->txtGrupo . '.txt', encode($serializedData));

Desta maneira é criado um arquivo criptografado, que fica desta maneira:

isEvbzOhKhU~QIITLQmt1M23IkJhVbSSBzUby4O1302yLIWBFDPJG45H96WE3oDFWwzVgave9YolvtNdOEhtqPY9BTb.I8zmXyzSay8I~uTuW9EcZevNKg9fquE75SMRvI0.Wu~.wk8lMb8x0CNJxRnuQTa9OAPTxkl4Sn128NYGoci0jGZZRluFVnaZJM84EsAuhDQsLwn7e~~cjkM..bwjiOyVBjsxU2wIZ4Y.ZkT1g4I.g3weFPTuUF~gIxaGbXq0OrJ2vSlqUcXXLTK6tf~RPO~EXD7keUi4n6SdhYt1XWVVGJHRgrAm9Skv4IGY~.wzVISOEoV~FsbNOf76Ky3nwvh.NjtYrcANxMHWibut3gddJ8Z2NFUbHJif3nD2vevHfZKQzYSixERQ1Gy.2Kobfv1UTUxtFU4uP~~3FegfmyPI.YzhGtEl.RT8qi7RhZ0E.h5dhDiBTpwMloORmTu9Vl0FcCD~iHouzNIAZSwuUZOdDB73g5EUrEGUb~FstFd1fIOdTOikWxlVGF.TizxiNNPfbypjCmXFtJpnhLCy.yELw4QrNWlIIajVRXg~Pqd4.ryi0OqZFHNys~n78lEr9.2bfi7mlVizJrYybjsmuaKegETYIU75ttb6XfERPqXzNVYpebK.bKAvTq2rcWviApoI0.QqYlKW3W.MtF5.KIHUD2MsbMxav1sA4~To83MTkCwZ~xKzjapN.RtPDp5f2Laam6ObPmrKH2EzGdyQfUMx23M2jm1s6NvHHe3oQYpXTeOZncV0Yt5mxYZC9H2zO.E.jnAWEoAnmSg2odkmXzDcRwKcqt9wR5U5Gqat6yQyWXcWr3iaOtufgqUdNgc6YH0cTZSQUkrcekSPHCfHnqs2H2F3LJEujfXDqkjGHWnUJHgEEAkRWvV5w796x42AZvoTRrXxJ0evWzSQa~sUwQwlklVNlC7~ygNCclTLqkaXKnyPTwVDlBFlX4aDZMFXSYtNoEVAcwzJzok1jlM8AK0441LXqpDtqe5OJBkmjcXDwaTWHMljdnFW3Wd7bpGT9gjlENLmFutNFx24rKR6nPXYsEOHH5GKQ2Bywrbezo2qMnNTl620t5A1YvxjXMSBLkxydr15x592~Sxz~IbH9ihksfJjccZ6.T7eSkTMpF4aBg6pfOhaZnUZnXKEwIdqLssKZsGHN.AC9PIEmvm07MklKvFnyHic1H8nFCymQgkcU2ps9n33AdHZICuHSgCRF8mcnXnhyeI.Db1BSihpTbgPCQe.4OM5pedwoNoS4gg6rsBcHn4UWi6WaJDKkmxIJZj9TbRaB~W~uWK9bWGNcBNNy8aKnFZDMXo7TJ9y0Y09Uxzg49spzWxIe3U4YH.~GuoO~G83bmVdrUDrCzkxbqBSztl.2J.VRtYFuSTX3PVZcd1b7VVRcYFiMFQx~7MFRReKhZyuG05qcf6UHc34Ovxat7Cn9FKsByXhxrDp5c23fVeiQnzpaGZmHui13KYhor2~JE6rBj3UICpXvwSccV.qoHUxBxl1x6kq15DkE4wJD4IlmoRnHpdkAmFYnHzAvLpU3NvNMxPTGMUZJioB8gDpL5UdNiK.HnPb6zqXCJO6elo.y4oM4BD9Uit8AmHgUuCRZmJb9j4FwK~ZoaaKiu.dDvQoskI6NyhM8B78Huu3M2l3ol1WsmFeaDyYpFRsPkfzamKccZGpTq9PrswYHyxulPtXzvf3QhIDDzTp8E6N.rsVD1NxqNKw16zJnguqgRv~R7cOdtqGtfWpkEmSjaLiEvh5.QefpM0DK~xMK.8mGM0icK1NpM58i.78JQ.rMIJrsHhDg1VUvezr8nXL475C9ZkktLTSjUxRzeBIkLVGjlsQkSTwoh6e38beMIUE3mgq8jlDu1WlFGDeBiot08J7j3R.ghj0xtU3eedupn9tOD4KT3M8aKeCzjgVz5npi1U5grVzuy2CipWSq7pCgGyk0GeitwJ2qLgPfEt5ViYzFuhwzbYePrr0jly2AjjlFmZ9vqbXOo4sMKGWCJ4L7cMn7e0WZA9JJLZzulGP

Agora, ao carregar o menu faço apenas a leitura deste arquivo e decripto ele, percorrendo o array e montando o menu.

Não gerei este arquivo criptografado já em HTML porque preciso inserir o ACTIVE do menu que o usuário se encontra, mas meu processamento caiu em 80%. Vejam como ficou a leitura do arquivo e a formatação dele para gerar o menu

$CI = & get_instance();
$CI->load->helper('file');
$recoveredData = read_file(assets_url('assets/menu/' . $CI->session->administrativo['txtMenuFile'] . '.txt'));
$this->build_nav_array(unserialize(decode($recoveredData)));
echo $this->nav_html;

foreach ($nav_array as $node):
  $class_active = '';

  // Determinar em qual menu será colocada a classe active
  $this->main_nav_active = str_replace('/admin/', '', $_SERVER['REQUEST_URI']);
  $capturarClasseMetodo = explode('/', $this->main_nav_active);
  if(!isset($capturarClasseMetodo[1]))
  	$this->main_nav_active = $capturarClasseMetodo[0];
  else
  	$this->main_nav_active = $capturarClasseMetodo[0] . '/' . $capturarClasseMetodo[1];

  $link_name      = isset($node['name']) ? $node['name'] : '';
  $link_icon      = isset($node['icon']) ? '<i class="' . $node['icon'] . '"></i>' : '';
  $link_url       = isset($node['url']) ? $node['url'] : '#';
  $link_sub       = isset($node['sub']) && is_array($node['sub']) ? true : false;
  $link_type      = isset($node['type']) ? isset($node['type']) : '';
  $sub_active     = false;
  $link_active    = $link_url == $this->main_nav_active ? true : false;

  if($link_sub){
  	$this->nav_html .= "<li>";
    $this->nav_html .= "$link_name";
    $this->nav_html .= "<ul>";
    $this->build_nav_array($node['sub']);
    $this->nav_html .= "</ul>";
    $this->nav_html .= "</li>";
  }
  else{
	if($link_active)
  		$class_active = 'active';

  if($link_type)
  	$this->nav_html .= $link_name;
  else
  	$this->nav_html .= '<li class="' . $class_active . '">' . $link_name . '</li>';
  }
  endforeach;

O código é bem grande mas resolveu o problema que eu tinha, e conforme o Sergio tinha faldo que seria ideal apagar o arquivo quando o usuário saisse do sistema, criptografando o arquivo não é necessário realizar esta ação

 

Vou manter o sistema desta maneira e acompanhar a performance dele com a utilização dos usuários

 

Se alguém tiver alguma idéia e quiser compartilhar será bem vinda e também se desejarem melhorar o sistema seria ótimo, toda a contribuição é válido

 

Espero ter contribuido se não resolver pelo menos para poder ajudar a clarear para novas idéias

 

Abs

 

 

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por violin101
      Caros amigos, saudações.
       
      Por favor, me permita tirar uma dúvida com os amigos.

      Tenho um Formulário onde o Usuário digita todos os Dados necessários.

      Minha dúvida:
      --> como faço após o usuário digitar os dados e salvar, o Sistema chamar uma Modal ou mensagem perguntando se deseja imprimir agora ?

      Grato,
       
      Cesar
    • Por Carcleo
      Tenho uma abela de usuarios e uma tabela de administradores e clientes.
      Gostaria de uma ajuda para implementar um cadastro
       
      users -> name, login, passord (pronta) admins -> user_id, registratiom, etc.. client -> user_id, registratiom, etc...
      Queria ajuda para extender de user as classes Admin e Client
      Olhem como estáAdmin
      <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Admin extends User {     use HasFactory;            protected $fillable = [         'name',         'email',         'password',         'registration'     ];      private string $registration;     public function create(         string $name,          string $email,          string $password,         string $registration     )     {         //parent::create(['name'=>$name, 'email'=>$email, 'password'=>$password]);         parent::$name = $name;         parent::$email = $email;         parent::$password = $password;         $this->registration = $registration;     } } User
      <?php namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class User extends Authenticatable {     /** @use HasFactory<\Database\Factories\UserFactory> */     use HasFactory, Notifiable;     static string $name;     static string $email;     static string $password;     /**      * The attributes that are mass assignable.      *      * @var list<string>      */     protected $fillable = [         'name',         'email',         'password',     ];          /**      * The attributes that should be hidden for serialization.      *      * @var list<string>      */     protected $hidden = [         'remember_token',     ];     /**      * Get the attributes that should be cast.      *      * @return array<string, string>      */     protected function casts(): array     {         return [             'email_verified_at' => 'datetime',             'password' => 'hashed',         ];     }          public function roles() : BelongsToMany {         return $this->belongsToMany(Role::class);     }       public function hasHole(Array $roleName): bool     {                 foreach ($this->roles as $role) {             if ($role->name === $roleName) {                 return true;             }         }         return false;     }         public function hasHoles(Array $rolesName): bool     {                 foreach ($this->roles as $role) {             foreach ($rolesName as $rolee) {             if ($role->name === $rolee) {                 return true;             }          }         }         return false;     }         public function hasAbility(string $ability): bool     {         foreach ($this->roles as $role) {             if ($role->abilities->contains('name', $ability)) {                 return true;             }         }         return false;     }     } Como gravar um Admin na tabela admins sendo que ele é um User por extensão?
      Tentei assim mas é claro que está errado...
      public function store(Request $request, Admin $adminModel) {         $dados = $request->validate([             "name" => "required",             "email" => "required|email",             "password" => "required",             "registration" => "required"         ]);         $dados["password"] =  Hash::make($dados["password"]);                  $admin = Admin::where("registration",  $dados["registration"])->first();                  if ($admin)              return                    redirect()->route("admin.new")                             ->withErrors([                                 'fail' => 'Administrador já cadastrados<br>, favor verificar!'                   ]);                            $newAdmin = $adminModel->create(                                    $dados['name'],                                    $dados['email'],                                    $dados['password'],                                    $dados['registration']                                 );         dd($newAdmin);         $adminModel->save();         //$adminModel::create($admin);                  return redirect()->route("admin.new")->with("success",'Cadastrado com sucesso');     }  
    • Por violin101
      Caros amigos, saudações.
       
      Gostaria de tirar uma dúvida com os amigos, referente a PDV.
       
      Estou escrevendo um Sistema com Ponto de Vendas, a minha dúvida é o seguinte, referente ao procedimento mais correto.

      Conforme o caixa vai efetuando a venda, o Sistema de PDV já realiza:
      a baixa direto dos produtos no estoque
      ou
      somente após concretizar a venda o sistema baixa os produtos do estoque ?
       
      Grato,
       
      Cesar
       
    • Por violin101
      Caros amigos do grupo, saudações e um feliz 2025.
       
      Estou com uma pequena dúvida referente a Teclas de Atalho.

      Quando o Caps Lock está ativado o Comando da Tecla de Atalho não funciona.
      ou seja:
      se estiver para letra minúscula ====> funciona
      se estiver para letra maiúscula ====> não funciona
       
      Como consigo evitar essa falha, tanto para Letra Maiúscula quanto Minúscula ?

      o Código está assim:
      document.addEventListener( 'keydown', evt => { if (!evt.ctrlKey || evt.key !== 'r' ) return;// Não é Ctrl+r, portanto interrompemos o script evt.preventDefault(); });  
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Por favor, poderiam me ajudar.

      Estou com a seguinte dúvida:
      --> como faço para para implementar o input código do produto, para quando o usuário digitar o ID o sistema espera de 1s a 2s, sem ter que pressionar a tecla ENTER.

      exemplo:
      código   ----   descrição
           1       -----   produto_A
       
      Grato,
       
      Cesar
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.