I have this simple singleton class:
public static function getInstance() {
if (!self::$_controller) {
self::$_controller = new self();
}
return self::$_controller;
}
Using PHP 5.3, this code seems to work fine, but on PHP 5.2 it seems like the instance is not returned. I put in a simple debug message like so:
public static function getInstance() {
if (!self::$_controller) {
self::$_controller = new self();
echo "I seem to be working";
}
return self::$_controller;
}
But "I seem to be working" is never echoed out. What's going on here and how can I fix it?
The following is working at my end for PHP 5.3 and 5.2 both.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('log_errors', 0);
class SingleTon {
private static $_controller = null;
private function __construct() {
// do something here or leave it blank.
}
public static function getInstance() {
if (!self::$_controller) {
self::$_controller = new self();
echo "I seem to be working";
}
return self::$_controller;
}
}
$obj = SingleTon::getInstance();
echo "\n";
?>
It displays "I seem to be working". Let me know if you need any further assistance.
Related
This is my first time having this problem and I hope that you can give me some explanation or some impetus to solve it.
I wrote this code here:
class Foo
{
public function __construct()
{
$this->bar = New Bar();
}
}
class Bar
{
public function __construct()
{
$this->foo = New Foo();
}
}
$foo = New Foo();
This code throwns following error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes)
How can I let the two classes communicate with each other without getting this error?
Edit:
As requested, I'll go into a little more detail. As an example, I have written two classes that are forced to communicate with each other, similar to my current project:
class UserStatusController
{
public function __construct()
{
$this->couponController = New CouponController();
}
private $badStatus = "blocked";
public function hasBadStatus(int $id): bool
{
$user = User::where(['id' => $id])->get();
return $user->status == self::$badStatus ? true : false;
}
public function actualizeStatus(int $id, string $status): bool
{
if ($status == self::$badStatus) {
$this->couponController->deleteCoupon();
return false;
}
$user = User::where(['id' => $id])->update(['status' => $status]);
$this->couponController->createCoupon();
return true;
}
}
class CouponController
{
public function __construct()
{
$this->userStatusController = New UserStatusController();
}
public function createCoupon(): bool
{
if ($this->userStatusController->hasBadStatus()) { return false; }
// create coupon ...
}
public function deleteCoupon(): bool
{
// delete coupon ...
}
}
Since the two classes each have information that the other class needs, they have to somehow exchange data. In the example above there is an infinity loop.
So the question is, what is the most common way of letting these two classes talk to each other?
In your code, you initiate New Bar(); in class Foo, and then initiate New Foo() in class Bar, which initiates New Bar() and so on.
The code below returns bool(true) which I presume is what you at trying to achieve.
<?php
class Foo
{
public function foo1()
{
return true;
}
}
class Bar
{
public function __construct()
{
$this->foo = New Foo();
}
}
$foo = New Foo();
var_dump( $foo->foo1() );
If you need something else please edit your question and be more specific. On the other hand, if you ammend the code like this:
class Foo
{
public function foo1()
{
return true;
}
}
class Bar
{
public function __construct()
{
$this->foo = New Foo();
return $this->foo;
}
}
$foo = New Bar();
var_dump($foo);
the result is object(Bar)#1 (1) { ["foo"]=> object(Foo)#2 (0) { } }
Also, if the 2 functions are on the same file, you don't need to have another class. If they have to be in separate files, you can write class bar extends Foo. There are a lot of OOP courses and free videos explaining classes, functions and so on.
I am trying to make a singleton pattern but it seems I am making mistake somewhere. Everytime i try to create an instance from the class Cart it makes new one. Tested it with the setId() and getId() functions. It returns different number everytime.
class Cart
{
private $cartQuantity = 0;
private static $instance;
private $id;
private function __construct(){}
public function addQuantity($quantity){
$this->cartQuantity += $quantity;
}
public function getQuantity(){
return $this->cartQuantity;
}
public function setId(){
$this->id = rand(0, 10);
}
public function getId(){
return $this->id;
}
public static function startCount(){
if(self::$instance === null){
self::$instance = new Cart();
self::$instance->setId();
}
return self::$instance;
}
}
$inst = Cart::startCount();
echo $inst->getId();
What am I doing wrong? Seems like legit block of code to me :/ Thank you in advance!
Your singleton is working perfectly. I have tested it 10 times with the following code:
$inst = Cart::startCount();
echo $inst->getId();
$winst = Cart::startCount();
echo $inst->getId();
$ninst = Cart::startCount();
echo $ninst->getId();
$ninst->setId();
echo $ninst->getId();
echo $winst->getId();
$ginst = Cart::startCount();
echo $ginst->getId();
Results:
999444
555222
333999
333444
111111
222222
999999
888666
101010999
000777
If you change the ID, it keeps beeing changed. Otherwise always the same is returned. This is exactly what you should expect (note that rand(0,10)) also can deliver 10.
There is never more than one instance.
What is the best way to call Method heDidIt() from child class Make?
I was thinking about events but couldnt find a good non global solution.
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make();
return $this->_make;
}
private function heDidIt()
{
//Call me if the Maker did something.
}
}
class Make
{
public function doIt()
{
//hey im doing something, better tell my Controller
}
}
Just tell Make who's its boss so it can inform him:
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make($this);
return $this->_make;
}
private function heDidIt()
{
//Call me if the Maker did something.
}
public function inform($sampleParam) {
var_dump($sampleParam);
$this->heDidIt();
}
}
class Make
{
protected $control;
public function __construct(Control $control) {
$this->control = $control;
}
public function doIt()
{
//hey im doing something, better tell my Controller
$control->inform('called in Make::doIt()');
}
}
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make();
return $this->_make;
}
**protected** function heDidIt()
{
//Call me if the Maker did something.
}
}
class Make **extends Control**
{
public function doIt()
{
**$this -> heDidIt();**
//hey im doing something, better tell my Controller
}
}
Although this seems extremely pointless, so maybe providing your actual code and requirements would let us help you better.
I'm new to PHP OOP, but not so much to PHP, wanted to start learning.. and hit a few brick walls, but this one stumped me.. BUT since I can't find any questions anywhere on the web.. I can't find answers either..
So.. The Code.. I dumbed it down to its core problem, if I can understand that..
<?php
class wallet {
public $Money = 5;
public function Add($mMoney) {
$this->Money += $mMoney;
echo "added $mMoney to Wallet";
}
public function take($mMoney) {
$this->Money -= $nMoney;
}
public function check() {
echo $this->Money;
echo "Check?";
}
public function __get($var) {
echo "trying to get $var and Failing";
}
}
class person {
public $Name;
public $Wallet;
public $Purse;
public $Cash;
public function __construct($name, $cash) {
$this->Wallet = new wallet();
$this->Purse = new wallet();
$this->Name = $name;
$this->Cash = $cash;
}
public function status() {
echo "<br><table border = 1><tr><td>".$this->Name."</td><td> Wallet?</td><td> Purse </td></tr>
<tr><td> $ ".$this->Cash."</td><td>".$this->checkWallet()."<td>22</td></tr></table>";
}
public function toWallet($toAdd) {
$this->Wallet->add($toAdd);
}
public function checkWallet() {
echo $this->Wallet->check();
}
}
$bob = new person ("Bob", 10);
$sarah = new person ("Sarah", 20);
$bob->status();
$sarah->status();
$bob->toWallet(10);
$bob->status();
$sarah->status();
?>
Why won't toWallet Work? Why can't I access $this->checkWallet()..
The reason why ToWallet won't work is because the function thinks the echo from the Add is the return value. (Which is obviously a string and is useless in calculation). There needs to be a return command for the mMoney variable. Try typing something like this in the Add function
public function Add($mMoney) {
$this->Money += $mMoney;
echo "added $mMoney to Wallet";
return $mMoney;
}
I don't know how nobody else spotted that.
For Anyone who comes across this in the future.. Heres the Solution:
First: When you have an Object, don't echo or print the data to the screen, return it to the parent object to do that for you,
Second: Double check that all Variables are either function only i.e. $wallet, or are the objects variables $this->wallet because even though I was staring at the code for hours, I couldn't see that this was not the same variable..
new to OOP, what a mind-mess
I'm trying to use call_user_func to call a method from another method of the same object, e.g.
class MyClass
{
public function __construct()
{
$this->foo('bar');
}
public function foo($method)
{
return call_user_func(array($this, $method), 'Hello World');
}
public function bar($message)
{
echo $message;
}
}
new MyClass; Should return 'Hello World'...
Does anyone know the correct way to achieve this?
Many thanks!
The code you posted should work just fine. An alternative would be to use "variable functions" like this:
public function foo($method)
{
//safety first - you might not need this if the $method
//parameter is tightly controlled....
if (method_exists($this, $method))
{
return $this->$method('Hello World');
}
else
{
//oh dear - handle this situation in whatever way
//is appropriate
return null;
}
}
This works for me:
<?php
class MyClass
{
public function __construct()
{
$this->foo('bar');
}
public function foo($method)
{
return call_user_func(array($this, $method), 'Hello World');
}
public function bar($message)
{
echo $message;
}
}
$mc = new MyClass();
?>
This gets printed out:
wraith:Downloads mwilliamson$ php userfunc_test.php
Hello World
new MyClass; Should return 'Hello World'...
A constructor does not return anything.