PHP Object Extension $ this-> some_object-> метод - PullRequest
2 голосов
/ 26 июля 2010

Я пытаюсь создать сценарий, в котором разные классы (например, База данных, Утилиты, Конфиг) используются для формирования одного центрального Главного класса. Я попытался расширить их цепочку:

Главная -> Утилиты -> База данных -> Конфигурация

Но как мне установить разные части так, чтобы они могли называться так:

<?php

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

?>

Ответы [ 5 ]

3 голосов
/ 26 июля 2010

Вы можете создать глобальный класс, который выполняет базовую инициализацию

class Base {

 $var1, var2;

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

Тогда ваши классы могут расширять базовый класс и иметь доступ к данным

class Foo extends Base {

  public function bar() {
    $this->var1->someOpertaion();
  }
}
1 голос
/ 26 июля 2010

1) использовать __autoload или spl_autoload_register для загрузки классов

2) использовать магические методы для вызова функции при получении неизвестного свойства.В следующих примерах показано, как использовать __get и динамически инициализировать объект только при их использовании.

//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()'

Но для доступа к экземплярам глобального класса я предпочитаю использовать следующий метод: Использовать шаблон синглтона для доступа к глобальному классу через GloballClass :: i() и если глобальный класс не определен, используйте автозагрузку для загрузки этого класса.

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();

Ниже приводится решение, основанное на комментарии Гордона: он использует класс GlobalClassFactory для определения только одного экземпляра глобальных классов.

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();
1 голос
/ 26 июля 2010

Вам необходимо объявить каждый новый объект как переменную в вашем главном классе, например:

class Main{

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

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

}

и т.д.

Хотя я не профессиональный кодер, я рассмотрю лучший подход, чем этот. Этот тип обработки объектов может вызвать раздутый основной класс, и в худшем случае вы можете столкнуться с некоторыми проблемами с производительностью.

0 голосов
/ 26 июля 2010

Создание составного объекта с экземплярами всего, что может понадобиться во время выполнения кода, является пустой тратой ресурсов. Вы хотите создавать экземпляры только при необходимости. Один из способов добиться этого - добавить в класс магический метод __get:

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
}

Но даже тогда, скорее всего, вы создаете Объект Бога , и магические методы несколько медленнее, чем обычные средства доступа. Если вам нужно создавать экземпляры таким образом, взгляните на Контейнер внедрения зависимостей Symfony или внедрите Registry .

0 голосов
/ 26 июля 2010

Вот образец прототипа:

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;
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...