While cloning an object, I need to perform the same initializations that happen during the object construction.
Can I do this?
public class MyClass {
protected $myVar;
public function __construct()
{
$this->myVar = 0
}
public function __clone()
{
$this->__construct();
}
}
You can do that just fine
class MyClass {
protected $myVar;
public function __construct()
{
echo "constructing!\n";
$this->myVar = 0;
}
public function __clone()
{
echo "cloning!\n";
$this->__construct();
}
}
$a = new MyClass();
$b = clone $a;
Output
constructing!
cloning!
constructing!
Related
I am noob in PHP because I am mostly do .NET/Java. In code base I am working, I have,
class SomeOtherBaseClass{
public $prop2;
public function __construct(string $prop3)
{
$this->prop2 = $prop3;
}
public function __toString()
{
return $this->prop2 . ' '. $this->prop2;
}
}
class SomeClass
{
public function __toString()
{
return $this->prop1 . ' '. $this->prop1;
}
public $prop1;
public function someMethod() : SomeOtherBaseClass
{
return $this->createClass();
}
public function __construct()
{
$this->prop1 = 'foo';
}
private function createClass(
): SomeOtherBaseClass {
return new class(
$this->prop1
) extends SomeOtherBaseClass {
};
}
}
$class = new SomeClass();
echo $class;
echo $class->someMethod();
Why I am getting error that prop1 not found. Clearly createClass function is part of SomeClass which have prop1. Why I cannot access prop1 inside createClass?
It's because $prop1 has no value or meaning.
You can add a __construct() function to resolve your issue:
public function __construct()
{
$this->prop1 = 'foo';
}
now when you call this class (e.g. $foo = new SomeClass();):
$prop1 has a value of foo which can be used in your functions:
public function echoProp()
{
echo $this->prop1; # will output foo
}
Note: This is just an explanation answer - not a copy/paste solution - but the principles are all here for you to use in your code.
Let me know if this wasn't what you were looking for :)
Edit:
if prop1 exists in SomeOtherClass, when you construct you can do
public function __construct()
{
$this->class = new SomeClass();
$this->prop1 = $this->class->prop1;
}
I was wondering if it is possible for an object to guess the class of his "owner" if the "owner" have a property of the object class.
Let me explain what I mean by a small example
class A {
public function Magic(){/*return owner's class*/}
}
class B {
private $foo;
public function __construct() {
$this->foo=new A();
}
public function getFoo(){
return $this->foo;
}
}
class C {
private $bar;
public function __construct() {
$this->bar=new A();
}
public function getBar(){
return $this->bar;
}
}
$b= new B();
$c= new C();
print($b->getFoo()->Magic()); // would print B
print($c->getBar()->Magic()); // would print C
I don't know if I am dreaming or if it's possible...
How would you do it if not possible?
You need to inject to A his owner. So, the Magic method is less "magical", but the dependency is more clear.
class A
{
private $owner;
public function __construct($owner)
{
$this->owner = $owner;
}
public function Magic() { return get_class($this->owner); }
}
class B
{
private $foo;
public function __construct()
{
$this->foo = new A($this);
}
public function getFoo()
{
return $this->foo;
}
}
class C
{
private $bar;
public function __construct()
{
$this->bar = new A($this);
}
public function getBar()
{
return $this->bar;
}
}
$b= new B();
$c= new C();
print($b->getFoo()->Magic()); // would print B
print($c->getBar()->Magic()); // would print C
I'm not sure with my approach. A have two classes and call functions of first class in second class like this:
class A {
public function aClassFunction() {...}
}
class B {
private $aClass;
public function __construct() {
$this->aClass = new A();
}
public function bClassFunction() {
$test = $this->aClass->aClassFunction();
}
}
It just works, but looks "suspiciously".
You can use dependency injection in B class. That approach helps you mocking classes in test.
class B {
private $aClass;
public function __construct(A $a) {
$this->aClass = $a;
}
public function bClassFunction() {
$test = $this->aClass->aClassFunction();
}
}
$b = new B(new A());
Looks "suspiciously" like a dependency. Why not Inject the Dependency?
class B {
private $aClass;
public function __construct($object) {
$this->aClass = $object;
}
public function bClassFunction() {
$test = $this->aClass->aClassFunction();
}
}
Trying to use objects that extend singletone, but something I can't do.
How to call method from extended class?
How to show 13 non 12 with singleton?
class SingletonTest
{
protected static $_instance;
private function __construct(){}
private function __clone(){}
public static function getInstance() {
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public function test2(){
return 12;
}
}
class ExtendSingleton extends SingletonTest
{
public function test2() {
return 13;
}
}
$b = ExtendSingleton::getInstance();
echo $b->test2(); //12
You will get what you want if you use static binding keyword "static" instead of "self"
class SingletonTest
{
protected static $_instance;
private function __construct(){}
private function __clone(){}
public static function getInstance() {
if (null === static::$_instance) {
static::$_instance = new static();
}
return static::$_instance;
}
public function test2(){
return 12;
}
}
class ExtendSingleton extends SingletonTest
{
public function test2() {
return 13;
}
}
$b = ExtendSingleton::getInstance();
echo $b->test2(); //13
$a = SingletonTest::getInstance();
echo $a->test2(); //13
exit;
But as You see in the above example this way a class which You will call first to "getInstance" will take place to store its instance in the $_instance field.
There is no way to create a base singleton class and inherit singleton behavior.
public static function getInstance()
{
static $instances = array();
$calledClass = get_called_class();
if (!isset($instances[$calledClass]))
{
$instances[$calledClass] = new $calledClass();
}
return $instances[$calledClass];
}
So this should work for you:
(So first normally functions are public so you can use them if you extend from another class! And the you have to make an object from ExtendSingleton not from SingletonTest since ExtendSingleton exdend's -> SingletonTest and not the other way.)
<?php
class SingletonTest {
protected static $_instance;
public function __construct() {
}
public function __clone() {
}
public static function getInstance() {
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
public function test2(){
return 12;
}
}
class ExtendSingleton extends SingletonTest {
public function test2() {
return 13;
}
}
$b = new ExtendSingleton();
echo $b->test2(); //13
?>
Output:
13
I've tested bicccio's solution and it works
class SingletonTest
{
protected static $_instances = [];
private function __construct(){}
private function __clone(){}
public static function getInstance()
{
$calledClass = get_called_class();
if (!isset(self::$_instances[$calledClass]))
{
self::$_instances[$calledClass] = new $calledClass();
}
return self::$_instances[$calledClass];
}
public function test2(){
return 12;
}
}
class ExtendSingleton extends SingletonTest
{
public function test2() {
return 13;
}
}
$b = ExtendSingleton::getInstance();
echo $b->test2(); //13
$a = SingletonTest::getInstance();
echo $a->test2(); //12
You can extend singleton class in php using late static binding the whole process is well discussed in this question.
Creating the Singleton design pattern in PHP5
class Foo {
public static function foobar() {
self::whereami();
}
protected static function whereami() {
echo 'foo';
}
}
class Bar extends Foo {
protected static function whereami() {
echo 'bar';
}
}
Foo::foobar();
Bar::foobar();
expected result foobar actual result foofoo
to make matters worse, the server is restricted to php 5.2
All you need is a one-word change!
The problem is in the way you call whereami(), instead of self:: you should use static::. So class Foo should look like this:
class Foo {
public static function foobar() {
static::whereami();
}
protected static function whereami() {
echo 'foo';
}
}
In another word, 'static' actually makes the call to whereami() dynamic :) - it depends on what class the call is in.
Try to use singleton pattern:
<?php
class Foo {
private static $_Instance = null;
private function __construct() {}
private function __clone() {}
public static function getInstance() {
if(self::$_Instance == null) {
self::$_Instance = new self();
}
return self::$_Instance;
}
public function foobar() {
$this->whereami();
}
protected function whereami() {
print_r('foo');
}
}
class Bar extends Foo {
private static $_Instance = null;
private function __construct() {}
private function __clone() {}
public static function getInstance() {
if(self::$_Instance == null) {
self::$_Instance = new self();
}
return self::$_Instance;
}
protected function whereami() {
echo 'bar';
}
}
Foo::getInstance()->foobar();
Bar::getInstance()->foobar();
?>
Don't you have to overwrite the parent function foobar() too?
class Foo {
public static function foobar() {
self::whereami();
}
protected static function whereami() {
echo 'foo';
}
}
class Bar extends Foo {
public static function foobar() {
self::whereami();
}
protected static function whereami() {
echo 'bar';
}
}
Foo::foobar();
Bar::foobar();