Singletton Pattern not respected in PHP - php

I need a few variables to be shared accross several sessions. To do this, I thought I could use a class with a singleton pattern storing the variables, so each user (session) would just have to include the class and access its data.
I proceed with the following way :
<?php
require_once('team.php');
class Game {
private static $_instance = null;
private $team1;
private $team2;
public function getTeam($num) {
if ($num == 1) return $this->team1;
if ($num == 2) return $this->team2;
}
private function __construct() {
$this->team1 = new Team();
$this->team2 = new Team();
$this->team1->init_team(1);
$this->team2->init_team(2);
}
public static function getInstance() {
if(is_null(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
}
?>
Then I try to use the class like this :
$game = Game::getInstance();
$player = new Player();
...
$game->getTeam($team)->addPlayer($player);
Here is the problem : two players from a same team can't see each other when displaying all the members of their teams. Moreover, when I use the following instruction on 2 different sessions :
spl_object_hash(Game::getInstance());
The output is different, whereas I would expect it to be the same, assuming that it works like Java classes's hashcodes.
Any help regarding this issue would be appreciated. Thanks for reading.

When running a PHP application, every request starts a new instance of the application.
Your code IS running how you expect it to, but PHP doesn't run how you expect it to. It is not comparable to the way Java runs.
If you were to start a HTTP server to serve your PHP application and you had 10 concurrent visitors, you would see 10 new processes running on your server - each one containing a different instance of the application for each visitor.
However, if you were to create your HTTP server in Java and have 10 concurrent visitors, you would only see 1 process.
If you are looking to have persistent data in PHP which can be displayed to different users you should look into storage systems such as MySQL.

Every page run is distinct PHP application. This means that every user (on page call) is using his own compiled version of app, which will be deleted afterwards.
Singleton it not for that. It's just to ensure there is only one instance of object. But this object "lives" solely within separately compiled application.
You should use database for this kind of things (or any other kind of storage)

Related

PHP persist data between pages without using $_GET and $_POST

Okay, so before I receive any abuse from this post, I'd like to state that I am all for following normal principals for persisting data, however today when I was developing I had an idea to create a class which sent a JSON object between pages simply using its own getter and setter methods.
class Persist {
private static $instance;
private static $object;
// singleton instanciation of the class
public static function getInstance() {
$object = __CLASS__;
!isset(self::$instance) ? self::$instance = new $object : false;
return self::$instance;
}
set__object($curr_object) {
self::$object = $curr_object;
}
get__object() {
return self::$object;
}
}
My question is, does this object get set exclusively to one user, or would it become system wide, I know that PHP is a server side language, so I assume the Object is created on the server.
Will each user have their own Persist object created or will there be one shared one, obviously one shared object would be a huge problem.
Thanks in advance,
Alex.
PHP is stateless. Each request will run usually in its own process/thread and the process/thread will stop after the script is done. Each instance of a class (also singletons) will thus be existing for the duration of that request. This is unlike c#/.net for example, where the entire web application is run like an application that handles multiple requests. So, no, it is not possible this way.
To share/persist data over multiple requests you will need to use something on disk or some external tool. Think of: sessions, databases, memcache, apc, etc.

Design pattern to manage a connection to remote APIs

I have some PHP code that connects to shopping cart API (SOAP) endpoints. This is not to one central server, but rather to any number of user's specific endpoint URLs.
Right now I have several different classes that all create their own connection to the users API.
E.G.,
CartProduct.php -> updateProduct() (creates api connection)
CartCategory.php -> updateCategory() (creates api connection)
I was thinking of using a Singleton to share the remote connection, but after reading through questions on SO, and some blogs, apparently everyone hates Singleton.
In my case I don't think a connection pool makes sense. I'm connecting to a remote user's website, so I don't just want to open 5 connections and potentially slow down their website. I think in this case I really want to share ONE connection between this call to the application. I think in the case of a DB, a connection pool makes sense, but not for remote user APIs. Now theoretically, I guess we should think about what happens if the user tries to run updateProduct and updateCategory at the same time... will that break the system?
Is there a design pattern that makes sense here to open a connection which several different classes can share??
I have no idea if this pattern has a name
In my humble opinion, the connection pool would actually make sense. Only you should not initialize all the connections right off. Instead use lazy initialization:
class LazyPool
{
private $connections = [];
private $providers = [];
public function addProvider($name, callable $provider)
{
$this->providers[$name] = $provider;
return $this;
}
public function getConnection($name)
{
if (array_key_exists($name, $this->connections) === false)
{
$this->connections[$name] = call_user_func($this->providers[$name]);
}
return $this->connections[$name];
}
}
This class can would be used like this:
$pool = new LazyPool;
$pool->addProvider('lorem', function() use ($config){
$instance = new SoapThing($config['wsdl_1']);
return $instance;
});
$pool->addProvider('ipsum', function() use ($config){
$instance = new SoapThing($config['i_think_it_was_wsdl']);
return $instance;
});
$foo = new Foo($pool);
$bar = new Bar($pool);
This way both instance will be able to initialize SOAP connection, but if Foo initialized connection named "ipsum", then Bar instance will get from pool the already initialized SOAP client.
Disclaimer:
This code was not tested. It was written directly in the SO post editor using some copy-paste from older post of mine. This particular syntax also will require PHP 5.4+, therefore you might need to adapt it for running in older PHP 5.* versions.

Scope of Static Members in PHP and Concurrency

I have a class that is declared in my application that has a private static member like so:
class SomeClass{
private static myMember = array();
public static getterFunction(){}
public static setterFunction(){}
}
My question / concern is that multiple requests (i'm thinking like a thread in Java) would be able to modify this static member. My understanding of php scope and static members is that they are in the request scope and a new variable is created for each new request and subsequently destroyed after the request has been fulfilled. That said, this would be a difficult thing to test (at least i can't think of an easy way) so i'd rather be safe than sorry.
Is my assessment correct? The PHP docs i've read are pretty crappy in terms of detail so I haven't been able to authoritatively answer yet...
No data, none, is persistent or shared across different instances of PHP scripts unless you explicitly make it so (for example using sessions, databases, files, shared memory). Each PHP instance is its own thing, and each new request causes the webserver to start a separate instance.
So yes, you are correct.
You don't have shared memory by default in PHP. Every single request is being processed in separate process, so they do not know about each other.
I hope I understood your question correctly.
For example:
You have a simple script.php file that sets private field in a class when GET parameter passed:
<?
class A {
private $x = 1;
public function setX($x) {$this->x = $x;}
public function getX() {return $this->x;}
}
$a = new A();
if (!empty($_GET['x'])) {
$a->setX($_GET['x']);
sleep(3);
}
echo $a->getX();
?>
You do two requests at once:
GET /script.php?x=5
GET /script.php
Second request will print you "1". Yes, you are correct!

Every client request is a new instance of the class?

I wrote a class that builds some url in a page every time there is a client request to the server. In a hypothetical scenario in which 100 clients, at the same time, require a server connection, it should produce 100 instances of that class, right?
So I would like to know what would be the result of many instances at the same time on the page and if this is a good practice to solve my problem with the "url generator".
Thanks
[EDIT]
What I tried to do it was to use __set() method and overloading to build the URLs. The fact is that I started to study object-oriented programming in php and I wanted to try a practical application of this method. Here is a piece of code:
Class BuildPath {
private $ServerPath;
private $ServerUrl;
private $UrlPath;
private $data;
function __construct()
{
$this->ServerPath = $_SERVER['DOCUMENT_ROOT'];
$this->ServerUrl = $_SERVER['HTTP_HOST'];
$this->UrlPath = $_SERVER['REQUEST_URI'];
$this->data = array();
}
public function __get($key) {
return $this->$key;
}
public function __set($key,$value)
{
$this->data[$key] = $value;
}
// others methods
After reading some of the comments I think you are misunderstanding what PHP is and isn't. Each time a user makes a request to the page it is "creating an instance" as you say. After the page is loaded the "instance" is removed. This is how PHP works.
Singleton classes will not share data with one users instance with another users instance but instead share that users intsance of that class with that same users instance of another class.
This is how PHP operates and is normal. Since php doesn't "store" data between each request this is where memcache or mysql come into use or sessions.
One thing to be aware of is that PHP has no application scope, meaning that there is no shared memory between requests. A database (mysql) or in memory store (memcache) is typically used to share the state of objects between requests.
Without knowing more specifics to your question, in general, each request made to the webserver will spawn a new instance of your class, but each class will only be aware of it's own state unless you have a mechanism to share it.

PHP Singleton: not holding instance

I'm just becoming dive into php after ages working in vb.net.
I wanna write a logger class that runs as singleon over my webapp, here the code:
class cLog{
private $data = NULL;
static private $instance = NULL;
static public function getInstance(){
if(self::$instance == NULL){
echo "empty!";
self::$instance = new cLog();
}
return self::$instance;
}
private function __construct(){
}
private function __clone(){
}
public function getData(){
return self::getInstance()->data;
}
public function trace($o){
self::getInstance()->data[] = $o;
}
}
What I expect is that, as i switch between pages of my application that make several calls to the cLog::trace() method, the data array increases and it's filled with all traces. But what I get is: everytime i run a page, the $instance is null so the object restarts (as you can see, I put an echo "empty!" line in the instance getter: it shows everytime)
I guess there's something I'm misunderstanding in the php application-lifecycle....
Here there's an usage example:
cLog::getInstance()->trace("hello world");
$logs = cLog::getInstance()->getData();
Thanks
PHP uses a "share nothing" architecture. This means (among other things) that nothing is shared between page loads. Unlike .NET, where the application is started on the first page hit and runs until stopped, just servicing requests as they come. In PHP, every time a page is requested the application is essentially compiled and run from scratch.
The PHP life cycle is from "page start to load" to "page ended load".
Generally speaking, every time you load a new page, everything starts from scratch.
You might be able to do some... interesting... things with session data to get your logger to work the way you want it to.
Good luck!
But what I get is: everytime i run a page, the $instance is null so the object restarts
...
I guess there's something I'm misunderstanding in the php application-lifecycle....
PHP's application-lifecycle mirrors that of HTTP. Each request for a page/URI is stateless. Each request knows nothing about the other requests. This is by design. The behavior you described is PHP acting as it should.
You need to take extra steps to have each request know about what happened in other requests. (PHP's session handling is one way to do this)
Instead of addressing your question on application life cycle in PHP, I would like to make a recommendation on using a prebuilt logging class.
The Zend Framework has Zend_Log which uses the Factory pattern and has a wide variety of Writer objects to log to databases, the filesystem, email, and so forth.
http://framework.zend.com/manual/en/zend.log.writers.html
You can use Zend_Log without needing any other part of the library, so it should be easy to adapt to your current system.

Categories