Как избежать использования глобальных объектов PHP? - PullRequest
6 голосов
/ 18 июля 2009

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

Существует два класса / объекта, к которым было бы полезно иметь глобальный доступ (подключение к базе данных mysqli и пользовательский класс, который проверяет, вошел ли пользователь в систему).

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

Ответы [ 4 ]

13 голосов
/ 18 июля 2009

Вы можете сделать объекты статическими, тогда у вас есть доступ к ним где угодно. Пример:

myClass::myFunction();

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

Expanded

Я думаю, что вы пытаетесь сделать, очень похоже на то, что я делаю с моим классом БД.

class myClass
{
    static $class = false;
    static function get_connection()
    {
        if(self::$class == false)
        {
            self::$class = new myClass;
        }
        return self::$class;
    }
    // Then create regular class functions.
}

Что происходит после того, как вы получите соединение, используя $ object = myClass :: get_connection (), вы сможете регулярно выполнять любые функции.

$object = myClass::get_connection();
$object->runClass();

Expanded

Как только вы сделаете это статическое объявление, вам просто нужно вызвать get_connection и присвоить возвращаемое значение переменной. Тогда остальные функции могут иметь то же поведение, что и класс, который вы вызвали с помощью $ class = new myClass (потому что именно это мы и сделали). Все, что вы делаете, это храните переменную класса внутри статического класса.

class myClass
{
    static $class = false;
    static function get_connection()
    {
        if(self::$class == false)
        {
            self::$class = new myClass;
        }
        return self::$class;
    }
    // Then create regular class functions.
    public function is_logged_in()
    {
        // This will work
        $this->test = "Hi";
        echo $this->test;
    }
}

$object = myClass::get_connection();
$object->is_logged_in();
8 голосов
/ 18 июля 2009

Вы можете передать текущие глобальные объекты в конструктор.

<?php
  class Foo {
    protected $m_db;
    function __construct($a_db) {
      $this->m_db = $a_db;
    }
  }
?>
3 голосов
/ 10 августа 2013

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

Я собираюсь показать несколько строк моего файла bootstrap.php (все мои запросы отправляются через этот файл, но вы можете достичь того же результата, включив его в начало каждого файла), чтобы показать вам, что Я имею в виду. Это довольно здоровенная версия того, что вы, вероятно, использовали бы в своей ситуации, но, надеюсь, идея полезна. (Это все немного модифицировано.)

 //bootstrap.php

...

// CONSTRUCT APPLICATION

{       
    $Database = new Databases\Mysql(
        Constant::get('DATABASE_HOST'),
        Constant::get('DATABASE_USER'),
        Constant::get('DATABASE_PASSWORD'),
        Constant::get('DATABASE_SCHEMA')
    );

    $Registry     = new Collections\Registry;
    $Loader       = new Loaders\Base;
    $Debugger     = new Debuggers\Dummy; // Debuggers\Console to log debugging info to JavaScript console

    $Application  = new Applications\Base($Database, $Registry, $Loader, $Debugger);
}

...

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

Объект базы данных не требует пояснений. Объект реестра действует как контейнер для объекта, к которому я могу обратиться в другом месте приложения. Загрузчик действует как утилита для загрузки других ресурсов, таких как файлы шаблонов. И отладчик для обработки вывода отладки.

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

Хорошо, теперь вернемся к вопросу. Как вы даете другим объектам доступ ко всему этому? Вы просто передаете это в качестве аргумента конструктору.

// still bootstrap.php

...

// DISPATCH APPLICATION

{
    $Router = new Routers\Http($Application);
    $Router->routeUri($_SERVER['REQUEST_URI']); 
}

...

Не только это, но мой Маршрутизатор (или любой другой объект, который я создаю с его помощью) также более гибок. Теперь я могу просто создать экземпляр объекта приложения по-другому, и мой маршрутизатор будет вести себя соответственно по-другому.

1 голос
/ 18 июля 2009

Ну, если у вас уже есть какой-то объект, с помощью которого вы ссылаетесь на систему блогов, вы можете объединить эти объекты в него, чтобы они были $blog->db() и $blog->auth() или чем-то еще.

...