Tworzenie wzorca Singleton design w PHP5

Jak stworzyć klasę Singleton używając klas PHP5?

Author: beatnik, 2008-10-15

20 answers

/**
 * Singleton class
 *
 */
final class UserFactory
{
    /**
     * Call this method to get singleton
     *
     * @return UserFactory
     */
    public static function Instance()
    {
        static $inst = null;
        if ($inst === null) {
            $inst = new UserFactory();
        }
        return $inst;
    }

    /**
     * Private ctor so nobody else can instantiate it
     *
     */
    private function __construct()
    {

    }
}

Do użycia:

$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();

$fact == $fact2;

Ale:

$fact = new UserFactory()

Wyrzuca błąd.

Zobacz http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static aby zrozumieć zakres zmiennych statycznych i dlaczego ustawienie static $inst = null; działa.

 252
Author: nlaq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-09 13:22:40

PHP 5.3 umożliwia tworzenie dziedziczonej klasy Singleton poprzez późne wiązanie statyczne:

class Singleton
{
    protected static $instance = null;

    protected function __construct()
    {
        //Thou shalt not construct that which is unconstructable!
    }

    protected function __clone()
    {
        //Me not like clones! Me smash clones!
    }

    public static function getInstance()
    {
        if (!isset(static::$instance)) {
            static::$instance = new static;
        }
        return static::$instance;
    }
}

Rozwiązuje to problem, że przed PHP 5.3 każda klasa, która rozszerzyła Singleton, stworzy instancję swojej macierzystej klasy zamiast własnej.

Teraz możesz zrobić:

class Foobar extends Singleton {};
$foo = Foobar::getInstance();

I $foo będzie instancją Foobara zamiast instancją Singletona.

 113
Author: selfawaresoup,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-04 11:29:39

Niestety odpowiedź Inwdr pęka, gdy jest wiele podklas.

Oto prawidłowa dziedziczona klasa bazowa Singletona.

class Singleton
{
    private static $instances = array();
    protected function __construct() {}
    protected function __clone() {}
    public function __wakeup()
    {
        throw new Exception("Cannot unserialize singleton");
    }

    public static function getInstance()
    {
        $cls = get_called_class(); // late-static-bound class name
        if (!isset(self::$instances[$cls])) {
            self::$instances[$cls] = new static;
        }
        return self::$instances[$cls];
    }
}

Kod badania:

class Foo extends Singleton {}
class Bar extends Singleton {}

echo get_class(Foo::getInstance()) . "\n";
echo get_class(Bar::getInstance()) . "\n";
 99
Author: mpartel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:54

Prawdziwy i nowoczesny sposób na wzór Singletona to:

<?php

/**
 * Singleton Pattern.
 * 
 * Modern implementation.
 */
class Singleton
{
    /**
     * Call this method to get singleton
     */
    public static function instance()
    {
      static $instance = false;
      if( $instance === false )
      {
        // Late static binding (PHP 5.3+)
        $instance = new static();
      }

      return $instance;
    }

    /**
     * Make constructor private, so nobody can call "new Class".
     */
    private function __construct() {}

    /**
     * Make clone magic method private, so nobody can clone instance.
     */
    private function __clone() {}

    /**
     * Make sleep magic method private, so nobody can serialize instance.
     */
    private function __sleep() {}

    /**
     * Make wakeup magic method private, so nobody can unserialize instance.
     */
    private function __wakeup() {}

}

Więc teraz możesz go używać jak.

<?php

/**
 * Database.
 *
 * Inherited from Singleton, so it's now got singleton behavior.
 */
class Database extends Singleton {

  protected $label;

  /**
   * Example of that singleton is working correctly.
   */
  public function setLabel($label)
  {
    $this->label = $label;
  }

  public function getLabel()
  {
    return $this->label;
  }

}

// create first instance
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;

// now try to create other instance as well
$other_db = Database::instance();
echo $other_db->getLabel() . PHP_EOL; // Abraham

$other_db->setLabel('Priler');
echo $database->getLabel() . PHP_EOL; // Priler
echo $other_db->getLabel() . PHP_EOL; // Priler

Jak widzicie, ta realizacja jest o wiele bardziej elastyczna.

 31
Author: Abraham Tugalov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-24 22:50:26

Prawdopodobnie powinieneś dodać prywatną metodę _ _ clone (), aby uniemożliwić klonowanie instancji.

private function __clone() {}

Jeśli nie włączysz tej metody, możliwe będzie następujące wyjście

$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;
Teraz != =$inst2 - nie są już tą samą instancją.
 25
Author: Stefan Gehrig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-15 07:06:37
protected  static $_instance;

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

Ten kod może dotyczyć każdej klasy bez dbania o jej nazwę.

 10
Author: hungneox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-18 04:20:25
<?php
/**
 * Singleton patter in php
 **/
trait SingletonTrait {
   protected static $inst = null;

  /**
   * call this method to get instance
   **/
   public static function getInstance(){
      if (static::$inst === null){
         static::$inst = new static();
      }
      return static::$inst;
  }

  /**
   * protected to prevent clonning 
   **/
  protected function __clone(){
  }

  /**
   * protected so no one else can instance it 
   **/
  protected function __construct(){
  }
}

Do użycia:

/**
 *  example of class definitions using SingletonTrait
 */
class DBFactory {
  /**
   * we are adding the trait here 
   **/
   use SingletonTrait;

  /**
   * This class will have a single db connection as an example
   **/
  protected $db;


 /**
  * as an example we will create a PDO connection
  **/
  protected function __construct(){
    $this->db = 
        new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
  }
}
class DBFactoryChild extends DBFactory {
  /**
   * we repeating the inst so that it will differentiate it
   * from UserFactory singleton
   **/
   protected static $inst = null;
}


/**
 * example of instanciating the classes
 */
$uf0 = DBFactoryChild::getInstance();
var_dump($uf0);
$uf1 = DBFactory::getInstance();
var_dump($uf1);
echo $uf0 === $uf1;

Respose:

object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}

Jeśli używasz PHP 5.4: cecha jest to opcja, więc nie musisz marnować hierarchii dziedziczenia, aby mieć wzór Singletona

I zauważ również, że czy używasz cechy lub extends Singleton Klasa jednym z luźnych zakończeń było utworzenie singletonu klas potomnych, jeśli nie dodasz następującej linii kod:

   protected static $inst = null;

W klasie dziecięcej

Nieoczekiwany wynik będzie:

object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
 10
Author: jose segura,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-18 13:14:31

Obsługuje wiele obiektów z 1 linią na klasę:

Ta metoda wymusi singletony na dowolnej klasie, którą chcesz, ale musisz dodać 1 metodę do klasy, którą chcesz utworzyć singleton i to zrobi to za Ciebie.

Przechowuje również obiekty w klasie "SingleTonBase", dzięki czemu można debugować wszystkie obiekty, które zostały użyte w systemie przez rekurencyjne obiekty SingleTonBase.


Utwórz plik o nazwie SingletonBase.php i dołącz go do katalogu głównego twojego scenariusz!

Kod to

abstract class SingletonBase
{
    private static $storage = array();

    public static function Singleton($class)
    {
        if(in_array($class,self::$storage))
        {
            return self::$storage[$class];
        }
        return self::$storage[$class] = new $class();
    }
    public static function storage()
    {
       return self::$storage;
    }
}

Następnie dla każdej klasy, którą chcesz utworzyć singleton, po prostu dodaj tę małą metodę single.

public static function Singleton()
{
    return SingletonBase::Singleton(get_class());
}

Oto mały przykład:

include 'libraries/SingletonBase.resource.php';

class Database
{
    //Add that singleton function.
    public static function Singleton()
    {
        return SingletonBase::Singleton(get_class());
    }

    public function run()
    {
        echo 'running...';
    }
}

$Database = Database::Singleton();

$Database->run();

I możesz po prostu dodać tę funkcję Singletona do dowolnej klasy, którą posiadasz i utworzy ona tylko 1 instancję na klasę.

Uwaga: zawsze powinieneś uczynić __konstrukt prywatnym, aby wyeliminować użycie nowych instancji klasy ();.

 6
Author: RobertPitt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-03 20:15:42
class Database{

        //variable to hold db connection
        private $db;
        //note we used static variable,beacuse an instance cannot be used to refer this
        public static $instance;

        //note constructor is private so that classcannot be instantiated
        private function __construct(){
          //code connect to database  

         }     

         //to prevent loop hole in PHP so that the class cannot be cloned
        private function __clone() {}

        //used static function so that, this can be called from other classes
        public static function getInstance(){

            if( !(self::$instance instanceof self) ){
                self::$instance = new self();           
            }
             return self::$instance;
        }


        public function query($sql){
            //code to run the query
        }

    }


Access the method getInstance using
$db = Singleton::getInstance();
$db->query();
 5
Author: rizon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-07 09:43:41

Cała ta złożoność ("późne wiązanie statyczne"... harumph) jest dla mnie po prostu znakiem zepsutego modelu obiektu/klasy PHP. Gdyby obiekty klasy były obiektami pierwszej klasy (Patrz Python), wtedy "$_instance " byłaby zmienną klasy instancją -- członkiem obiektu klasy, w przeciwieństwie do członka/właściwości jego instancji, a także w przeciwieństwie do współdzielonych przez jego potomków. W świecie Smalltalk jest to różnica między "zmienną klasy" A "zmienną instancji klasy".

In PHP, wydaje mi się, że musimy wziąć sobie do serca wskazówki, że wzorce są przewodnikiem w kierunku pisania kodu - może pomyślimy o szablonie Singleton, ale próba napisania kodu, który dziedziczy z rzeczywistej klasy "Singleton", wygląda na błędną dla PHP (chociaż przypuszczałem, że jakaś przedsiębiorcza dusza mogłaby stworzyć odpowiednie słowo kluczowe SVN).

Będę nadal kodować każdy singleton osobno, używając współdzielonego szablonu.

Zauważ, że absolutnie trzymam się z dala od singletons-to-zła dyskusja, życie jest za krótkie.

 3
Author: Tom Stambaugh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-09 21:10:57

Wiem, że prawdopodobnie spowoduje to niepotrzebną wojnę ognia, ale widzę, jak możesz chcieć więcej niż jedno połączenie z bazą danych, więc przyznam, że singleton może nie być najlepszym rozwiązaniem na to... istnieją jednak inne zastosowania wzoru Singletona, które uważam za niezwykle przydatne.

Oto przykład: zdecydowałem się uruchomić własny silnik MVC i szablonów, ponieważ chciałem czegoś naprawdę lekkiego. Jednak dane, które chcę wyświetlić, zawierają wiele specjalnych znaków matematycznych, takich jak ≥ i μ i co masz... Dane są przechowywane jako rzeczywisty znak UTF-8 w mojej bazie danych, a nie przed zakodowaniem HTML, ponieważ moja aplikacja może dostarczać inne formaty, takie jak PDF i CSV oprócz HTML. Odpowiednie miejsce do formatowania dla HTML jest wewnątrz szablonu ("Widok", jeśli chcesz), który jest odpowiedzialny za renderowanie tej sekcji strony (fragment). Chcę przekonwertować je do odpowiednich encji HTML, ale funkcja PHPS get_html_translation_table() jest nie za szybko. Lepiej jest pobierać dane jednorazowo i przechowywać je jako tablicę, dzięki czemu są one dostępne dla wszystkich. Oto próbka, którą zebrałem, by sprawdzić prędkość. Prawdopodobnie działałoby to niezależnie od tego, czy inne metody, których używasz (po pobraniu instancji), były statyczne, czy nie.

class EncodeHTMLEntities {

    private static $instance = null;//stores the instance of self
    private $r = null;//array of chars elligalbe for replacement

    private function __clone(){
    }//disable cloning, no reason to clone

    private function __construct()
    {
        $allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
        $specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
        $this->r = array_diff($allEntities, $specialEntities);
    }

    public static function replace($string)
    {
        if(!(self::$instance instanceof self) ){
            self::$instance = new self();
        }
        return strtr($string, self::$instance->r);
    }
}
//test one million encodings of a string
$start = microtime(true);
for($x=0; $x<1000000; $x++){
    $dump = EncodeHTMLEntities::replace("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)");
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds using singleton\n";
//now repeat the same without using singleton
$start = microtime(true);
for($x=0; $x<1000000; $x++){
    $allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
    $specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
    $r = array_diff($allEntities, $specialEntities);
    $dump = strtr("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)", $r);
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds without using singleton";

W zasadzie widziałem typowe wyniki takie jak:

php test.php
Run time: 27.842966794968 seconds using singleton
Run time: 237.78191494942 seconds without using singleton
Więc chociaż z pewnością nie jestem ekspertem, nie widzę bardziej wygodnego i niezawodnego sposobu na zmniejszenie kosztów powolne wywołanie jakiegoś rodzaju danych, jednocześnie czyniąc je bardzo prostymi (pojedyncza linia kodu, aby zrobić to, czego potrzebujesz). Oczywiście mój przykład ma tylko jedną użyteczną metodę, a zatem nie jest lepszy niż globalnie zdefiniowana funkcja, ale jak tylko będziesz miał dwie metody, będziesz chciał je pogrupować, prawda? Jestem daleko poza bazą?

Również wolę przykłady, które rzeczywiście coś robią, ponieważ czasami trudno jest wizualizować, gdy przykład zawiera stwierdzenia typu " / / zrób coś użytecznego tutaj" które widzę cały czas szukając tutoriali.

W każdym razie, chciałbym wszelkie opinie lub komentarze na temat tego, dlaczego używanie Singletona do tego typu rzeczy jest szkodliwe (lub zbyt skomplikowane).

 2
Author: user2009125,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-18 09:52:54

Nie musisz używać wzoru Singletona, ponieważ jest on uważany za antypattern. Zasadniczo istnieje wiele powodów, aby w ogóle nie wdrażać tego wzoru. Przeczytaj to na początek: najlepsza praktyka na klasach singleton PHP .

Jeśli mimo wszystko nadal uważasz, że potrzebujesz użyć wzorca Singletona, możemy napisać klasę, która pozwoli nam uzyskać funkcjonalność Singletona poprzez rozszerzenie naszej abstrakcyjnej klasy SingletonClassVendor.

To jest to, co przyszedłem do Rozwiąż ten problem.

<?php
namespace wl;


/**
 * @author DevWL
 * @dosc allows only one instance for each extending class.
 * it acts a litle bit as registry from the SingletonClassVendor abstract class point of view
 * but it provides a valid singleton behaviour for its children classes
 * Be aware, the singleton pattern is consider to be an anti-pattern
 * mostly because it can be hard to debug and it comes with some limitations.
 * In most cases you do not need to use singleton pattern
 * so take a longer moment to think about it before you use it.
 */
abstract class SingletonClassVendor
{
    /**
     *  holds an single instance of the child class
     *
     *  @var array of objects
     */
    protected static $instance = [];

    /**
     *  @desc provides a single slot to hold an instance interchanble between all child classes.
     *  @return object
     */
    public static final function getInstance(){
        $class = get_called_class(); // or get_class(new static());
        if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
            self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
            echo "new ". $class . PHP_EOL; // remove this line after testing
            return  self::$instance[$class]; // remove this line after testing
        }
        echo "old ". $class . PHP_EOL; // remove this line after testing
        return static::$instance[$class];
    }

    /**
     * Make constructor abstract to force protected implementation of the __constructor() method, so that nobody can call directly "new Class()".
     */
    abstract protected function __construct();

    /**
     * Make clone magic method private, so nobody can clone instance.
     */
    private function __clone() {}

    /**
     * Make sleep magic method private, so nobody can serialize instance.
     */
    private function __sleep() {}

    /**
     * Make wakeup magic method private, so nobody can unserialize instance.
     */
    private function __wakeup() {}

}

Użyj przykładu:

/**
 * EXAMPLE
 */

/**
 *  @example 1 - Database class by extending SingletonClassVendor abstract class becomes fully functional singleton
 *  __constructor must be set to protected becaouse: 
 *   1 to allow instansiation from parent class 
 *   2 to prevent direct instanciation of object with "new" keword.
 *   3 to meet requierments of SingletonClassVendor abstract class
 */
class Database extends SingletonClassVendor
{
    public $type = "SomeClass";
    protected function __construct(){
        echo "DDDDDDDDD". PHP_EOL; // remove this line after testing
    }
}


/**
 *  @example 2 - Config ...
 */
class Config extends SingletonClassVendor
{
    public $name = "Config";
    protected function __construct(){
        echo "CCCCCCCCCC" . PHP_EOL; // remove this line after testing
    }
}

Aby udowodnić, że działa zgodnie z oczekiwaniami:

/**
 *  TESTING
 */
$bd1 = Database::getInstance(); // new
$bd2 = Database::getInstance(); // old
$bd3 = Config::getInstance(); // new
$bd4 = Config::getInstance(); // old
$bd5 = Config::getInstance(); // old
$bd6 = Database::getInstance(); // old
$bd7 = Database::getInstance(); // old
$bd8 = Config::getInstance(); // old

echo PHP_EOL."COMPARE ALL DATABASE INSTANCES".PHP_EOL;
var_dump($bd1);
echo '$bd1 === $bd2' . ($bd1 === $bd2)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd2 === $bd6' . ($bd2 === $bd6)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd6 === $bd7' . ($bd6 === $bd7)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE

echo PHP_EOL;

echo PHP_EOL."COMPARE ALL CONFIG INSTANCES". PHP_EOL;
var_dump($bd3);
echo '$bd3 === $bd4' . ($bd3 === $bd4)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd4 === $bd5' . ($bd4 === $bd5)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd5 === $bd8' . ($bd5 === $bd8)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
 2
Author: DevWL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-08 20:45:59

Ten artykuł dość obszernie omawia tematykę: http://www.phptherightway.com/pages/Design-Patterns.html#singleton

Uwaga:

  • konstruktor __construct() jest zadeklarowany jako protected, aby zapobiec tworzeniu nowej instancji poza klasą za pomocą operatora new.
  • metoda magiczna __clone() jest zadeklarowana jako private, Aby zapobiec klonowaniu instancji klasy za pomocą operatora clone.
  • metoda magiczna __wakeup() jest zadeklarowana jako private, Aby zapobiec unserializacji instancji klasy za pomocą funkcji globalnej unserialize().
  • nowa instancja jest tworzona poprzez późne wiązanie statyczne w metodzie tworzenia statycznego {[9] } ze słowem kluczowym static. To pozwala na podklasowanie class Singleton W przykładzie.
 1
Author: Krzysztof Przygoda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-17 19:21:10

Od dawna pisałem, że mogę się tu podzielić

class SingletonDesignPattern {

    //just for demo there will be only one instance
    private static $instanceCount =0;

    //create the private instance variable
    private static $myInstance=null;

    //make constructor private so no one create object using new Keyword
    private function  __construct(){}

    //no one clone the object
    private function  __clone(){}

    //avoid serialazation
    public function __wakeup(){}

    //ony one way to create  object
    public static  function  getInstance(){

        if(self::$myInstance==null){
            self::$myInstance=new SingletonDesignPattern();
            self::$instanceCount++;
        }
        return self::$myInstance;
    }

    public static function getInstanceCount(){
        return self::$instanceCount;
    }

}

//now lets play with singleton design pattern

$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();

echo "number of instances: ".SingletonDesignPattern::getInstanceCount();
 1
Author: Gyaneshwar Pardhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-31 07:00:50

Zgadzam się z pierwszą odpowiedzią, ale chciałbym również zadeklarować klasę jako ostateczną, aby nie mogła być rozszerzona, ponieważ rozszerzenie Singletona narusza wzór Singletona. Również zmienna instancji powinna być prywatna, aby nie można było do niej bezpośrednio uzyskać dostępu. Uczyń również metodę _ _ clone prywatną, aby nie można było sklonować obiektu singleton.

Poniżej znajduje się przykładowy kod.

/**
 * Singleton class
 *
 */
final class UserFactory
{
    private static $_instance = null;

    /**
     * Private constructor
     *
     */
    private function __construct() {}

    /**
     * Private clone method
     *
     */
     private function __clone() {}

    /**
     * Call this method to get singleton
     *
     * @return UserFactory
     */
    public static function getInstance()
    {
        if (self::$_instance === null) {
            self::$_instance = new UserFactory();
        }
        return self::$_instance;
    }
}

Przykładowe Użycie

$user_factory = UserFactory::getInstance();

Co to powstrzymuje cię przed robieniem (co naruszałoby singleton wzór..

NIE MOŻESZ TEGO ZROBIĆ!

$user_factory = UserFactory::$_instance;

class SecondUserFactory extends UserFactory { }
 0
Author: Joseph Crawford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-08 22:51:27

To powinna być właściwa droga Singletona.

class Singleton {

    private static $instance;
    private $count = 0;

    protected function __construct(){

    }

    public static function singleton(){

        if (!isset(self::$instance)) {

            self::$instance = new Singleton;

        }

        return self::$instance;

    }

    public function increment()
    {
        return $this->count++;
    }

    protected function __clone(){

    }

    protected function __wakeup(){

    }

} 
 0
Author: Mário Kapusta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 16:33:07

Podobała mi się metoda używania cech przez @ jose-segura, ale nie podobała mi się potrzeba definiowania zmiennej statycznej na podklasach. Poniżej znajduje się rozwiązanie, które unika tego poprzez buforowanie wystąpień w statycznej zmiennej lokalnej do metody fabrycznej indeksowanej przez nazwę klasy:

<?php
trait Singleton {

  # Single point of entry for creating a new instance. For a given
  # class always returns the same instance.
  public static function instance(){
    static $instances = array();
    $class = get_called_class();
    if( !isset($instances[$class]) ) $instances[$class] = new $class();
    return $instances[$class];
  }

  # Kill traditional methods of creating new instances
  protected function __clone() {}
  protected function __construct() {}
}

Użycie jest takie samo jak @ jose-segura tylko nie potrzeba zmiennej statycznej w podklasach.

 0
Author: Eric Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-02 15:39:11

Klasa bazy danych, która sprawdza, czy istnieje jakaś istniejąca instancja bazy danych, zwróci poprzednią instancję.

   class Database {  
        public static $instance;  
         public static function getInstance(){  
            if(!isset(Database::$instance) ) {  
                Database::$instance = new Database();  
            }  
           return Database::$instance;  
         }  
         private function __cunstruct() {  
           /* private and cant create multiple objects */  
         }  
         public function getQuery(){  
            return "Test Query Data";  
         }  
    }  
    $dbObj = Database::getInstance();  
    $dbObj2 = Database::getInstance();  
    var_dump($dbObj);  
    var_dump($dbObj2);  


/* 
After execution you will get following output: 

object(Database)[1] 
object(Database)[1] 

*/  

Ref http://www.phptechi.com/php-singleton-design-patterns-example.html

 0
Author: sunil rajput,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-08 15:49:43

Jest to przykład create singleton on Database class

Wzorce projektowe 1) singleton

class Database{
  public static $instance;
  public static function getInstance(){
    if(!isset(Database::$instance)){
    Database::$instance=new Database();

     return Database::$instance;
    }

  }

  $db=Database::getInstance();
  $db2=Database::getInstance();
  $db3=Database::getInstance();

  var_dump($db);
  var_dump($db2);
  var_dump($db3);

Wtedy out put jest --

  object(Database)[1]
  object(Database)[1]
  object(Database)[1]

Używaj tylko pojedynczej instancji, a nie twórz 3 instancji

 0
Author: Surendra Kumar Ahir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-02 08:21:56

Oto mój przykład, który daje możliwość wywołania jako $ var = new Singleton (), a także tworzenia 3 zmiennych, aby sprawdzić, czy tworzy nowy obiekt:

class Singleton{

    private static $data;

    function __construct(){
        if ($this::$data == null){
            $this->makeSingleton();
        }
        echo "<br/>".$this::$data;
    }

    private function makeSingleton(){
        $this::$data = rand(0, 100);
    }

    public function change($new_val){
        $this::$data = $new_val;
    }

    public function printme(){
        echo "<br/>".$this::$data;
    }

}


$a = new Singleton();
$b = new Singleton();
$c = new Singleton();

$a->change(-2);
$a->printme();
$b->printme();

$d = new Singleton();
$d->printme();
 -3
Author: bboydev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-04 08:14:59