Getting class name from static function in abstract class - php

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.

Related

PHP class extends Singleton pattern

class singleton:
class Singleton
{
private static $_myself;
private function __construct(){}
public static function getInstance()
{
if(!isset(self::$_myself))
{
$obj = __CLASS__;
self::$_myself = new $obj;
}
return self::$_myself;
}
}
my class:
class MyApp extends Singleton
{
public function show()
{
echo 'show';
}
}
MyApp::getInstance()->show();
but not working, this error:
Call to undefined method Singleton::show()
somebody can help me?
Because you're returning a Singleton class (as you can see by your error), but should be returning a MyApp class. You can do this by using the late static binding method get_called_class() introduced in PHP 5.3:
public static function getInstance()
{
if(!isset(self::$_myself))
{
//__CLASS__ = Singleton | get_called_class() = MyApp
$obj = get_called_class();
self::$_myself = new $obj;
}
return self::$_myself;
}
self returns the actual class instance (Singleton in this case), so there is no method show. But you could use static instead of self (Differences) and change $_myself from private to protected so it is accessible in child classes.
class Singleton
{
protected static $_myself;
private function __construct(){}
public static function getInstance()
{
if(!isset(static::$_myself))
{
static::$_myself = new static;
}
return static::$_myself;
}
}
The problem is in
$obj = __CLASS__;
self::$_myself = new $obj;
You create a new instance of the class Singleton, not of the class MyApp, so the method is not available.
Now h2ooooooo was faster with his answer than I edited, see his answer regarding what to put instead of __CLASS__.

Initiating a class globally

To be specific, i have a two class Request and Utils,
class Request
{
public function __construct()
{
//constructor method
}
public function request()
{
$utils=new Utils;
$consolidated_errors=$utils->array_remove_empty($all_params_error);
}
public function process()
{
$utils=new Utils;
$consolidated_errors=$utils->another_method($all_params_error);
}
}
And class Utils,
class Utils
{
public function __construct()
{
//constructor method
}
public function array_remove_empty()
{
//returns a variable.
}
public function another_method()
{
//returns a variable.
}
}
you can see that i am initializing the class two times in request class , and my question is that any way initializing the class globally and using through out the class?
You are looking for Singleton pattern
Following demonstrate very basic Singleton example for your class
public class Utils {
private static Utils uniqInstance;
private Utils() {
}
public static synchronized Utils getInstance() {
if (uniqInstance == null) {
uniqInstance = new Utils();
}
return uniqInstance;
}
// other useful methods here
}
get the instance using static-factory pattern
The above code does not look like Java to me, but anyway,
You could create the class at a class level private Utils myUtuils = new Utils ();
or
have the class as a static class and then just use it directly in your method
public function process()
{
consolidated_errors= Utils.another_method($all_params_error);
}
}

PHP syntax for static attribute of attribute

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.

PHP 5.3 Abstract singleton class and childrens?

i has singleton class with final static method "getInstance()":
<?php
abstract class Singleton
{
protected static $instances;
final public static function getInstance()
{
$class = get_called_class();
if(!isset(static::$instances[$class]))
static::$instances[$class] = new $class();
return static::$instances[$class];
}
}
And code like this:
<?php
class C1 extends Singleton { }
class C2 extends Singleton { }
C1::getInstance(); // Created C1 class
C2::getInstance(); // Still get C1 class, get_called_class() return C1 when i try get C2
What i'm do wrong?
The reason this isn't working is that you're not creating a $instance property for each of your subclasses. While using static:: and get_called_class() will access subclass members instead of superclass members, if the members don't exist in the subclass then they will fall back to the ones defined in the superclass. The result of this is that you'll end up getting the same member anyway.
Try defining your subclasses like this instead.
class C1 extends Singleton {
protected static $instances;
}
class C2 extends Singleton {
protected static $instances;
}
C1->getInstance();
C2->getInstance();
should be
C1::getInstance();
C2::getInstance();
The code
Update:
You don't need an array to hold the instances, instead, let the subclass the hold. Try the code below.
class Singleton
{
private function __construct(){}
protected static $instance;
final public static function getInstance()
{
$class = get_called_class();
if(!static::$instance)
static::$instance = new $class();
return static::$instance;
}
}
class C1 extends Singleton {
protected static $instance;
}
class C2 extends Singleton {
protected static $instance;
}
var_dump(C1::getInstance());
var_dump(C2::getInstance());
Try this abstract Singleton:
abstract class Singleton
{
private static $_instances = array();
public static function getInstance()
{
$class = get_called_class();
if (!isset(self::$_instances[$class])) {
self::$_instances[$class] = new $class();
}
return self::$_instances[$class];
}
}
I can't reproduce your problem:
var_dump(C1::getInstance());
var_dump(C2::getInstance());
gives:
object(C1)#1 (0) {
}
object(C2)#2 (0) {
}
As the var_dump output shows, the types are different (C1, then C2). Keep in mind that you need to invoke the getInstance() statically as it's a static function.
Next to that if you want to really implement the Singleton pattern in PHP, your abstract class is missing some important method definitions to make this more precise with PHP. See Patterns­PHP Manual.
Also in PHP you normally do not need a Singleton at all, inject dependencies instead which will make your code more fluent.
Hope this is helpful.
Working version of abstract singleton:
abstract class Singletone {
private static $_instance = NULL;
private function __construct(){}
public static function GetInstance() {
if( !static::$_instance ) {
static::$_instance = new static();
}
return static::$_instance;
}
}
The derived class must overwrite the $_instance
class DefaultRouter extends Singletone {
protected static $_instance = NULL;
}
There's no need to redefine the static $instance property in the child classes, just use the one defined in the superclass:
<?php
class Singleton
{
public static $Instance;
private function __construct() { }
public static function GetInstance() {
if(!Singleton::$Instance) {
Singleton::$Instance = new static();
}
return Singleton::$Instance;
}
}
class MyClass extends Singleton
{
public $field1;
public $field2;
public $field3;
public function __construct()
{
$this->field1 = "field1";
$this->field2 = "field2";
$this->field3 = "field3";
}
}
var_dump(Myclass::GetInstance());
?>
It outputs
object(MyClass)#1 (3) {
["field1"]=>
string(6) "field1"
["field2"]=>
string(6) "field2"
["field3"]=>
string(6) "field3"
}
https://eval.in/306503

When to put factory() method into factoried object and when put factory() method to separated class?

Is it ok to put factory() method to the factoried object's class?
class User {
public static function factory($id) {
return new User($id);
}
private function __construct($id) {
}
}
And when consider placing factory() method into separated class?
class User {
public function __construct($id) {
}
}
class UserFactory {
public static function factory($id) {
return new User($id)
}
}
I can't see any benefits of using additional class for factory, but I consider that there are some benefits I don't know about. :)
When to put factory() method into factoried object and when put factory() method to separated class?
The advantage with putting the factory method inside the class itself is protecting the class from being instantiated without using the factory method:
class User {
public static function factory($id) {
return new User($id);
}
private function __construct($id) {
// Now, only the factory method within this class can call this method.
// (Additionally, this method was static, which it shouldn't.)
}
}
I let other add to this with advantages of the opposite solution.
If you have a static creator method there is not much use in putting in into a factory.
It's only really useful to put factory method in it's own class if it isn't static and you want to inject it somewhere.
class User {
public static function __construct($id) {
}
}
class UserFactory {
public function factory($id) {
return new User($id)
}
}
class SomethingUserReleated {
public function __construct(UserFactory $factory) {
$this->userFactory = $factory;
}
public function iNeedToCreateAnUserForSomething() {
$userOne = $this->userFactory->factory(1233);
$userTwo = $this->userFactory->factory(123533);
}
}
Since you can't to the above with static methods.
Moving the factory methods into separate class allows you to separate object-methods and factory-specific methods (that are only needed while creating a new object).
class User {
public static function __construct($id, $name){
// call this directly or via Factory
}
}
class UserFactory {
private static function randomName(){
// return some random name
}
public static function factory($id){
return new User($id, UserFactory::randomName());
}
}

Categories