php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #39946 Native Singleton Implementation
Submitted: 2006-12-25 17:45 UTC Modified: 2007-04-30 16:08 UTC
Votes:8
Avg. Score:4.2 ± 1.3
Reproduced:3 of 3 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (33.3%)
From: scott dot mcnaught at synergy8 dot com Assigned:
Status: Not a bug Package: Feature/Change Request
PHP Version: 6CVS-2006-12-25 (CVS) OS: All
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: scott dot mcnaught at synergy8 dot com
New email:
PHP Version: OS:

 

 [2006-12-25 17:45 UTC] scott dot mcnaught at synergy8 dot com
Description:
------------
###
# Introduction
###
This document is an RFC for adding a small patch to the zend engine to allow for native singleton classes.  The problem 
is that currently theres no clean way to implement singleton classes in user-land over the entirety of a project.

Singleton classes are beneficial because:

- Removes the overhead of having multiple instances of the one object when there is no need
- Allows you to keep the objects state rather than always starting from an initial state. 
- They provide namespaces with the benefits of polymorphism (eg - singleton classes can override / inherit from each other)

Throughout this document, I will use an example of a singleton class "members" which acts as an interface to a database table.  
This class can save and load members from this database table simply by calling the following methods in this class.

members::get($member_id) Loads a member from a member id and returns an associative array with info about that member
members::save($member) Saves a member to the database from an array of properties about that member

With the recent phase of tiered and service oriented architecture, the need for Singleton has become more and more apparent.




###
# Singleton in php5
###
In the past, I have implemented Singleton two different ways.  Both of these have problems.


# Method 1:
The first method involves having a public static getInstance method in every singleton class.  This sucks because you
need to manually copy and paste it into every singleton class you make.  Using a singleton class in this way is also confusing
for novice programmers. Eg:

<?php

class members
{
	static public function getInstance()
	{
		static $object = null;
		
		if($object)
		{
			return $object;
		}
		
		$object = new members();
		return $object;
	}
	
	/**
	 * Returns a member from the database based on their id
	 */
	function get($id)
	{
		// ...
	}
	
	// save method etc...
}

// Usage
$arrMember = members::getInstance()->get(49);
$arrMember['member_f_name'] = 'Scott';
members::getInstance()->save($arrMember);

?>



# Method 2:
This method involves an associative array of class names to their instances, probably via a helper function similar to this.

<?php

class members
{
	/**
	 * Returns a member from the database based on their id
	 */
	function get($id)
	{
		// ...
	}
	
	// save method etc...
}

/**
 * Returns an instance of a singleton class from its class name
 */
function getInstance($strClass)
{
	static $objects = array();
	
	if(!isset($objects[$strClass]))
	{
		return $objects[$strClass];
	}
	
	$objects[$strClass] = new members();
	return $objects[$strClass];
}

// Usage
$arrMember = getInstance('members')->get(49);
$arrMember['member_f_name'] = 'Scott';
getInstance('members')->save($arrMember);

?>

This sucks because its slow, confusing for novices, and IDEs never pick up the class for code hinting.




###
# Proposed new functionality
###

I propose that singleton classes become a native part of the php language by adding the "singleton" class modifier T_SINGLETON.

I don't know if native singleton classes have been implemented in a language before.  Most other languages eg - C++
you can use template classes or generics to implement a clean singleton.

The zend engine could feature a hash table and store the instances of objects.

An example of the new way of using singleton classes would be:

<?php

/**
 * A class for saving / retreiving members from a database
 */
singleton class members extends dataadapter
{
	/**
	 * Returns a member from the database based on their id
	 */
	function get($id)
	{
		// ...
	}
	
	// save method etc...
}


// Usage
$arrMember = members->get(49);
members->save($arrMember);

?>


###
# Edge cases / got-cha's
###
Some investigation will have to be performed as to how inheritence will work with singletons.

Eg 
- Never have singleton abstract classes?

- What happens when $members = new members() is called
-- I say an exception being thrown and a suggestion to remove "new"

- Is it ok to go $members = members; ?
-- I'd say yes

- Singleton constructors should not have parameters

- Perhaps a new function singleton_getobjects needs to be added to enable access to the internal hash table 

- Dereferencing a non-singleton class should produce the same error


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-12-29 07:59 UTC] me at bashkim dot com dot au
I think the term "singleton" itself is a little confusing for newbies (considering that it's who you want to target here). Perhaps what you're looking for is a "static class" ...

<?php

    static class Members
    {
        ...
    }
    
?>
 [2006-12-29 08:23 UTC] scott dot mcnaught at synergy8 dot com
But the term singleton and static class are two different things.

The problem with pure static classes is that you can't inherit because an instance is never created.

With static classes, you arent invoking methods on an instance of a class.  You are simply calling static functions in a static namespace.
 [2007-03-06 05:51 UTC] toomuchphp-phpbugs at yahoo dot com
Perhaps some nicer solutions to your got-cha's:

- What happens when $members = new members() is called

If the class is defined as a singleton, then PHP should create the instance as
normal (this includes calling __construct() ) and store it in the hash table,
or return the cached instance if it's already created.


-- I say an exception being thrown and a suggestion to remove "new"

You should still be able to use 'new', with the expectation that if the class
is a singleton, you might actually get a cached instance, rather than a 'new'
instance, but it's not very difficult to understand:

  $a = new members;
  $b = new members;
  $c = new members;
  // $a $b and $c are all the same instance because members is a singleton

If you really think 'new' is too ambiguous, why not add a new token such as
'only', which is used for instantiation of singletons?

  $a = only members;
  $b = only members;
  $c = only members;
  // it's a bit more obvious $a $b and $c are the same instance.


- Is it ok to go $members = members; ?

That's too ambiguous.  In that example 'members' could be a constant,
singleton, or simply the string 'members'.


- Singleton constructors should not have parameters

Perhaps they could (and it might be useful), if it's done like this:

singleton class members { ... }

$foo = new members(1, 2, 3); // arguments are passed to __construct()
$bar = new members(3, 2, 1); // arguments are ignored, object has already been constructed
$baz = new members(4, 5, 6); // arguments are ignored, object has already been constructed


- Perhaps a new function singleton_getobjects needs to be added to enable access to the internal hash table 

Not a bad idea. Getting in 'through the back door' is really important. Why not
also a 'singleton_is_loaded()', and an 'is_singleton()'?  Obviously this would
eventually need to be visible through the Reflection classes (etc, etc).


- Never have singleton abstract classes?

I think that would be an unfair limitation.



You should just need to:
 - add T_SINGLETON to the parser.
 - add an is_singleton flag for class definitions, activated by T_SINGLETON.
 - overload the 'new' operator to retrieve from the hash table if the class is
   a singleton (otherwise call __construct() as normal).
 - implement some of those helper functions such as singleton_getobjects().
 [2007-04-30 16:08 UTC] tony2001@php.net
We don't have any plans on implementing this in the nearest future.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed May 15 06:01:33 2024 UTC