2012-11-01 4 views
5

Ecriture de ma première application en PHP qui utilise des classes et des objets. J'ai une classe DB qui prend une chaîne pour sélectionner la configuration appropriée car il y a plusieurs bases de données. J'ai commencé avec une classe de connexion, mais j'ai gratté cette idée en échange d'une classe d'utilisateur afin que je puisse faire des choses utilisateur-> isLoggedIn. La classe d'utilisateurs utilise MySQL qui stocke les informations d'utilisateur et de connexion, ainsi que les informations d'identification pour la deuxième base de données.Nouveau sur OOP PHP, demande de guidence, partage de données entre classes design

$mysql = new db('mysql'); 

$user = new user($mysql); 
if(!($user->isLoggedIn() === true)) 
{ 
    goToPage('login.php'); 
    exit(); 
} 

La deuxième base de données est Sybase et stocke les informations de compte. J'ai besoin des informations d'identification de la classe d'utilisateurs pour obtenir des informations sur les listes et les comptes d'ici. Je pense qu'une classe de compte devrait être la prochaine, mais pas sûr de la meilleure façon de le faire. Quelque chose comme ça peut-être ..

$sybase = new db('sybase'); 

$account = new account($sybase); 

$account_list = $account->getList($user->info); 

$ user-> Lire les infos un tableau je suppose que des pouvoirs et des informations nécessaires à la table de compte, ou est-il une meilleure façon d'aller à ce sujet?

Edité d'inclure par exemple de classe db

config.db.php

$config_array = array(); 

$config_array[ 'mysql' ][ 'dsn' ] = "mysql:host=localhost;dbname=********;charset=UTF-8"; 
$config_array[ 'mysql' ][ 'user' ] = "********"; 
$config_array[ 'mysql' ][ 'pass' ] = "**************"; 

$config_array[ 'sybase' ][ 'dsn' ] = "odbc:DRIVER={Adaptive Server Anywhere 8.0};***************"; 
$config_array[ 'sybase' ][ 'user' ] = "**********"; 
$config_array[ 'sybase' ][ 'pass' ] = "*********"; 

class.db.php

public function __construct($type) 
{ 
    require 'config.db.php'; 

    $this->type = $type; 

    foreach($config_array[ $this->type ] AS $key => $value) 
    { 
     $this->$key = $value; 
    } 

    try 
    { 
     $this->connection = new PDO($this->dsn, $this->user, $this->pass, $this->options); 
    } 
    catch(PDOException $ex) 
    { 
     log_action("db->" . $this->type, $ex->getCode() . ": " . $ex->getMessage()); 
     $this->error = true; 
    } 
    return $this->connection; 
} 

Est-ce que quelque chose comme logique ?

class User() 
{ 
    public function getAccountList() 
    { 
     $this->Account = new Account(new Database('sybase')); 
     return $this->Account->list($this->userid); 
    } 
} 

En outre, les comptes ont des sections différentes (à savoir l'histoire & Notes, transactions financières, documents) qui seront différents 'onglets' sur la page. Est-ce que chacun d'entre eux devrait aussi être une classe? Merci.

+0

Je ne comprends pas vraiment la différence entre un utilisateur et un compte dans ce scénario. Ne sont-ils pas la même chose? Ou l'utilisateur est la personne connectée, et les comptes sont des choses auxquelles ils essaient d'accéder? –

+0

L'utilisateur est simplement une personne connectée. Userid et pass sont stockés dans mysql sur le serveur web. pas de registre - nous configurons les utilisateurs et donnons des informations d'identification pour la deuxième base de données. informations sur le compte (deuxième base de données) est stocké dans sybase sur le serveur distant – bdscorvette

+0

Ok, cela a du sens. Mon travail est plus de gestion de compte que de codage ces jours-ci, donc j'ai tendance à penser à "comptes" et "utilisateurs" comme la même chose ;-). –

Répondre

2

Première place, comme une réponse secondaire autre réponse par Dimitry:

Les choses que vous gagnez en ayant un Singleton pâle aux choses que vous perdez. Vous obtenez un objet global, que chaque partie de votre programme peut lire et modifier, mais vous perdez la testabilité, la lisibilité et la maintenabilité. Comme l'objet Singleton est en fait global, vous ne pouvez pas isoler avec précision les unités individuelles de votre application (ce qui est crucial pour Unit Testing), car votre fonction dépend d'autres composants qui y sont "magiquement" insérés.

Vous perdez la lisibilité car method() peut réellement besoin d'autres choses à travailler (par exemple, l'objet user a besoin d'une instance db, ce qui rend new user($db) beaucoup plus lisible que new user(), parce que même sans regarder le code source, je peux dire ce que la méthode/l'objet doit fonctionner

Vous perdez la maintenabilité pour la raison indiquée ci-dessus.Il est plus difficile de dire quels composants sont insérés via le Singleton que de le voir dans le "contrat" ​​de la fonction, pour cette raison, il sera plus difficile pour vous et/ou tout autre développeur de lire et de refactoriser votre code.


Comme une note de côté, il est considéré comme une bonne convention de nommage pour nommer Class noms avec sa première lettre tubé supérieure, je vais utiliser cette convention à partir de maintenant.

Commençons par le haut. Vous avez 2 états possibles pour votre objet Db, MysqlDb et SybaseDb. Cela appelle un polymorphisme. Vous avez un résumé classe Db, et deux béton classes MysqlDb et SybaseDb en héritant. L'instanciation de l'objet correct Db est la responsabilité d'un Maintenant, vous devriez vous demander usine

class DbFactory { 

    private $db; 

    /** 
    * Create a new Db object base on Type, and pass parameters to it. 
    * 
    * @param string $type Type of database, Mysql or Sybase. 
    * @param string $dsn The DSN string corresponding to the type. 
    * @param string $user User credential 
    * @param string $pass Password credential 
    * 
    * @return Db 
    */ 

    public function create($type, $dsn, $user, $pass) { 
     if (!is_a($this->db, "Db")) { 
      $type  = $type . "Db"; 
      $this->db = new $type($dsn, $user, $pass); 
     } 

     return $this->db; 
    } 
} 

abstract class Db { 

    /** 
    * @param $dsn 
    * @param $user 
    * @param $pass 
    */ 
    public function __construct($dsn, $user, $pass) { 
     $this->db = new PDO("$dsn", $user, $pass); 
     $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
    } 
} 

class MysqlDb extends Db { 

    /* 
    * More specific, Mysql only implementation goes here 
    */ 
} 

class SybaseDb extends Db { 

    /* 
    * More specific, Sybase only implementation goes here 
    */ 
} 

, qui est responsable pour obtenir la liste des comptes? Assurément, ils ne devraient pas aller chercher eux-mêmes (tout comme il n'est pas de la responsabilité de l'utilisateur d'extraire ses propres données de la base de données). C'est la responsabilité de User d'aller chercher ces comptes, en utilisant la connexion SybaseDb.

En fait, le besoin User ce qui suit au travail:

  • connexion base de données Sybase - de récupérer la liste des comptes. Nous lui passerons l'instance DbFactory, afin que nous puissions facilement obtenir l'instance si elle était déjà instanciée, et l'instancier si ce n'est pas le cas.
  • Informations d'état (état connecté, ID utilisateur, nom d'utilisateur, etc.).

Le User n'est pas responsable de définir ces données, il a besoin dans le but de travailler.

Ainsi, le constructeur User devrait ressembler à ceci (en supposant "ID" et "name" champs):

User::__construct($id, $name, DbFactory $factory); 

Le User aura un champ $accounts, qui détiendrait un tableau de Account objets. Ce tableau serait rempli avec une méthode User::getAccounts().

+0

Merci. Très informatif Je pense que je comprends ce que vous dites au sujet de leur responsabilité et de ce dont ils ont besoin pour travailler. L'utilisateur obtiendrait ses comptes. Les comptes ne seraient pas eux-mêmes. Mais, sûrement, Compte doit aussi être un objet? Les comptes ont des transactions financières, l'historique, les notes, les factures, etc. – bdscorvette

+0

En effet. L'utilisateur aurait ** une ** propriété '$ accounts', ce qui serait ** un tableau d'objets' Account' **. Cela vous aidera à encapsuler facilement quel compte appartient à quel utilisateur. –

-1

Je créerais Account le membre de la classe User. "L'utilisateur a un compte", non?

De même, en parlant de classes, assurez-vous que vos deux DB sont des singletones, et obtenez-les via getInstance(), et non __construct().

+0

Merci. Je pense que je dis plus précisément que l'utilisateur ** a accès ** à une gamme de comptes.par exemple, l'administrateur a accès à tous les comptes, tandis que les clients et les employés (comme les vendeurs) ont accès à une gamme limitée de comptes. Ces plages ou limites à l'autre base de données sont appliquées par un «code client» que nous appelons. Je suis en train d'éditer l'OP pour inclure un exemple de classe db. S'il vous plaît aidez-moi à comprendre ce que je vais gagner en passant à un singleton avec un getInstance() (Je pense que je comprends ce qu'est un singleton, peut-être pas) – bdscorvette

+0

Vous ne trouverez nulle part bon avec un Singleton. Je peux te donner ça. –