2010-07-26 2 views
2

J'essaie de créer un script dans lequel différentes classes (par exemple, Database, Utilities, Config) sont utilisées pour former une classe Main centrale. J'ai essayé l'extension d'une chaîne d'entre eux:

principal -> Utilitaires -> Base de données -> Configuration

Mais comment puis-je régler les différentes parties afin qu'ils puissent être appelés comme ceci:

<?php 

    $this->db->select("WAFFLES"); 
    echo($this->config->app_path); 

?> 

Répondre

1

Vous devez déclarer chaque nouvel objet comme variable dans votre classe principale comme:

class Main{ 

    private $db = NULL; 
    private $config = NULL; 

    $this->db = new Database; 
    $this->config = new Config; 

} 

etc.

Même si je ne suis pas un codeur professionnel, je vais envisager une meilleure approche que celle-ci. Ce type de manipulation d'objets peut provoquer une classe principale trop lourde et, dans le pire des cas, vous pouvez rencontrer des problèmes de performances.

0

Voici le prototype de l'échantillon:

include 'db.php'; // include db class 
include 'config.php'; // include config class 

class main{ 
    public $db = NULL; 
    public $config = NULL; 

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

} 
3

Vous pouvez créer une classe mondiale que vous ne base d'initialisation

class Base { 

$var1, var2; 

public function __construct() { 
    $this->var1 = new DB(); 
    $this->var2 = new Config(); 
    .... 
} 
} 

Ensuite, vos classes peuvent étendre la classe de base et d'avoir accès aux données

class Foo extends Base { 

    public function bar() { 
    $this->var1->someOpertaion(); 
    } 
} 
0

Création d'un objet composite avec des instances de tout ce qui pourrait être nécessaire pendant L'exécution de code g à l'avant est un gaspillage complet de ressources. Vous souhaitez créer des instances uniquement en cas de besoin. Une façon d'y parvenir serait d'ajouter une méthode magique __get à la classe:

public function __get($name) { 
    // if self::$instances (or main) contains instance of $name, return instance 
    // else if class_exists $name, create, store and return instance 
    // else throw exception 
} 

Mais même alors, les chances sont que vous créez une God Object et les méthodes magiques sont un peu plus lent que accesseurs réguliers. Si vous avez besoin de créer des instances de cette manière, jetez un œil au Symfony Dependency Injection Container ou implémentez un Registry.

1

1) utilisent __autoload ou spl_autoload_register pour charger les classes

2) utiliser des méthodes magiques, pour appeler la fonction lors de l'obtention propriété inconnue. Les exemples suivants montrent comment utiliser __get et dynamicaly initialize object uniquement lorsque vous les utilisez.

//use __autoload to load db and config class when they are called. 
class db{ 
    function lol(){ 
    echo 'Hello from db->lol() <br />'; 
    } 
} 
class config{ 
    function lol(){ 
    echo 'Hello from config->lol() <br />'; 
    } 
} 


//Manager class to use with classes where you want to access other object trough $this 
class Manager{ 
    private $_instances=array(); 
    function __get($name){ 
    //if instance does not exists, create one 
    if (!isset($this->_instances[$name])){ 
     $this->_instances[$name]=new $name(); 
    } 

    //return instance 
    return $this->_instances[$name];  
    } 

} 

class Some extends Manager{ 
    function f1(){ 
    $this->db->lol(); 
    $this->config->lol(); 
    } 
} 

$some=new Some(); 
$some->f1(); //echoes 'Hello from db->lol()' and 'Hello from config->lol()' 

Mais pour accéder à des instances de classe mondiale, je préfère utiliser la méthode suivante: Utiliser modèle singleton pour accéder GloballClass global creux de classe :: i() et si la classe mondiale ne définit pas l'utilisation autoload pour charger cette classe.

class db extends mysqli{ 
    private static $_i; 
    //Access to singleton instance 
    public static function i() {  
    return (self::$_i instanceof self)?self::$_i:self::$_i = new self(); 
    } 

    //class functions 
    function q($q){ 
    echo 'Hello from db->q()'; 
    } 
} 

class config{ 
    private static $_i; 
    //Access to singleton instance 
    public static function i() {  
    return (self::$_i instanceof self)?self::$_i:self::$_i = new self(); 
    } 

    //class functions 
    function somefunction(){ 
    echo 'Hello from config->somefunction()'; 
    } 
} 


db::i()->q('SELECT * FROM users'); 
config::i()->somefunction(); 

Suite est une solution inspirée par Gordons commentaire: Il utilise la classe GlobalClassFactory pour définir une seule instance de classes mondiales.

class db{ 
    function lol(){ 
    echo 'Hello from db->lol() <br />'; 
    } 
} 
class config{ 
    function lol(){ 
    echo 'Hello from config->lol() <br />'; 
    } 
} 

class GlobalClassFactory{ 
    private static $_classes=array(); 
    public static function getInstance($name){ 
    if (!isset(self::$_classes[$name])){ 
     self::$_classes[$name]=new $name(); 
    } 
    return self::$_classes[$name]; 
    } 
} 

class Base{ 
    function __get($name){ 
    return GlobalClassFactory::getInstance($name); 
    } 
} 

class Some extends Base{ 
    function f1(){ 
    $this->db->lol(); 
    $this->config->lol(); 
    } 
} 

$some=new Some(); 
$some->f1(); 
+0

La sous-classification d'une classe de base générale est presque toujours une mauvaise idée. Vous créez une relation qui dit 'Some' * is-a *' Manager', quand ce n'est vraiment pas le cas.De même, si vous stockez les instances en tant qu'instances d'objet, toute classe développant le gestionnaire créera des instances séparées uniquement pour lui-même, ce qui dans le cas de db et de config est peu probable. Les singletons peuvent atténuer cela, mais étant donné que Singletons ne peut pas être instancié avec 'new', le code dans' __get' ne fonctionnera plus. Et les Singletons sont généralement une mauvaise idée de toute façon. – Gordon

+0

Vous avez raison, Gordon, j'ai donc créé une solution où une seule instance de chaque classe globale est créée. Mais pourquoi les Singletons sont une mauvaise idée? – codez

+0

Vous venez d'échanger le problème :) Comment créez-vous non-Singleton maintenant? En outre, vous créez toujours une relation * is-a * et maintenant vous avez également couplé la classe Base à l'usine en la codant en dur dans la méthode '__get', réduisant ainsi efficacement la classe Base à un getter magique. Je veux dire, bien sûr que cela fonctionne, mais c'est une mauvaise conception IMO. Essayez d'éviter les choses * globales *. – Gordon