Pergunta

A minha pergunta é como é que se uma conexão de dados abstrato da camada de modelo de um aplicativo? A principal preocupação é a de ser capaz de mudar facilmente de diferentes tipos de bancos de dados. Talvez você começa com uma lima chata, banco de dados separado por vírgulas. Então você quer se mudar para um banco de dados SQL. Então, mais tarde você decidir uma implementação LDAP seria melhor. Como uma pessoa pode facilmente planejar para algo assim?

Para um exemplo simples, digamos que você tem um usuário com um primeiro nome, sobrenome e e-mail. Uma classe PHP muito simples representá-lo pode ter esta aparência (ignore os problemas com variáveis ??de instância públicas):

<?php

class User {
  public $first;
  public $last;
  public $email;
}

?>

Eu tenho visto freqüentemente onde as pessoas têm uma classe DAO que tem o SQL embutido nele como tal:

<?php

class UserDAO {
  public $id;
  public $fist;
  public $last;
  public $email;

  public function create( &$db ) {
    $sql = "INSERT INTO user VALUES( '$first', '$last', '$email' )";
    $db->query( $sql );
  }
}

?>

O meu problema com estratégias de como este é quando você quer mudar seu banco de dados, você tem que mudar a cada classe DAO criar, atualizar carga, funções de exclusão para lidar com o novo tipo de banco de dados. Mesmo se você tiver um programa de auto-gerá-los para você (que eu não sou particularmente fã de), você teria que editar este programa para fazê-lo funcionar agora.

Quais são as suas sugestões de como lidar com isso?

Minha idéia atual é criar uma classe super para DAO objetos com sua própria criação, funções excluir, atualizar carga. No entanto, estas funções levaria matrizes de atributos do DAO e gerar a consulta em si. Desta forma, a única SQL está na classe SuperDAO ao invés de serem espalhadas várias classes. Então, se você queria mudar sua camada de banco de dados, você só tem que mudar a forma como a classe SuperDAO gera as consultas. Vantagens? Desvantagens? problemas previsíveis? O bom, o mau eo feio?

Foi útil?

Solução

Utilizando um ORM geralmente é a forma preferida de abstrair o banco de dados. Uma lista incompleta de implementações de PHP está disponível em Wikipedia .

Outras dicas

Você pode usar várias estruturas, como DOP, PEAR :: MDB2 ou Zend_Db, mas para ser honesto, em 12 anos de desenvolvimento PHP, eu nunca tive a transição de um tipo de infra-estrutura de armazenamento de dados para outro.

Sua extremamente raros até mesmo ir de algo muito semelhante, como SQLite, o MySQL. Se você fez fazer mais do que isso, você teria problemas muito maiores de qualquer maneira.

Eu vim com um conceito interessante que permitiria desenvolvedor para criar banco de dados agnóstica código, mas ao contrário ORM vai não sacrificar o desempenho :

  • simples de usar (como ORM)
  • DB-agnóstico: funciona com SQL, NoSQL, arquivos etc
  • Sempre consultas otimizar se o fornecedor permite (sub-selecionar, Map-Reduce)

O resultado é Agile dados - banco de dados quadro de acesso (veja o vídeo para explicação detalhada).

Resolver tarefa da vida real com código DB-agnóstico e Dados Agile

  1. Comece por descrevendo modelos de negócios .
  2. Criar persistência $db driver (uma palavra chique para conexão DB), que poderia ser arquivo CSV, SQL ou LDAP.
  3. modelo associado com $db e expressar a sua Action
  4. Executar Action

Neste quadro ponto irá determinar melhor estratégia dadas as capacidades do banco de dados, irá mapear a sua declaração de campos, preparar e executar consultas para você, para que você não tem que escrevê-los.

Exemplo de código

Meu próximo trecho de código resolve um problema bastante complexo de determinar qual é a dívida total atual de todos os nossos clientes VIP . Esquema:

enter descrição da imagem aqui

A seguir é o código independente de fornecedor:

$clients = new Model_Client($db);
// Object representing all clients - DataSet

$clients -> addCondition('is_vip', true);
// Now DataSet is limited to VIP clients only

$vip_client_orders = $clients->refSet('Order');
// This DataSet will contain only orders placed by VIP clients

$vip_client_orders->addExpression('item_price')->set(function($model, $query){
    return $model->ref('item_id')->fieldQuery('price');
});
// Defines a new field for a model expressed through relation with Item

$vip_client_orders->addExpression('paid')
  ->set(function($model, $query){
    return $model->ref('Payment')->sum('amount');
});
// Defines another field as sum of related payments

$vip_client_orders->addExpression('due')->set(function($model, $query){
    return $query->expr('{item_price} * {qty} - {paid}');
});
// Defines third field for calculating due

$total_due_payment = $vip_client_orders->sum('due')->getOne();
// Defines and executes "sum" action on our expression across specified data-set

A consulta resultante se $db é SQL:

select sum(
  (select `price` from `item` where `item`.`id` = `order`.`item_id` )
  * `order`.`qty`
  - (select sum(`payment`.`amount`) `amount` 
     from `payment` where `payment`.`order_id` = `order`.`id` )
) `due` from `order` 
where `order`.`user_id` in (
  select `id` from `user` where `user`.`is_client` = 1 and `user`.`is_vip` = 1 
)

Para outras fontes de dados, a estratégia de execução possa heavy-lift alguns mais dados, mas iria trabalhar de forma consistente.

Eu acho que a minha abordagem é uma ótima maneira de banco de dados abstratos e eu estou trabalhando para implementá-lo sob a licença MIT:

https://github.com/atk4/data

Você deve olhar para o DOP biblioteca.

DOP fornece uma camada de abstração de acesso a dados, o que significa que, independentemente de qual banco de dados você está usando, você usa as mesmas funções para consultas de emissão e buscar dados.

DOP não fornece uma abstração de banco de dados; não reescrever SQL ou emular características ausentes. Você deve usar uma camada de abstração de full-blown se precisar essa facilidade.

A melhor maneira é usar um ORM (mapeamento objeto-relacional) biblioteca. Há uma abundância de-los para PHP. Eu pessoalmente usado e pode recomendar doutrina ORM (Eu usei-o em combinação com silex, que é um framework PHP minimalista).

Aqui é uma discussão StackOverflow sobre ORMs PHP, onde pode encontrar algumas alternativas se você como: Boa PHP ORM Library?

Parece bom em teoria, mas com toda a probabilidade YAGNI .

Você seria melhor fora de usar uma biblioteca de SQL, como DOP e não se preocupar com LDAP até que você chegar lá.

De um modo geral, se você estiver indo para a dificuldade de usar um banco de dados, em seguida, o aplicativo irá beneficiar usando recursos específicos para uma "marca" de banco de dados, e será um aplicativo mais sólida para isso.

É muito raro para passar de um sistema de banco de dados para outro. A única vez que você pode considerar realisticamente que aa pena recurso de execução é se você está escrevendo algum tipo de sistema ou estrutura de baixo acoplamento destinado ao consumo de massa (como o Zend Framework, ou Django).

Eu sempre gostei utilizando ADOdb. Pelo que tenho visto, parece que ele é capaz de alternar entre muito diferentes plataformas.

http://adodb.sf.net

solução fato In para o tópico "onde implementar a lógica de acesso de dados?" não é complexa. Tudo que você tem que lembrar é que o código do modelo deve estar separado do seu código de acesso de dados.

Como:

camada Modelo com alguma lógica de negócios User :: name () método

class User 
{
  public $first;
  public $last;
  public $email;
  public function name ()
  {
      return $this->first." ".$this->last;
  }
}

camada de acesso a dados:

class Link
{
    $this->connection;
    public function __construct ()
    {
        $this->connection = PDO_Some_Connect_Function();
    }
    public function query ($query)
    {
        PDO_Some_Query ($this->connection, $query);
    }

}

class Database
{
    public $link;
    public function __construct ()
    {
        $this->link = new Link();
    }
    public function query ($query)
    {
        $this->link->query ($query);
    }
}

class Users
{
    public $database;
    public function __construct (&$database)
    {
         $this->database = &$database;
    } 
    public save ($user)
    {
        $this->database->link->query ("INSERT INTO user VALUES( '$user->first', '$user->last', '$user->email' ))";
    }

Uso:

$database = new Database();

$users = new Users();

$users->save (new User());

Neste exemplo, é óbvio que você sempre pode mudar o seu acesso de dados de classe link que irá executar consultas em qualquer que seja (Isso significa que você pode salvar seus usuários em qualquer servidor como você mudar link).

Ao mesmo tempo você tem o código camada de modelo limpo que vive de forma independente e não tem idéia de quem e onde está salvando seus objetos.

Além disso classe de banco de dados aqui parece desnecessário, mas na verdade ele pode dar à luz a grandes idéias como a coleta muitos links uma instância para muitas conexões db em um projeto.

Também há fila única estrutura mais simples e todo-poderoso chamado db.php ( http://dbphp.net ) que é construído sobre o padrão que eu descrevi aqui e até mesmo cria tabelas automaticamente com a capacidade para controlar plenamente as suas configurações de campo padrão SQL / mesa e banco de dados de sincronia estrutura para o seu modelo de cada vez que quiser.

Axon ORM detecta automaticamente as alterações em seu esquema sem a necessidade de reconstruir o seu código.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top