PHP syntax for static attribute of attribute - php

I have implemented a singleton pattern class, and who can be used in another classes like this :
class myClass {
private $attr;
public function __construct() {
$this->attr = Singleton::getInstance;
echo $this->attr::$sngtAttr; // Throw an error
// witch syntax use whithout pass by a temp var ?
}
}

Is $sngtAttr a static property?
If not, then just:
echo $this->attr->sngtAttr; instead of echo $this->attr::$sngtAttr;
will do it.
Otherwise since is static:
echo Singleton::$sngtAttr;

What is your question exactly ?
This is how you do a singleton :
<?php
class ASingletonClass
{
// Class unique instance. You can put it as a static class member if
// if you need to use it somewhere else than in yout getInstance
// method, and if not, you can just put it as a static variable in
// the getInstance method.
protected static $instance;
// Constructor has to be protected so child classes don't get a new
// default constructor which would automatically be public.
protected final function __construct()
{
// ...
}
public static function getInstance()
{
if( ! isset(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
}
// OR :
public static function getInstance()
{
static $instance;
if( ! isset($instance)) {
$instance = new self;
}
return $instance;
// In that case you can delete the static member $instance.
}
public function __clone()
{
trigger_error('Cloning a singleton is not allowed.', E_USER_ERROR);
}
}
?>
Also don't forget the () when you call getInstance, it's a method, not a member.

Related

Is there a way to check if class member access on instantiation?

So in PHP 5.4 and up you can call a method on instantiation like so.
$class = new Foo()->methodName();
I would like to check when the class is instantiated if it was done so with a method at the same time.
Is it possible to check if the class was instantiated without a method at the same time and default to a method if not?
you can use instanceOf on the object for which you wanted to check the class.
Constructor of the class cannot return a value in php, so you can't use singleton incapsulated in constructor and have it looks nice. Of cource, you can make something like this
// NOT FOR USE
class Foo {
private static $instance;
public function __construct($skipIncapsulate = false) {
if (!$skipIncapsulation && !self::$instance)
{
self::instance = new self(true);
}
}
public function bar() {
// Do what you want with self::$instance
}
}
N.B. Do not use the example above, it is ugly solution, which also incapsulates unnecessary logic in controller, and while working with the class
Better use a usual singleton like this
class Foo {
private static $instance;
private function __construct()
{}
public static getInstance()
{
return self::$instance ?? self::$instance = new self();
}
}
Nevertheless you can create a new class FooManager, which will delegate the if the Foo class is defined
class FooManager {
private static $foo;
public function __construct()
{
self::$foo = self::$foo ?? self::$foo = new Foo();
}
public function getFoo()
{
return self::$foo;
}
}
// usage in your code
(new FooManager)->getFoo()->bar();
// You can add __call method to use (new FooManager)->foo->bar()
This will simplify working with your code. Incapsulating static self-instance in constructor is not the good practice

Getting class name from static function in abstract class

I have an abstract class that has a number of static functions (which return a new instance of itself by using new static($args) which works fine), but I can't work out how to get the class name. I am trying to avoid putting
protected static $cn = __CLASS__;
but if unavoidable, then its not the end of the world
abstract class ExtendableObject {
static function getObject() {
return new static($data);
}
static function getSearcher() {
return new ExtendableObjectFinder(/* CLASS NAME CLASS */);
}
}
class ExtendableObjectFinder {
private $cn;
function __construct($className) {
$this->cn = $className;
}
function where($where) { ... }
function fetch() { ... }
}
To get the name of the class you can use get_class and pass $this.
Alternatively, there is get_called_class which you can use within static methods.
You don't need to use the class name explicitly, you can use self.
class SomeClass {
private static $instance;
public static function getInstance() {
if (self::$instance) {
// ...
}
}
}
CodePad.

extends a singleton class in PHP

<?php
class LoveBase
{
protected static $_instance = NULL;
protected function __construct() {}
public static function app()
{
if(self::$_instance == NULL) {
self::$_instance = new self();
}
return self::$_instance;
}
public function get()
{
return 'LoveBase';
}
}
class Love extends LoveBase
{
public static function app()
{
if(self::$_instance == NULL) {
self::$_instance = new self();
}
return self::$_instance;
}
public function get()
{
return 'Love';
}
}
// Print "LoveLove" in this case(first case)
echo Love::app()->get();
echo LoveBase::app()->get();
// Print "LoveBaseLoveBase" in this case(second case)
// echo LoveBase::app()->get();
// echo Love::app()->get();
Why the two different method come out the same result?
Compare the two case, the method will work when it's class instantiate first.
(Sorry, I am not good at english, hopefully you can make sence)
You define two static functions, that both use the same static variable ($_instance) - a static member of the base class can also be access via subclasses (as long as it is not private). Remember that static stuff (methods and variables) gets inherited, but not cloned.
Solution: Make the member variable private, and create one per class.
class LoveBase
{
private static $_instance = NULL;
// ...
class Love extends LoveBase
{
private static $_instance = NULL;
// ...
// Print "LoveLove" in this case(first case)
//Set self::$_instance to Love object id
echo Love::app()->get();
//Static property $_instance is now already set, so LoveBase::app() won't create new self(), it will just return created and saved Love object
echo LoveBase::app()->get();
// Print "LoveBaseLoveBase" in this case(second case)
// Here is the same case, but static property $_instance filled with new self() in LoveBase class
// echo LoveBase::app()->get();
// echo Love::app()->get();

PHP Don't allow object to instantiate more than once

I have an abstract class that is inherited by a number of other classes. I'd like to have it so that instead of re-instantiating (__construct()) the same class each time, to have it only initialize once, and utilize the properties of the previously inherited classes.
I'm using this in my construct:
function __construct() {
self::$_instance =& $this;
if (!empty(self::$_instance)) {
foreach (self::$_instance as $key => $class) {
$this->$key = $class;
}
}
}
This works - sort of, I'm able to get the properties and re-assign them, but within this, I also want to call some other classes, but only one time.
Any suggestions for a better way to go about doing this?
Thats a Singleton construct:
class MyClass {
private static $instance = null;
private final function __construct() {
//
}
private final function __clone() { }
public final function __sleep() {
throw new Exception('Serializing of Singletons is not allowed');
}
public static function getInstance() {
if (self::$instance === null) self::$instance = new self();
return self::$instance;
}
}
I made the constructor and __clone() private final to hinder people from cloning and directly instanciating it. You can get the Singleton instance via MyClass::getInstance()
If you want an abstract base-singleton class have a look at this: https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/SingletonFactory.class.php
You're referring to the Singleton pattern:
class Foo {
private static $instance;
private function __construct() {
}
public static function getInstance() {
if (!isset(static::$instance)) {
static::$instance = new static();
}
return static::$instance;
}
}

How can I create a singleton in PHP?

I'm using PDT and Aptana on Eclipse Indigo with PHP 5.3 and I want to create a singleton in a class.
By singleton, I mean I want to just have one instance of that object, and for other objects or classes to get that single instance via a function that returns that object (so this would mean I'm trying to create an object within the class that defines that object, ie: creating objA within the class objA)
I understand you can't just go a head and do this:
public $object = new Object();
with in a class definition, you have to define it in the constructor.
How can I go ahead and do this? I'm coming from Java, so it could be I'm confusing some basic stuff. Any help is greatly appreciated. Here's the code:
<?php
class Fetcher{
private static $fetcher = new Fetcher(); //this is where I get the unexpected "new" error
static function getFetcherInstance(){
return $this->$fetcher;
}
}
?>
Solved! Thanks for all the help guys!
try this:
<?php
class myclass{
private static $_instance = null;
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new myclass();
}
return self::$_instance;
}
}
?>
and call it with:
<?php
$obj = myclass::getInstace();
?>
You cannot assign a class property in PHP like that. It must be a scalar, or array value, or the property must be set in a method call.
protected static $fetcher;
static function getFetcherInstance(){
if (!self::$fetcher) {
self::$fetcher = new Fetcher();
}
return self::$fetcher;
}
Also, notice that I did not use $this->, as that only works for object instances. To work with static values you need to use self:: when working within the class scope.
You might want to just read common design patterns on the php site. There are pretty good examples with good documentation:
http://www.php.net/manual/en/language.oop5.patterns.php
Else, a singleton is simply a method that returns one single instance of itself:
class MySingletonClass {
private static $mySingleton;
public function getInstance(){
if(MySingletonClass::$mySingleton == NULL){
MySingletonClass::$mySingleton = new MySingletonClass();
}
return MySingletonClass::$mySingleton;
}
}
Building on #periklis answer you might want separate singletons for different application scopes. For example, lets say you want a singleton of a database connection - fine. But what if you have TWO databases you need to connect too?
<?php
class Singleton
{
private static $instances = array();
public static function getInstance($name = 'default')
{
if ( ! isset(static::$instances[$name]))
{
static::$instances[$name] = new static();
}
return static::$instances[$name];
}
}
Class DB extends Singleton {}
$db_one = DB::getInstance('mysql');
$db_two = DB::getInstance('pgsql');
Alse define __clone method
class Fetcher {
protected static $instance;
private function __construct() {
/* something */
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new Fetcher();
}
return self::$instance;
}
private function __clone() {
/* if we want real singleton :) */
trigger_error('Cannot clone', E_USER_ERROR);
}
}
Basically implementing a singleton pattern means writing a class with a private constructor and a static method to build itself. Also check PHP site for it: http://www.php.net/manual/en/language.oop5.php and http://it2.php.net/manual/en/book.spl.php
class A {
protected $check;
private function __construct($args) {
}
static public function getSingleton($args) {
static $instance=null;
if (is_null($instance)) {
$instance=new A();
}
return $instance;
}
public function whoami() {
printf("%s\n",spl_object_hash($this));
}
}
$c=A::getSingleton("testarg");
$d=A::getSingleton("testarg");
$c->whoami(); // same object hash
$d->whoami(); // same object hash
$b= new A("otherargs"); // run time error
<?php
class MyObject {
private static $singleInstance;
private function __construct() {
if(!isset(self::$singleInstance)) {
self::$singleInstance = new MyObject;
}
}
public static function getSingleInstance() {
return self::$singleInstance;
}
}
?>
class MyClass {
private static $instance;
public static function getInstance() {
if( !isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
Then call get instance using
MyClass::getInstance();

Categories