Define a Zend Model as Singleton - php

I want to put my Zend Model as Singleton, so I have done this:
class Social_Model_DbTable_Dossier extends Zend_Db_Table_Abstract {
private static $_instance;
public static function GetInstance() {
if (!self::$_instance instanceof self) {
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() {
// put normal constructor code.
// it will only ever be called once
}}
I instantiate my model like so:
$dossiercasModel = Social_Model_DbTable_Dossier::GetInstance();
but this erreur is occured:
Fatal error: Access level to Social_Model_DbTable_Dossier::__construct() must be public (as in class Zend_Db_Table_Abstract)
when I put the constructor of the Model as public it works fine but this is inconsistent with the notion of singleton!

In the past I have gotten arround having to do this by creating a table broker that would serve up cached table instances,
kind of a multiton.
a simple example
class My_TableManager{
protected static $_instance;
protected $_tableCache = array();
protected function __construct(){
}
public static function getInstance(){
if (!isset(self::$_instance)) self::$_instance = new self();
}
public function getTable($tableName){
if (!array_key_exists($tableName, $this->_tableCache)){
// you can do fun stuff here like name inflection
// Im assuming that tables will be suffixed with _Table
$tableClass = "My_".$tableName."_Table";
$this->_tableCache[$tableName] = new $tableClass();
}
return $this->_tableCache[$tableName];
}
public static function get($tableName){
return self::getInstance()->getTable($tableName);
}
}
To use to get an instance of My_User_Table you would could:
$table = My_TableManager::get("My_User");
or
$table = My_TableManager::getInstnace()->getTable("My_Table");

Related

Calling a function in the class that extend current abstract class

I have an Connection class which connects to a specific "Service". You call the specific Service such as mysqli or PDO when instantiating the class.
class Connection
{
private $service;
private $state = null;
public function __construct(Service $service) {
$this->service = $service;
}
public function initialize() {
....
}
public function destruct() {
....
}
//Maybe some getters and setters
}
In the Service class there is an getObject() method, this contains the object which has to be instantiated to make a connection to a Database or something else.
There is also an getInstance() method. This is used for returning the object in the getObject method if it isnt already instantiated.
abstract class Service
{
public static function getInstance() {
$instance = null;
if ($instance == null) {
$instance = self::getObject();
}
return $instance;
}
/**
* #return object Returns the object where the service should start from.
*/
public abstract function getObject();
}
Here is an example of an Service class.
class MySQLService extends Service
{
public function getObject() {
return new mysqli('127.0.0.1', 'root', '', 'db');
}
}
Problem
When using this code like this:
$connection = new Connection(MySQLService::getInstance());
$connection->initialize();
It comes with this error:
Fatal error: Cannot call abstract method Service::getObject() in
C:\Users.\Documents...\Service.php on line 18
Questions
How does it come that this error appears?
How can I solve this error?
How can I call a function from a class that extends the Service class?
In order to get this working you need to declare the getObject methods as the static methods they are.
In Service:
public abstract function getObject()
Should be:
public static function getObject() {}
(Sorry, you can't have a static abstract)
In MySQLService:
public function getObject() {
Should be:
public static function getObject() {
You can then direct the call to the right class by using the following:
public static function getInstance() {
static $instance = null;
if ($instance == null) {
$instance = static::getObject();
}
return $instance;
}
Note - you missed the static keyword from the instance variable too.

How to get parent class instance?

I have two classes:
Singleton.php
namespace Core\Common;
class Singleton
{
protected static $_instance;
private function __construct(){}
private function __clone(){}
public static function getInstance() {
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
Config.php
namespace Core;
class Config extends Common\Singleton
{
private $configStorage = array();
public function setConfig($configKey, $configValue)
{
$this->configStorage[$configKey] = $configValue;
}
public function getConfig($configKey)
{
return $this->configStorage[$configKey];
}
}
my index.php
require_once 'common\Singleton.php';
require_once 'Config.php';
$config = \Core\Config::getInstance();
$config->setConfig('host', 'localhost');
but got the error: "Call to undefined method Core\Common\Singleton::setConfig()"
So as i can see getInstance() return me Singleton class instance, but not Config, how i can return Config instance from Singleton?
You can change your getInstance to this:
public static function getInstance() {
if (!isset(static::$_instance)) {
static::$_instance = new static;
}
return static::$_instance;
}
The difference between self and static is highlighted here:
self refers to the same class whose method the new operation takes place in.
static in PHP 5.3's late static bindings refers to whatever class in the hierarchy which you call the method on.
So it means that is bounded dynamically to the extending class, hence new static in your case refers to the Config class, using self will always statically refers to the Singleton class.
Working example here.

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

Instance as a static class property

Is it possible to declare an instance of a class as a property in PHP?
Basically what I want to achieve is:
abstract class ClassA()
{
static $property = new ClassB();
}
Well, I know I can't do that, but is there any workaround beside always doing something like this:
if (!isset(ClassA::$property)) ClassA::$property = new ClassB();
you can use a singleton like implementation:
<?php
class ClassA {
private static $instance;
public static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new ClassB();
}
return self::$instance;
}
}
?>
then you can reference the instance with:
ClassA::getInstance()->someClassBMethod();
An alternative solution, a static constructor, is something along the lines of
<?php
abstract class ClassA {
static $property;
public static function init() {
self::$property = new ClassB();
}
} ClassA::init();
?>
Please note that the class doesn't have to be abstract for this to work.
See also How to initialize static variables and https://stackoverflow.com/a/3313137/118153.
This is a few years old, but I just ran into a issue where I have a base class
class GeneralObject
{
protected static $_instance;
public static function getInstance()
{
$class = get_called_class();
if(!isset(self::$_instance))
{
self::$_instance = new $class;
}
return self::$_instance;
}
}
That has a Child Class
class Master extends GeneralObject
{
}
And another Child class
class Customer extends Master
{
}
But when I try to call
$master = Master::getInstance();
$customer = Customer::getInstance();
then $master will be Master as expected, but $customer will be Master because php uses the GeneralObject::$_instance for both Master and Customer
The only way I could achieve what I want was to change the GeneralObject::$_instance to be an array and adjust the getInstance() method.
class GeneralObject
{
protected static $_instance = array();
public static function getInstance()
{
$class = get_called_class();
if(!isset(self::$_instance[$class]))
{
self::$_instance[$class] = new $class;
}
return self::$_instance[$class];
}
}
I hope this helps someone else out there. Took me a few hours to debug what was going on.

singleton in abstract class php

I have a simple question. I use a singleton which implements an abstract class. Is it possible to put the getInstance() Method and the variable $_instance in the abstract class instead of the concrete one I want to create?
Here's my code:
<?php
class Command_Log extends Command_Abstract {
private static $_instance=null;
public static function getInstance() {
if (self::$_instance==null)
self::$_instance=new self();
return self::$_instance;
}
protected function realExecute() {
}
protected function realSimulate($fileHandle) {
}
}
and
<?php
abstract class Command_Abstract implements Command_Interface {
protected $_data=array();
//private static $_instance=null;
protected $_isExecuted=false;
protected $_execute=false;
public function enableExecute() {
$this->_execute=true;
return $this;
}
protected function __construct() {
}
protected function __clone() {}
public function addData($data) {
array_push($this->_data,$data);
return $this;
}
abstract protected function realExecute();
abstract protected function realSimulate($fileHandle);
public function execute() {
if(!$this->_isExecuted && $this->_execute) {
$this->_isExecuted = true;
$this->realExecute();
}
}
public function simulate() {
$exitSystem = false;
if(!$this->_isExecuted && $this->_execute) {
$this->_isExecuted = true;
$exitSystem = $this->realSimulate($fh);
}
}
return $exitSystem;
}
}
I have many implementations of the the commands, so I don't want redundant code everywhere in my implementations. Is it possible to put these two things in the abstract class, if yes please tell me how.
If not please explain it to me why it isnt possbile. Or if I need to change something to do it, anyhow.
regards
YES WE CAN!
I have a class called Singleton that is abstract... and many classes that extends that Singleton class... this is the code:
abstract class Singleton {
private static $instances = array();
final private function __construct($_params) {
$class = get_called_class();
if (array_key_exists($class, self::$instances))
throw new Exception('An instance of '. $class .' already exists !');
//static::initialize(); //In PHP 5.3
$this->initialize($_params);
}
final private function __clone() { }
abstract protected function initialize();
public static function getInstance($_params=array()) {
$class = get_called_class();
if (array_key_exists($class, self::$instances) === false){
self::$instances[$class] = new $class($_params);
}
return self::$instances[$class];
}
}
and (for example) the class DBConnection that extends from Singleton
class DBConnection extends Singleton{
private $connexion_pdo=null;
protected function initialize(){
//connect to the DB
$this->connexion_pdo = blablalba;
}
}
although there are some problems in php 5.2.. specially with the function get_called_class() and the static::initialize()
You could also check the php site for patterns... there are lots of contributions for the singleton
Good Luck

Categories