Skip to content

Configuração de acesso a dados

Lucas de Araújo edited this page Aug 3, 2015 · 17 revisions

Introdução

Utilizando o ZendAccessManager é possível, dentro de uma estrutura pré-definida, construir estratégias de acesso a dados para serem utilizadas de uma maneira simples. Supondo que exista uma tabela cad_contrato, e diferentes usuários com diferentes níveis de acesso num sistema precisam acessar os dados dessa tabela, de formas diferentes, de modo que cada nível de acesso poderá ver apenas dados específicos, como proceder?

try
{
   // Obtém o usuário armazenado na sessão
   $usuario = (new UserContainer())->getCurrentUser();

   // Obtém a estratégia de acesso definida para o usuário
   $sm = new ContratoStrategyManager();
   $estrategia = $sm->getStrategyFor($usuario);

   // Acessa os dados de acordo com a estratégia
   $contratos = $estrategia->fetchContratos();

   // [...]
   // Exibe contratos...
}
catch(StrategyNotFoundException $e)
{
   // Acesso negado...
}

Entendendo a estrutura

Para criar uma estrutura de acesso a dados personalizada devemos ter em mente que precisaremos de três coisas: um TableGateway, responsável por executar as operações nos banco de dados, ao menos uma Strategy de acesso aos dados, e um StrategyManager, responsável por fazer a escolha da estratégia de acordo com as regras definidas no mesmo.

StrategyManager

Criando uma estratégia de acesso a dados

Criando um TableGateway

Por definição, toda estratégia de acesso a dados, precisa estar ligada a um tablegateway. Portanto, se vai fazer uma estratégia de acesso a dados, o primeiro a se fazer, é criar a classe que acessa os dados, para em seguida, executá-la na estratégia. Para mais informações, veja a documentação do ZendFramework 2.

class ContractTable extends AbstractTableGateway
{
   public function __construct()
   {
      $this->table = "cad_contrato";
      $this->adapter = GlobalAdapterFeature::getStaticAdapter();
   }
}

Criando uma interface de acesso a dados

A interface, é um padrão que deverá ser seguido pelas estratégias de acesso aos dados. Isto é, presume-se existem diferentes estratégias, para se fazer as mesmas coisas, então, deverão as estratégias de acesso a dados implementar igualmente, os métodos definidos na interface, cada qual com sua regra específica.

interface ContractStrategyInterface extends DataAccessStrategyInterface
{
   public function fetchRecentContracts();
   public function fetchAllContracts();
} 

Implementando a interface de acesso a dados

Nesse exemplo implementaremos as funções da estratégia que foram definidas na interface.

Estratégia de acesso para administradores

class AdminContractAccessStrategy implements ContractStrategyInterface
{
   /**
    * Configura a estratégia
    */
   public function __construct()
   {
      $this->setTableGateway(new ContractTable());
   }

   /**
    * Localiza os contratos recentes
    * @return ResultSet
    */
   public function fetchRecentContracts()
   {
      return $this->getTableGateway()->select(function(Select $select){
         $select->order('idcontrato DESC');
         $select->limit(10);
      });
   }

   /**
    * Localiza todos os contratos
    * @return ResultSet
    */
   public function fetchAllContracts()
   {
      return $this->getTableGateway()->select();
   }
}

Estratégia de acesso para vendedores

class SalesContractAccessStrategy implements ContractStrategyInterface
{
   /**
    * Configura a estratégia
    */
   public function __construct()
   {
      $this->setTableGateway(new ContractTable());
   }

   /**
    * Localiza os contratos recentes
    * @return ResultSet
    */
   public function fetchRecentContracts()
   {
      $user = (new UserContainer())->getUser();

      return $this->getTableGateway()->select(function(Select $select) use($user) {
         $select->where->equalTo('idsalesman', $user->getId());
         $select->order('idcontract DESC');
         $select->limit(10);
      });
   }

   /**
    * Localiza todos os contratos
    * @return ResultSet
    */
   public function fetchAllContracts()
   {
      $user = (new UserContainer())->getUser();
      return $this->getTableGateway()->select(function(Select $select){
         $select->where->equalTo('idsalesman', $user->getId());
      });
   }
}

Criando um StrategyManager

O StrategyManager é o elemento responsável por ler o contexto da aplicação, e retornar qual a melhor estratégia para o contexto, de acordo com o que fora definido pelo programador.

class ContractStrategyManager extends AbstractStrategyManager
{
   public function getStrategyForContext($context)
   {
      $user = $context;

      switch($user->getType())
      {
         case UserType::Admin: return new AdminContractAccessStrategy();
         case UserType::Sales: return new SalesContractAccessStrategy();
      }
   }
}

Implementando as estratégias

class ContractController extends AbstractActionController
{
   public function indexAction()
   {
      $user = (new UserContainer())->getUser();
      $manager = new ContractStrategyManager();
      $strategy = $manager->getStrategyFor($manager);
   }
}