Создание синглтона - это правда? - PullRequest
0 голосов
/ 15 февраля 2011

Я пытаюсь создать свой собственный облегченный, но ООП-способ для отслеживания загруженных файлов и их соответствующих версий (еще не реализованных) в моей среде PHP, чтобы иметь возможность легко тестировать проблемы с зависимостями в будущем.

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

class loadRegistry {

    private static $registry = null;

    private function __construct(){

        if (is_null(self::$registry));
        self::$registry = array();

    }

    public static function get() {
        return self::$registry;
    }

    public static function set($filename){

        if ( isSet( self::$registry[$filename]) AND !empty($filename) ) {
            throw new Exception("File already loaded");
        }
        else self::$registry[$filename] = '';
    }

}

loadRegistry::set('filename');
loadRegistry::set('filename2');

$reg = loadRegistry::get();

Ответы [ 4 ]

2 голосов
/ 15 февраля 2011

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

Вы можете прочитать о паттерне Singleton в PHP в официальном руководстве; http://php.net/manual/en/language.oop5.patterns.php

Приведенный выше ручной пример дает простой пример, но у меня никогда не было необходимости использовать Singleton в PHP с момента выпуска PHP5. Они более полезны на устройствах, таких как iPhone, где вам нужен только один интерфейс для определенной части оборудования, например, экрана. Тем не менее, я думаю, вы можете использовать его для подключения к БД в приложении PHP ...

2 голосов
/ 15 февраля 2011

Нет, это не синглтон.Вы на самом деле играете только со статическими свойствами.Синглтон был бы больше похож на это:

class Registry {

    private static $registry = null;
    private $data;

    private function __construct(){
        $this->data = array();
    }

    public static function getInstance() {
        if (is_null(self::$registry)) {
            self::$registry = new Registry();
        }
        return self::$registry;
    }

    public function set($filename){
        if (isset($this->data[$filename]) && !empty($filename) ) {
            throw new Exception("File already loaded");
        }
        else {
            $this->data[$filename] = '';
        }
    }

    // further **instance** methods
}

$reg = Registry::getInstance();
$reg->set('filename');
$reg->set('filename2');

Я не знаю, можно ли установить конструктор как частный в PHP ... Я думаю, что нет.* Существует разница между статическими классами $ и синглтоном.Синглтон позволяет иметь только один экземпляр за раз.Для статических классов вам даже не нужен экземпляр.Кроме того, статические свойства являются общими для всех экземпляров класса (в случае, если вы создаете экземпляр).

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

$: реальных статических классов нет.Только члены могут быть определены как статические.Я бы сказал, что класс, имеющий только статические члены, можно назвать статическим классом.

1 голос
/ 15 февраля 2011

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

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

Вот вам синглтон:

class Singleton {
   private static $me;

   private function __construct 
   { 
       /* something */ 
   }

   public static getInstance() 
   {
      if(empty(self::$me)) self::$me = new self;
      return self::$me;
   }

}

Вот улучшенный синглтон 5.3+:

class Singleton {
   private static $me;

   private function __construct 
   { 
      /* something */ 
   }

   public static getInstance() 
   {
      if(empty(self::$me)) self::$me = new static;
      return self::$me;
   }

}

0 голосов
/ 23 мая 2011

Я вижу, что это немного устарело, однако ..

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

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

Основная идея:

  1. Есть реестр

  2. В самом начале создается только экземпляр класса базы данных, таким образом, мы не беспокоимся о создании соединений и т. Д. Я использую две базы данных, и соединение не создается до тех пор, пока в первый раз мне это не понадобится .

    $ registry-> dbManager = new dbManager ();

  3. Передача объекта реестра в реестр базовых классов маршрутизатора, контроллера и модели наблюдается повсеместно.
    $ registry = My_Registry :: singleton (); $ registry-> router = новый маршрутизатор ($ registry); $ registry-> dbManager = new dbManager (); и т.д. ..................

  4. Класс БД остается обычным классом, это только часть класса БД

    класс dbManager {

    //DB Connections
    private  $Internal_db_con = null;
    private  $Business_db_con = null;
    
    //DB Connection Parameters
    private  $host=null;
    private  $user=null;
    private  $pass=null;
    
    //DB Names
    private  $internal_db_name=null;
    private  $business_db_name=null;    
    
    //
    private $result = null;
    
    
    
    //   only one object created
    public  function __construct()
    { 
            include_once __SITE_PATH . 'includes/db_config.inc';
    

    список ($ this-> host, $ this-> user, $ this-> pass, $ this-> internal_db_name, $ this-> business_db_name) = $ db_conf;

    }
    
    
    
    
    //set  internal database connection
    private function setInternalDBCon()
    { debug('setInternalDBCon called');
                try{    
                    # MySQL with PDO_MYSQL  
                    $dbq="\"";
                    $this->Internal_db_con = new 
    

    PDO ("mysql: host =". $ This-> host. "; Dbname =". $ This-> internal_db_name, $ this-> user, $ this-> pass, массив (PDO :: MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

    $this->Internal_db_con->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                    }  
                catch(PDOException $e) 
                {  
                echo 'Error connecting to MySQL: ' .$e->getMessage();  
                }    
    
    }
    
    
    
    
    
    
    //set  business database connection
    public  function setBusinessDBCon()
    { 
                try{    
                # MySQL with PDO_MYSQL  
                $dbq="\"";
                $this->Business_db_con = new 
    

    PDO ("mysql: host =". $ This-> host. "; Dbname =". $ This-> internal_db_name, $ this-> user, $ this-> pass, массив (PDO :: MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

    $ this-> Business_db_con-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); }
    поймать (PDOException $ e) {
    echo 'Ошибка подключения к MySQL:'. $ e-> getMessage ();
    }

    }
    
    
    
    
    
    
    /*check if a row exists in a safe way that avoids sql atack*/
    public  function uniqueRowExists($dbcon, $table,$col_name, $data)
    {    
            //check if connection is set 
            if($this->{$dbcon.'_db_con'}==null) //dynamic variable call
        $this->callMyFunc( 'set'.$dbcon.'DBCon');  //dynamic function call
    

    ....................... и т.д. ....

            //prepare
            $stmt =  $this->{$dbcon.'_db_con'}->prepare($sql);
        $stmt->execute($data);
    

    ................. и т. Д.

  5. И вот как я вызываю публичную функцию из класса DB

    // запросим базу данных
    $ Результат = $ this-> registry-> dbManager-> uniqueRowExists («Internal», «internal_user», Array («uname», «pass»), $ input); // соединение на выбор, таблица, столбцы, массив данных для поиска

таким образом, где-то есть только один экземпляр.

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