سؤال

كيف يمكن للمرء إنشاء فئة مفردة باستخدام فصول PHP5؟

هل كانت مفيدة؟

المحلول

/**
 * 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()
    {

    }
}

ليستخدم:

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

$fact == $fact2;

ولكن:

$fact = new UserFactory()

يلقي خطأ.

نرى http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static لفهم نطاقات متغيرة ثابتة ولماذا الإعداد static $inst = null; يعمل.

نصائح أخرى

يسمح PHP 5.3 بإنشاء فئة مفردة قابلة للوراثة عبر الربط الثابت المتأخر:

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

هذا يحل المشكلة ، أنه قبل PHP 5.3 ، فإن أي فئة مددت على المفرد من شأنها أن تنتج مثيلًا من فئة الأم بدلاً من تلقاء نفسه.

الآن يمكنك أن تفعل:

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

وسيكون $ foo مثالًا لـ Foobar بدلاً من مثيل Singleton.

للأسف إجابة inwdr يكسر عندما يكون هناك عدة فئات فرعية.

فيما يلي فئة قاعدة وراثي قابلة للوراثة.

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

رمز الاختبار:

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

echo get_class(Foo::getInstance()) . "\n";
echo get_class(Bar::getInstance()) . "\n";

الحقيقي والحديث طريقة لجعل نمط المفرد هي:

<?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() {}

}

حتى الآن يمكنك استخدامه مثل.

<?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

كما ترى هذا الإدراك أكثر مرونة.

ربما يجب عليك إضافة طريقة __clone () خاصة لعدم السماح لمثيل.

private function __clone() {}

إذا لم تقم بتضمين هذه الطريقة ، فإن ما يلي ممكن

$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;

حاليا $inst1 !== $inst2 - لم تعد مثيلًا بعد الآن.

<?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(){
  }
}

ليستخدم:

/**
 *  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) {
}

إذا كنت تستخدم PHP 5.4: سمة إنه خيار ، لذلك ليس عليك أن تضيع التسلسل الهرمي للميراث من أجل الحصول على نمط المفرد

ولاحظ أيضًا أنك سواء كنت تستخدم سمات أو يمتد سينجلتون كانت النهاية الفضفاضة من الفئة الأولى هي إنشاء Singleton من فصول الأطفال إذا لم تضيف السطر التالي من التعليمات البرمجية:

   protected static $inst = null;

في فئة الطفل

ستكون النتيجة غير المتوقعة:

object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
protected  static $_instance;

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

يمكن أن يتقدم هذا الرمز للحصول على أي فئة دون الاهتمام باسم الفصل.

يدعم كائنات متعددة بخط واحد لكل فئة:

ستنفذ هذه الطريقة المفردات على أي فصل ترغب في القيام به ، عليك إضافة طريقة واحدة إلى الفصل الذي ترغب في صنعه في المفرد وسيفعل ذلك من أجلك.

هذا أيضًا يخزن الكائنات في فئة "SingletonBase" حتى تتمكن من تصحيح جميع الأشياء التي استخدمتها في نظامك عن طريق تكرار SingleTonBase أشياء.


قم بإنشاء ملف يسمى singletonbase.php وقم بتضمينه في جذر البرنامج النصي الخاص بك!

الرمز هو

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

ثم بالنسبة لأي فصل ، فأنت تريد أن تجعل المفرد فقط أضف هذه الطريقة الفردية الصغيرة.

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

هنا مثال صغير:

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

ويمكنك فقط إضافة وظيفة Singleton هذه في أي فصل لديك وسيقوم فقط بإنشاء مثيل واحد لكل فصل.

ملاحظة: يجب عليك دائمًا جعل __construct Private للقضاء على استخدام الفئة الجديدة () ؛ إنشاءات.

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

لا تحتاج حقًا إلى استخدام نمط المفرد لأنه يعتبر مضادًا للمنفثين. في الأساس ، هناك الكثير من الأسباب لعدم تنفيذ هذا النمط على الإطلاق. اقرأ هذا لتبدأ بـ: أفضل الممارسات على دروس PHP Singleton.

إذا كنت لا تزال تعتقد أنك بحاجة إلى استخدام نمط Singleton ، فيمكننا كتابة فصل يسمح لنا بالحصول على وظائف Singleton من خلال توسيع صفنا التجريدي SingletonClassvendor.

هذا ما جئت معه لحل هذه المشكلة.

<?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() {}

}

استخدم مثال:

/**
 * 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
    }
}

فقط لإثبات أنه يعمل كما هو متوقع:

/**
 *  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

كل هذا التعقيد ("الربط الثابت المتأخر" ... Harumph) هو ، بالنسبة لي ، مجرد علامة على نموذج كائن/فئة من PHP. إذا كانت كائنات الفئة كائنًا من الدرجة الأولى (انظر Python) ، فإن "$ _instance" ستكون فئة نموذج متغير - عضو في كائن الفصل ، على عكس عضو/ممتلكات في حالاته ، وكذلك على عكس مشاركتها من نسلها. في عالم Smalltalk ، هذا هو الفرق بين "متغير الطبقة" و "متغير مثيل الفئة".

في PHP ، يبدو لي كما لو أننا بحاجة إلى أن نأخذ بعين الاعتبار أن الأنماط هي دليل على كتابة رمز - ربما ربما نفكر في قالب مفردة ، ولكن نحاول كتابة رمز يرث من فئة "Singleton" الفعلية يبدو مضللاً لـ PHP (على الرغم من أنني من المفترض أن بعض الروح المغامرة يمكن أن تخلق كلمة رئيسية مناسبة SVN).

سأستمر في رمز كل Singleton بشكل منفصل ، باستخدام قالب مشترك.

لاحظ أنني أبقى على الإطلاق خارج المناقشة المفردة ، والحياة قصيرة جدًا.

أعلم أن هذا ربما سيتسبب في حرب اللهب غير الضرورية ، لكن يمكنني أن أرى كيف قد ترغب في أكثر من اتصال قاعدة بيانات ، لذلك أود أن أقر بأنه قد لا يكون الحل الأفضل لذلك ... ومع ذلك ، هناك استخدامات أخرى لنمط المفرد الذي أجده مفيدًا للغاية.

إليك مثال: قررت أن أرفع محرك MVC الخاص بي ومحرك Templating لأنني أردت شيئًا خفيفًا حقًا. ومع ذلك ، فإن البيانات التي أريد عرضها تحتوي على الكثير من أحرف الرياضيات الخاصة مثل ≥ و μ وماذا لديك ... يتم تخزين البيانات كحرف UTF-8 الفعلي في قاعدة البيانات الخاصة بي بدلاً من مشفر قبل HTML بسبب يمكن للتطبيقي تقديم تنسيقات أخرى مثل PDF و CSV بالإضافة إلى HTML. يوجد المكان المناسب لتنسيق HTML داخل القالب ("عرض" إذا صح التعبير) المسؤول عن تقديم قسم الصفحة هذا (المقتطف). أرغب في تحويلها إلى كيانات HTML المناسبة ، لكن وظيفة PHPS GET_HTML_TRANSLation_Table () ليست سريعة للغاية. من المنطقي استرداد البيانات مرة واحدة وتخزينها كصفيف ، مما يجعلها متاحة للجميع لاستخدامها. إليك عينة قمت بتجميعها لاختبار السرعة. من المفترض أن هذا من شأنه أن يعمل بغض النظر عما إذا كانت الطرق الأخرى التي تستخدمها (بعد الحصول على المثيل) ثابتة أم لا.

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

في الأساس ، رأيت نتائج نموذجية مثل هذا:

php test.php
Run time: 27.842966794968 seconds using singleton
Run time: 237.78191494942 seconds without using singleton

لذا ، على الرغم من أنني لست خبيرًا بالتأكيد ، إلا أنني لا أرى طريقة أكثر ملاءمة وموثوقية لتقليل النفقات العامة للمكالمات البطيئة لنوع من البيانات ، مع جعلها بسيطة للغاية (سطر واحد من التعليمات البرمجية للقيام بما تحتاجه). منحت مثالتي فقط لها طريقة واحدة مفيدة ، وبالتالي ليست أفضل من وظيفة محددة عالميًا ، ولكن بمجرد أن يكون لديك طريقتان ، سترغب في تجميعها معًا ، أليس كذلك؟ هل أنا بعيدًا عن القاعدة؟

أيضًا ، أفضل الأمثلة التي تفعل شيئًا فعليًا ، لأنه من الصعب في بعض الأحيان تصور عندما يتضمن مثال عبارات مثل "// افعل شيئًا مفيدًا هنا" الذي أراه طوال الوقت عند البحث عن البرامج التعليمية.

على أي حال ، أحب أي ردود فعل أو تعليقات على سبب استخدام المفرد لهذا النوع من الأشياء ضارة (أو معقدة للغاية).

تغطي هذه المقالة الموضوع على نطاق واسع:http://www.phptherightway.com/pages/design-patterns.html#singleton

لاحظ ما يلي:

  • المُنشئ __construct() تم إعلانه protected لمنع إنشاء مثيل جديد خارج الفصل عبر new المشغل أو العامل.
  • الطريقة السحرية __clone() تم إعلانه private لمنع استنساخ مثيل الفصل عبر clone المشغل أو العامل.
  • الطريقة السحرية __wakeup() تم إعلانه private لمنع عدم تسوية مثيل الفصل عبر الوظيفة العالمية unserialize().
  • يتم إنشاء مثيل جديد عبر الربط الثابت المتأخر في طريقة الإنشاء الثابت getInstance() مع الكلمة الرئيسية static. هذا يسمح للتصنيف الفرعي من class Singleton في المثال.

لقد كتبت منذ فترة طويلة يعتقد أن أشاركها هنا

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

وأنا أتفق مع الإجابة الأولى ، لكنني سأعلن أيضًا أن الفصل نهائي بحيث لا يمكن تمديده لأن تمديد المفرد ينتهك نمط Singleton. كما يجب أن يكون متغير المثيل خاصًا بحيث لا يمكن الوصول إليه مباشرة. اجعل أيضًا طريقة __clone خاصة بحيث لا يمكنك استنساخ كائن Singleton.

فيما يلي بعض رمز المثال.

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

مثال الاستخدام

$user_factory = UserFactory::getInstance();

ما يمنعك هذا من فعله (والذي ينتهك نمط المفرد ..

لا يمكنك القيام بذلك!

$user_factory = UserFactory::$_instance;

class SecondUserFactory extends UserFactory { }

يجب أن تكون هذه هي الطريقة الصحيحة للفرد.

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

    }

} 

لقد أحببت طريقة @jose-segura لاستخدام السمات ، لكنني لم أحب الحاجة إلى تحديد متغير ثابت على الفئات الفرعية. فيما يلي حل يتجنبه عن طريق تخزين الحالات في متغير محلي ثابت إلى طريقة المصنع المفهرسة باسم الفصل:

<?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() {}
}

الاستخدام هو نفسه @jose-segura فقط لا حاجة للمتغير الثابت في الفئات الفرعية.

فئة قاعدة البيانات التي تتحقق مما إذا كان هناك أي مثيل قاعدة بيانات موجود ، فسيقوم بإرجاع المثيل السابق.

   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] 

*/  

المرجع http://www.pptechi.com/php-singleton-design-paterns-example.html

This is the example of create singleton on Database class

design patterns 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);

then out put is --

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

use only single instance not create 3 instance

Here's my example that provides ability to call as $var = new Singleton() and also creating 3 variables to test if it creates new object:

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();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top