Как создать экземпляр моего объекта базы данных для использования в других классах? - PullRequest
3 голосов
/ 07 марта 2011

Я столкнулся с архитектурной проблемой в моем приложении. Я свернул свой собственный (очень простой) MVC, и одна из моих моделей - это объект базы данных: class MySQLDatabase { }

Есть ряд мест, в которых я хотел бы использовать объект моей базы данных, не создавая дублирующихся экземпляров. Внутри моего контроллера я объявил public $db;, а внутри __construct { } у меня есть $this->db = new MySQLDatabase;

Вопрос:

Как мне использовать $db в других моих классах - все они также создаются в __construct { } контроллера ... я бы объявил global $db в начале всех моих классов, которые требуют подключения к базе данных?

Я привык к тому, что глобальные переменные объявляются в глобальной области видимости как обычные переменные, а затем используют ключевое слово global для ссылки на глобальную область видимости ... Я не уверен, применимо ли это к переменным, объявленным в классе (мой контроллер.)

Ответы [ 6 ]

4 голосов
/ 07 марта 2011

Я бы держался подальше от использования глобалов или паттерна Синглтона (который в любом случае является глобальным) и попытался бы найти некоторые альтернативы. Кроме того, вы говорите о соединении с базой данных. Используя шаблон Singleton, вы говорите, что никогда не будет более одного соединения с базой данных, хотя, как правило, это верно для небольших приложений, так как они растут больше, вы не сможете разместить несколько соединения.

Как только вы делаете что-то глобальное, вы теряете автоматические ограничения того, где оно может быть использовано / изменено. Использование MVC представление не должно использоваться ни для чего иного, кроме как для отображения данных, при использовании global / singleton разработчик не должен использовать глобальные переменные. Принимая во внимание, что с другим дизайном у них нет этой опции.

Вы упомянули, что создали свою собственную инфраструктуру MVC, так что я представляю, какие классы вы хотите использовать в ней, это ваши модели? Поправь меня, если они где-нибудь еще.

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

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

Вот несколько примеров паттерна синглтона, если вам интересно:

Там еще много всего ...

3 голосов
/ 07 марта 2011

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

Хорошая статья в блоге на эту тему:

http://www.potstuck.com/2009/01/08/php-dependency-injection/

2 голосов
/ 07 марта 2011

Я думаю, что вы поступаете неправильно, вам не следует выполнять запросы к базе данных от вашего контроллера.

это означает, что приведенное ниже недействительно.

class ControllerIndex extends Controller
{
    public function index()
    {
        $this->db->selectAll("table");
    }
}

Тамдолжен быть слой, который отделяет ваш контроллер от интерфейса вашей базы данных, вот куда входит модель.

У вас должна быть папка моделей, содержащая классы для таких действий, как пользователи, публикации, ведение журнала и т. д.

class Users_Model extends Model
{
    public function getUser($id)
    {
    }
}

Класс модели должен быть частью ядра вашей системы и должен расширять ваш класс базы данных. Таким образом, в главном контроллере вы должны загружать модели через класс ModelLoader.

, например,:

class ModelLoader
{
    private $models = array();

    public function __get($model)
    {
        //load (/application/models/?.php) and initiate it here
        //Storing it in models array above
    }
}

Затем в вашем главном контроллере:

class Controller
{
    private $model;

    public function __construct()
    {
        $this->model = new ModelLoader;
    }
}

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

class Controller_index extends Controller
{
    public function index()
    {
        $user = $this->model->users->getUser(22);
    }
}

Надеюсь, это поможет!

1 голос
/ 07 марта 2011

Не используйте синглтоны.Гораздо лучше явно передавать данные.Например:

abstract class Controller {
  private static $conn; // could be an array for multiple connections
  final protected function getDBConnection() {
    if (!$this->conn) {
      $this->conn = new DBConnection();
    }
    return $this->conn;
  }
  abstract public function process(Request $r);
}

class HomePageController extends Controller {

  public function process(Request $r) {
    $results = $this->getDBConnection()->query('SELECT stuff FROM foo;');
    // do stuff with $results
  }

}

Вы также можете иметь явный объект модели, который вы передаете, например, тот, который представляет пользователя, но это может быть избыточным для вашего проекта.

1 голос
/ 07 марта 2011

Я думаю, что вам нужен единый для вас объект базы данных:)

Подробнее см. Здесь: http://en.wikipedia.org/wiki/Singleton_pattern

Редактировать с примером синглтона для php:

<?php
class UniqueObject {

    private $_uniq = null;

    //private cause you don't want to instanciate the classic way
    private function __construct() {
        //...
    }

    //check if unique object exists or not, then return it
    public static function uniq() {
        if(!self::$_uniq)
            self::$_uniq = new UniqueObject();

        return self::$_uniq;
    }
}

//call your unique object whenever you need it
UniqueObject::uniq();
?>

(уже поздно, надеюсь, я не ошибся :))

0 голосов
/ 07 марта 2011

Вам нужно будет использовать шаблон синглтона. Они приводят примеры в документах php

<?php
class Example
{
    // Hold an instance of the class
    private static $instance;

    // A private constructor; prevents direct creation of object
    private function __construct() 
    {
        echo 'I am constructed';
    }

    // The singleton method
    public static function singleton() 
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }

    // Example method
    public function bark()
    {
        echo 'Woof!';
    }

    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

}

?>

http://php.net/manual/en/language.oop5.patterns.php

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