2009-11-11 4 views
-1

Il est difficile d'expliquer cette situation, mais s'il vous plaît voir l'exemple.Base de données et les pratiques OOP en PHP

J'ai codé un site Web où la page se charge, j'initialise une classe de base de données. J'ai envoyé cette classe en tant que paramètre de fonction à toutes les fonctions qui ont besoin d'accéder à la base de données.

Je sais que c'est une mauvaise approche mais actuellement je n'ai aucune idée de la façon de le faire d'une autre manière. Pouvez-vous m'aider s'il vous plaît.

Exemple

class sms { 

    function log_sms($message, $db) { 

     $sql = "INSERT INTO `smslog` SET 
      `mesasge` = '$message' 
      "; 
     $db->query($sql); 

     if ($db->result) 
      return true; 
     return false; 
    } 

} 

puis sur la page principale ..

$db = new db(username,pass,localhost,dbname); 

$sms = new sms; 

$sms->log_sms($message, $db); 

Y at-il une meilleure approche que cela?

Répondre

8

il y a plusieurs options comment résoudre le problème des dépendances (objet A nécessite l'objet B):

injection constructeur

class Sms { 
     function __construct($db) .... 
    } 

    $sms = new Sms (new MyDbClass); 

injection setter

class Sms { 
     protected $db; 
    } 
    $sms = new Sms; 
    $sms->db = new MyDbClass; 

'registre' pattern

class Registry { 
    static function get_db() { 
      return new MyDbClass; 
}} 

class Sms { 
     function doSomething() { 
      $db = Registry::get_db(); 
      $db->.... 
    }} 

'localisateur de services' pattern

class Loader { 
    function get_db() { 
      return new MyDbClass; 
}} 

class Sms { 
     function __construct($loader) { 
     $this->loader = $loader; 

     function doSomething() { 
      $db = $this->loader->get_db(); 
      $db->.... 
    }} 

    $sms = new Sms(new Loader); 

automatisé injection de dépendance basée sur les conteneurs, voir par exemple http://www.sitepoint.com/blogs/2009/05/11/bucket-is-a-minimal-dependency-injection-container-for-php

interface DataSource {...} 
    class MyDb implements DataSource {...} 

    class Sms { 
     function __construct(DataSource $ds) .... 


    $di = new Dependecy_Container; 
    $di->register('DataSource', 'MyDb'); 
    $sms = $di->get('Sms');  

pour ne citer que quelques-uns;)

aussi l'article de Fowler je vous ai donné avant vaut vraiment la peine d'être lu

+0

avez-vous une idée des temps de traitement de chacun? qui est plus rapide et qui est plus lent? Ou s'il n'y a pas beaucoup de différence alors chose du constructeur semble le plus simple pour moi :) –

+0

Ooh, belle vue d'ensemble. Merci :) – Svish

+0

Vous et moi comprenons les modèles 'Registry' et' ServiceLocator' différemment. Pour moi, votre registre ressemble à un ServiceLocator (un registre qui sait comment instancier des objets) et votre ServiceLocator ressemble bien ... à un ServiceLocator qui est implémenté dans une autre classe via la composition. Et rien ici ne ressemble à un registre. –

2

Pour commencer, vous pouvez créer une variable $ db protégée dans chacune de vos classes qui ont besoin d'utiliser la base de données. Vous pouvez ensuite passer $ db dans le constructeur de la classe. Voici le code mis à jour:

$db = new db(username,pass,localhost,dbname); 
$sms = new sms($db); 
$sms->log_sms($message); 

class sms { 

    protected $db; 

    public function __construct($db) { 
     $this->db = $db; 
    } 

    public function log_sms($message) { 
     $sql = "INSERT INTO `smslog` SET 
       `mesasge` = '$message' 
       "; 
     $this->db->query($sql); 

     if ($this->db->result) 
       return true; 
     return false; 
    } 
} 

Cet exemple est en PHP 5.

+0

est c'est le meilleur moyen? J'ai presque 14 classes, alors dois-je ajouter un constructeur à chacun d'eux? P.S Ceci est pour un site Web de réseautage social –

+1

Il n'y a pas de meilleure façon. L'approche de cballou donne certainement un bon moyen. Afin de savoir si c'est un bon moyen pour vos 14 classes, nous aurions besoin de savoir ce qu'elles sont. Dans tous les cas, si vous avez des méthodes sur ces 14 classes comme log ($ msg, $ db) vous devrez passer l'objet $ db autant de fois (probablement même plus) que vous le feriez en le passant en tant que constructeur argument. – koen

+0

Oui par 14 classes je veux dire que j'ai 14 classes de plus qui ont besoin de l'utilisation de DB classe (comme le profil, usersettings, albums, vidéos, auth, messages, réseaux, références, mises à jour etc) et oui je fournis db dans chacun des arguments de la méthode. J'utilise $ db comme argument pour environ 50 méthodes ou plus, je crois. Cela ne me dérange pas de changer le code complet s'il y a un meilleur moyen, car il y a beaucoup plus de choses à ajouter sur le site. –

0

Vous pouvez soit avoir une classe statique qui a deux listes, l'une des connexions disponibles, l'autre des connexions remis, et juste avoir un pool de connexion. Ou, si vous utilisez quelque chose qui a un temps de connexion rapide, comme MySQL, alors créez simplement la connexion dans votre classe de base de données, faites toutes les requêtes nécessaires pour cette fonctionnalité, puis fermez-la. C'est mon approche préférée.

+0

Je n'utilise qu'une seule connexion pour économiser des ressources car le site est sur un serveur partagé lol –

+0

Alors pourquoi ne pas simplement mettre en file d'attente les requêtes, les traiter, et transmettre les résultats dans un rappel, emballé, sinon vous rencontrerez des problèmes deux threads essaient d'utiliser la même connexion. –

+0

Je ne peux pas, parce que j'ai écrit une classe pour chaque fonction, comme une classe pour authentifier l'utilisateur, un pour obtenir les détails des utilisateurs, un pour lire les boîtes de réception des utilisateurs et ainsi de suite. qui initialise au-dessus du fichier d'index et les méthodes sont traitées l'une après l'autre Chaque méthode a la requête pour extraire seulement les choses requises et retourner un tableau. Le code HTML est rendu sur une page de modèle comme MVC. Donc la deuxième requête est exécutée seulement après la première. Cependant je déteste ajouter $ db sur chaque fonction et j'ai une perception si cela ralentit –

1

Singleton est également une bonne pratique dans la conception d'applications. Ils sont très utiles pour éviter les requêtes répétées ou les calculs lors d'un appel. Passer l'objet de base de données à chaque méthode ou constructeur n'est pas une très bonne idée, utilisez plutôt Singleton. Développez votre base de données ou insérez une méthode statique dans votre classe DB.(Je qualifierais aussi pour config dans les db méthode constructeur)

class database extends db 
{ 
    public static function instance() 
    { 
     static $object; 

     if(!isset($object)) 
     { 
      global $config; 

      $object = new db($config['username'],$config['pass'],$config['localhost'],['dbname']); 
     } 

     return $object; 
    } 
} 

rendre votre méthode statique

class sms { 

    public static function log($message) { 

     $sql = "INSERT INTO `smslog` SET `mesasge` = '$message'"; 

     database::instance()->query($sql); 

     return (bool) database::instance()->result; 
    } 
} 

La prochaine fois que vous devez vous connecter sms juste faire appel statique comme celui-ci

sms::log($message);