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();
}
}
Related
I am learnig about test doubles, but I'm a little confused about the difference between Mocks and Stubs.
So, looking for some references about this topic, I found this article (is a good article, but some examples are a little bit confusing)
Then, I was following the examples in my IDE, however, the examples about Mocks and Stubs are the same.
Stubs example:
class A
{
public function calculate() { }
}
class B
{
private A $a;
public $value;
public function __construct(A $a)
{
$this->a = $a;
}
public function setValue()
{
$this->value = $this->a->calculate();
}
}
class StubsTest extends \PHPUnit\Framework\TestCase
{
public function testValueCorrect()
{
$a = $this->createStub(A::class);
$a
->method('calculate')
->willReturn(10);
$b = new B($a);
$b->setValue();
$this->assertEquals(10, $b->value);
}
}
Mock example:
use PHPUnit\Framework\TestCase;
class A {
public function calculate() { }
public function doSomething() { }
}
class B {
private $a;
public $value;
public function __construct(A $a)
{
$this->a = $a;
}
public function setValue()
{
$this->value = $this->a->calculate();
}
public function doSomethingWithA()
{
$this->a->doSomething();
}
}
class MockTest extends TestCase
{
public function testValueCorrect()
{
$a = $this->createStub(A::class);
$a
->method('calculate')
->willReturn(10);
$b = new B($a);
$b->setValue();
$this->assertEquals(10, $b->value);
}
}
What the real difference between both? These code examples above are valid?
I have some classes:
class A{
public $D;
public function __construct()
{
$this->D = new D();
}
}
class C extends E{
public function testC(){
return 'test C';
}
}
class B extends A
{
public function __construct()
{
$this->C = new C();
}
public function testB()
{
echo $this->C->testC();
}
}
(new B)->testB();
I would like transfer variables class A to class C, how i can make it (that i can use variables class A in class C) ?
What you want to achieve is most likely this.
class A
{
public $variable;
}
class B extends A
{
public function __construct()
{
$this->variable = 'value';
}
public function testVar()
{
echo $this->variable;
}
}
I suggest reading OOP basics, there is much more to it than this.
In PHP (Symfony 3);
I want to reference an existing object A in another object B which class extends the one of object A, like this:
class A {
private $property1;
private $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
}
class B extends A {
private $property3;
public function __construct($objectA,$p3){
$this = $objectA;
$this->property3 = $p3;
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
This does not work and throw the following error at the statement $this = $objectA:
Compile Error: Cannot re-assign $this
Which are documented and explain there and there. I am looking for a workaround.
You must call parent constructor and also make property1 and property2 visible in class B
<?php
class A {
private $property1;
private $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
public function getProperty1()
{
return $this->property1;
}
public function getProperty2()
{
return $this->property2;
}
}
class B extends A {
private $property3;
public function __construct($objectA,$p3){
parent::__construct($objectA->getProperty1(), $objectA->getProperty2());
$this->property3 = $p3;
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
See it live here: http://sandbox.onlinephpfunctions.com/code/705bf1827da2bdf10f8d961ee1cb6fbdd88bc663
As an alternative, you could use __call magic method to forward all cals to class A:
<?php
class A {
private $property1;
private $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
}
class B extends A {
private $property3;
private $a;
public function __construct($objectA,$p3){
$this->a = $objectA;
$this->property3 = $p3;
}
public function __call($name, $arguments)
{
return call_user_func_array(array($this->a, $name), $arguments);
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
Based on how to clone object to child class in php
Using get_object_vars on the parent object, you can get an array of properties keys and values. You can then loop through them and assign them to the child object:
<?php
class A {
protected $property1;
protected $property2;
public function __construct($p1,$p2){
$this->property1 = $p1;
$this->property2 = $p2;
}
}
class B extends A {
private $property3;
public function __construct($objectA,$p3){
//$this = $objectA;
$objValues = get_object_vars($objectA); // return array of object values
foreach($objValues AS $key=>$value)
{
$this->$key = $value;
}
$this->property3 = $p3;
echo $this->property1;
}
}
$a = new A('p1','p2');
$b = new B($a,'p3');
This does not work with private properties, they need to be at least of protected level.
I ended up managing it like that:
class B extends A{
public function __construct($objectA){
foreach($this as $k => $v){
if(isset($objectA->{$k})){
$this->{$k} = &$objectA->{$k};
}
}
}
}
Compare to #Antony answer, notice it has & in front of $objectA->{$k}: $this->{$k} = &$objectA->{$k};. As I understood it, with &, any change on $objectB of properties belonging to the extended class A applies to $objectA.
I am aware it is not perfect and quite hacky but it does the job I need. Thanks for the input given by everybody.
I have 3 classes:
Class A - Parent Class
Class B - Child Class
Class C - Class to be used in Class A
I want to use functions from class C using variables from my Child class.
<?php
class A
{
public function __construct()
{
$this->load();
}
public function load()
{
$class = new C();
$class->test = $this->test;
$this->c = $class;
}
}
class B extends A
{
public function __construct()
{
parent::__construct();
}
}
class C
{
public function display()
{
echo $this->test;
}
}
$b = new B();
$b->test = 1;
$b->c->display();
Your problem is here:
$class->test = $this->test;
You are attempting to use a property that is not yet defined, because when you do this:
$b->test = 1;
the constructor has already been called, and there's nothing in your classes to update C with the value of B's test property.
You can solve this in a couple of different ways.
1) Send the value in B's constructor, and pass it down the entire chain:
class A
{
public function __construct($test)
{
$this->load($test);
}
public function load($test)
{
$class = new C();
$class->test = $test;
$this->c = $class;
}
}
class B extends A
{
public function __construct($test)
{
parent::__construct($test);
}
}
class C
{
public function display()
{
echo $this->test;
}
}
$b = new B(123);
$b->c->display();
2) Add a method to B that will update C's property:
<?php
class A
{
public function __construct()
{
$this->load();
}
public function load()
{
$class = new C();
$this->c = $class;
}
}
class B extends A
{
public function __construct()
{
parent::__construct();
}
public function setTest($test)
{
$this->c->test = $test;
}
}
class C
{
public function display()
{
echo $this->test;
}
}
$b = new B();
$b->setTest(123);
$b->c->display();
Or perhaps a combination of both.
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!