Back-End

3 set, 2015

Use o padrão Gateway e acesse dados de onde quiser em seu projeto

Publicidade

Todos os aplicativos precisam acessar dados comuns de diferentes partes do código, como valores de configuração, traduções de texto, acessar bancos de dados etc. O padrão Gateway define uma abordagem limpa para acessar os dados de aplicativos comuns de qualquer lugar no seu código.

Leia este artigo para saber mais sobre padrão Gateway e como implementá-lo para acessar métodos e propriedades comuns a partir de qualquer parte do código do seu aplicativo PHP seguindo os princípios da orientação a objetos, e como ele também pode ser usado para implementar outros padrões de projeto bem conhecidos.

Introdução

Em um artigo anterior, descrevemos 3 formas de acessar dados comuns de aplicativos em PHP. O padrão Gateway foi introduzido como uma das três maneiras de acessar métodos e propriedades comuns do aplicativo. Os métodos são chamados e as propriedades são acessadas através de um único ponto do programa.

No entanto, há um risco em acessar indevidamente (e involuntariamente substituir) as propriedades comuns de várias partes do programa. Os métodos adicionais são descritos neste artigo para acesso seguro e unificado das propriedades.

Os aplicativos modernos em PHP tendem a seguir o conceito OOP. O acesso aos dados comuns no âmbito global não está em conformidade com a utilização do OOP. O padrão Gateway implementado pela classe do gateway alivia esse problema.

Métodos de acesso a propriedades

As propriedades comuns podem ser implementadas através da variável estática da classe gateway utilizando propriedade de sobrecarga (ver artigo anterior). Isso é conveniente, mas torna difícil acompanhar as mudanças de variáveis. Um novo método _() é adicionado para lidar com as propriedades comuns, e uma variável estática $_ é retida para ser usada como área de trabalho para as atividades de tempo crítico:

class ¤ {

  private static $cmi;                  /* common instance */
  private static $sep;                  /* path separator */
  public static $_;                     /* workarea */

  /**
   * link to common data
   * @param string $cln common class name
   * @param string $sep path separator
   */
  public static function _Init($cln = 'Common', $sep = '.') {
    self::$cmi = new $cln( self::$_ );    /* instantiate the common class */
    self::$sep = $sep;                  /* save property path separator */
  }

  /**
   * access a method
   * @param object $func method name
   * @param array $args arguments list
   * @return mixed
   */
  public static function __callStatic( $func, $args ) {
    return call_user_func_array( array( self::$cmi, $func), $args );
  }

  /**
   * get/set a property value 
   * @param arguments -- 1st - path string
   *                     2nd - value (set only)
   * @return mixed get/set value
   */
  public static function _() {
    $path = trim(func_get_arg(0), self::$sep);  /* remove leading / trailing separators */
    $pth = explode( self::$sep, $path);          /* split the path */
    if (func_num_args() > 1) {
      $value = func_get_arg( 1 );                 /* value to set */
      self::$cmi->_set($pth, $value);    /* set a value */
    } else {
      $value = self::$cmi->_get($pth);   /* get a value */
    }
    return $value;
  }

}

O método _() obtém ou define o valor da propriedade, dependendo do número de argumentos, sendo 1 ou 2, respectivamente. O primeiro argumento especifica o caminho da propriedade. O segundo argumento especifica o valor a ser definido.

A classe Common fornece os métodos _get() e _set() para processamento das propriedades comuns. Não confundir com os métodos mágicos __get() e __set(). Veja o arquivo common.php para esses métodos. Talvez você possa descobrir um algoritmo melhor para implementar os métodos _get e _set.

Caminho de acesso à propriedade

A propriedade é identificada pelo caminho de acesso. Cada elemento do caminho representa tanto uma propriedade do objeto como um elemento do array associativo. Assim, o caminho pode ser uma mistura da propriedade do objeto e dos nomes de chave do array.

O exemplo a seguir demonstra o uso do caminho de acesso comuns ao gateway (o ponto é usado como um separador de caminho e pode ser redefinido).

<?php
 include 'gateway.php';
 include 'common.php';
 define('BR', '<br />');

 $ctt = array('phn' => '444555666', 'eml' => 'info@mail.com', /* test data */
    'adr' => (object) array('str' => 'Elm', 'twn' => 'Sunny'));

 ¤::_Init();       /* instantiate common */
 header("Content-Type: text/html; charset=utf-8");

 ¤::_('ctt', $ctt); /* set a structured value */
 ¤::_('ctt.chd', array('Sally', 'Billy'));  /* set an array value */
 echo 'Phone: ' . ¤::_('ctt.phn') . BR;  /* get a value */
 ¤::_('ctt.adr.str', 'Oak'); /* replace a value */
 echo 'Street: ' . ¤::_('ctt.adr.str') . BR;  /* get a value */
 echo 'Town: ' . ¤::_('ctt.adr.twn') . BR;  /* get a value */
 $c = 'chd';
 if (version_compare(PHP_VERSION, '5.4', '<')) {
   $a = ¤::_("ctt.$c"); /* get a value */
   echo 'Child1: ' . $a[0] . BR;
 } else {
   echo 'Child1: ' . ¤::_("ctt.$c")[0] . BR;  /* array dereferencing */
 }

A sobrecarga e a desreferência de valores aplicam-se aos resultados.

Outros padrões

Os suprimentos do Gateway funcionam com os métodos usados ​​com frequência e comumente dados são necessários como propriedades por meio das chamadas estáticas. Ele pode também atuar como o recipiente das instâncias de classe vulgarmente utilizadas. Existem vários padrões para fornecer os serviços e lidar com dependências. A abordagem do gateway oferece funcionalidades semelhantes.

A inicialização do gateway se assemelha ao utilizado para implementar o padrão Singleton, mas instancia a classe comum, em vez de a si mesma, e salva a referência. Você pode modificar o método _init() para assegurar que apenas uma instância é criada.

Aqui está um exemplo da implementação do Service Locator:

$locator = new ServiceLocator()
$locator->set('app', new Application());
$locator->set('db', new Database());
// ...
$locator->get('db')->connect();
$locator->get('app')->run();

Comparada com a implementação do Gateway:

¤::_Init();
¤::_('app', new Application());
¤::_('db', new Database());
// ...
¤::_('db')->connect();
¤::_('app')->run();

A implementação do Gateway no container de injeção de dependências:

¤::('usr', new User(new Auth());
//...
¤::('usr')->Login($creds);

A arte é encontrar um equilíbrio entre a utilização dos dados comum e da passagem de parâmetros.

Conclusão

Em uma aplicação PHP, as funções essenciais devem ser estendidas para as funções personalizadas executarem ações padrão, como as conversões de dados.

Não é muito prático implementar todas as ações elementares como classes separadas, porque isso torna a aplicação demasiado fragmentada em muitas classes pequenas. Reunir todas essas ações elementares em uma classe é muito mais confortável para desenvolver e manter, pois torna o código da aplicação mais fácil de entender.

Os desenvolvedores têm a responsabilidade de decidir o que é o propósito de uma classe ou uma função, quais dados devem ser recuperados de recipientes de dados comuns, e os dados que devem passar como parâmetros para classes ou funções.

O objetivo de usar soluções como o padrão Gateway é evitar a dor de passar valores frequentemente usados ​​para muitos objetos, métodos de classe ou funções. Nesse sentido, o padrão Gateway é uma solução que segue o conceito OOP, o que é uma grande medida, uma vez que isso promove uma melhor encapsulação do código.

Qualquer método de acesso de dados comum cria dependências. Profissionalmente, projetar aplicativos não usa ou minimiza o usuário de variáveis ​​globais. Além disso, ao usar o padrão Gateway, as dependências são tratadas pelo código implementado num único ponto, a classe Gateway.

***

Vallo Reima faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://www.phpclasses.org/blog/post/297-Using-the-Gateway-Pattern-in-PHP-to-Access-Common-Data-From-Anywhere-in-your-Application.html