Stub a method on any instance of object - php

How can I stub a method of an object that is hardcoded in app? In rspec there is a method allow_any_instance_of.
I can't reverse the dependency, the initialisation of the object should still be hardcoded.
So, I have ClassA
namespace App
class ClassA
{
public function doSomething(){
// more code
return($sth);
}
}
It is used in ClassB
namespace App
class ClassB
{
protected $instanceOfA;
public function __construct(){
$this->instnaceOfA = new ClassA();
}
public function methodToTest(){
$result = $this->instanceOfA->doSomething()
// more code
}
}

I think this is what you're looking for? a plugable interface? if you change the classB to ClassA on line 33 it will switch to the other class.
Interface TheInterface
{
public function doSomething();
}
class ClassA implements TheInterface
{
public function doSomething(){
echo __METHOD__;
}
}
class ClassB implements TheInterface
{
public function doSomething(){
echo __METHOD__;
}
}
class ClassProcess
{
protected $instance;
public function __construct(TheInterface $class){
$this->instance = $class;
}
public function methodToTest(){
$this->instance->doSomething();
}
}
$process = new ClassProcess(new ClassB());
$process->methodToTest();

Related

PHP Traits for interfaces

I have the next code
<?php
interface SimpleInterface
{
public function method(): self;
}
trait SimpleTrait
{
public function method(): self
{
return $this;
}
}
class SomeClass implements SimpleInterface
{
use SimpleTrait;
}
But PHP says that RenderableTrait->setLayout(layout:string) isn't compatible with RenderableInterface->setLayout(layout: string)
Obviously, because interface expects self as returned value, but in trait I return Trait itself and it's not compatible. Are there any solutions?
Change you return type self for SimpleInterface
https://3v4l.org/LTc8E
<?php
trait Test {
public function test() {
return $this;
}
}
class Foo {
use Test;
}
class Bar {
use Test;
}
$f = new Foo();
$b = new Bar();
// object(Foo)
var_dump($f->test());
// object(Bar)
var_dump($b->test());
//So for you case
interface SimpleInterface
{
public function method(): SimpleInterface;
}
trait SimpleTrait
{
// This method will work only in classes that implements SimpleInterface
public function method(): SimpleInterface
{
return $this;
}
}
class SomeClass implements SimpleInterface
{
// Traits $this is now SomeClass
use SimpleTrait;
}
$s = new SomeClass();
// object(SomeClass)
var_dump($s->method());

How do you access a child method

How do you access a child method eg.?
class A
{
public function Start()
{
// Somehow call Run method on the B class that is inheriting this class
}
}
class B extends A
{
public function Run()
{
...
}
}
$b = new B();
$b->Start(); // Which then should call Run method
Class A should not try to call any methods that it itself does not define. This will work just fine for your scenario:
class A {
public function Start() {
$this->Run();
}
}
However, it will fail terribly should you actually do this:
$a = new A;
$a->Start();
What you're trying to do here sounds very much like a use case for abstract classes:
abstract class A {
public function Start() {
$this->Run();
}
abstract function Run();
}
class B extends A {
public function Run() {
...
}
}
The abstract declaration will precisely prevent you from shooting your own foot by trying to instantiate and Start A without extending and defining required methods.
If B is inherited from A then B will be like:
class B extends A
{
public function Start()
{
...
}
public function Run()
{
...
}
}
So as Run() and Start() are in the same class, we can call Run() in Start() directly.
public function Start()
{
Run();
}

Calling subclass method from contructor of superclass

How Can i call subclass method from superclass constructor?
Example subclass:
<?php
include('../classes/A.php');
class B extends A {
public function __construct()
{
parent::__construct($this->view);
}
public function view() {
//something
}
}
$b = new B;
?>
Example superclass:
<?php
abstract class A
{
private $callback;
public function __construct($callback)
{
$this->callback = $callback;
call_user_func($this->callback);
}
}
?>
What can I do to make it works?
Pass an array containing your object instance $this, and the method to call
(see Example #4 of the call_user_func man page on calling class methods)
class B extends A {
public function __construct()
{
parent::__construct(array($this, 'view'));
}
public function view() {
//something
}
}

PHP: Calling another class' method

I'm still learning OOP so this might not even be possible (although I would be surprised if so), I need some help calling another classes method.
For example in ClassA I have this method:
function getName()
{
return $this->name;
}
now from ClassB (different file, but in the same directory), I want to call ClassA's getName(), how do I do that? I tried to just do an include() but that does not work.
Thanks!
//file1.php
<?php
class ClassA
{
private $name = 'John';
function getName()
{
return $this->name;
}
}
?>
//file2.php
<?php
include ("file1.php");
class ClassB
{
function __construct()
{
}
function callA()
{
$classA = new ClassA();
$name = $classA->getName();
echo $name; //Prints John
}
}
$classb = new ClassB();
$classb->callA();
?>
If they are separate classes you can do something like the following:
class A
{
private $name;
public function __construct()
{
$this->name = 'Some Name';
}
public function getName()
{
return $this->name;
}
}
class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
function getNameOfA()
{
return $this->a->getName();
}
}
$a = new A();
$b = new B($a);
$b->getNameOfA();
What I have done in this example is first create a new instance of the A class. And after that I have created a new instance of the B class to which I pass the instance of A into the constructor. Now B can access all the public members of the A class using $this->a.
Also note that I don't instantiate the A class inside the B class because that would mean I tighly couple the two classes. This makes it hard to:
unit test your B class
swap out the A class for another class
You would need to have an instance of ClassA within ClassB or have ClassB inherit ClassA
class ClassA {
public function getName() {
echo $this->name;
}
}
class ClassB extends ClassA {
public function getName() {
parent::getName();
}
}
Without inheritance or an instance method, you'd need ClassA to have a static method
class ClassA {
public static function getName() {
echo "Rawkode";
}
}
--- other file ---
echo ClassA::getName();
If you're just looking to call the method from an instance of the class:
class ClassA {
public function getName() {
echo "Rawkode";
}
}
--- other file ---
$a = new ClassA();
echo $a->getName();
Regardless of the solution you choose, require 'ClassA.php is needed.
File 1
class ClassA {
public $name = 'A';
public function getName(){
return $this->name;
}
}
File 2
include("file1.php");
class ClassB {
public $name = 'B';
public function getName(){
return $this->name;
}
public function callA(){
$a = new ClassA();
return $a->getName();
}
public static function callAStatic(){
$a = new ClassA();
return $a->getName();
}
}
$b = new ClassB();
echo $b->callA();
echo $b->getName();
echo ClassB::callAStatic();

Best practice to implement static class inheritance? (singleton)

From php manual:
[...] Static method calls are resolved at compile time.
When using an explicit class name the method is already identified completely and no
inheritance rules apply. If the call is done by self then self is translated to
the current class, that is the class the code belongs to.
Here also no inheritance rules apply [...]
..so im looking for a way to emulate the standard oop inheritance with static singleton.
Code explain better:
// Normal inheritance: my goal.
class Foo{
public function test(){
echo "Foo->test()\n";
}
}
class Bar extends Foo{
public function other_test()
{
echo "Bar->other_test()\n";
}
}
$obj = new Bar();
echo get_class($obj) . "\n";
$obj->test();
$obj->other_test();
/*
Output:
Bar
Foo->test()
Bar->other_test()
*/
// How i would love to do:
class Foo2{
public static function test2()
{
echo "Foo2::test2()\n";
}
// Singleton?
public static $_instance;
public static function get_instance()
{
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
}
class Bar2 extends Foo2{
public static function other_test2()
{
echo "Bar2::other_test2()\n";
}
}
$obj2 = Bar2::get_instance();
echo get_class($obj2) . "\n";
$obj2::test2();
$obj2::other_test2();
/*
Output:
Foo2
Foo2::test2()
Fatal error: Call to undefined method Foo2::other_test2()
*/
echo "\n-------\n";
// How im doing actually:
interface Foo3{
public static function get_instance();
}
class Bar3 implements Foo3{
// Singleton?
public static $_instance;
public static function get_instance()
{
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
public static function test3()
{
echo "Bar3::test3()\n";
}
public static function other_test3()
{
echo "Bar3::other_test3()\n";
}
}
$obj3 = Bar3::get_instance();
echo get_class($obj3) . "\n";
$obj3::test3();
$obj3::other_test3();
/*
Output:
Bar3
Foo3::test3()
Bar3::other_test3()
*/
The last 'way' force me to avoid the get_instance and static variables to be placed in the parent class, so I do not consider it as a best solution.. if for some reason my get_instance() function will change in the future, i dont want to edit all classes (inheritance! inheritance! we all want inheritance!)
So, is there a way or a best practices to solve this problem?
p.s: php5.3.2
The Singleton pattern in PHP is something like this:
class Singleton {
private static $instance = null;
// Constructor is private, so class cannot be instantiazed from outside
private function __construct() {
}
public static function getInstance() {
if (static::$instance === null) {
static::$instance = new Singleton();
}
return static::$instance;
}
public static function test() {
echo 'Singleton::test()';
}
public function __sleep() {
throw new Exception('Serialization is not alowed.');
}
public function __wakeup() {
throw new Exception('Serialization is not alowed.');
}
public function __clone() {
throw new Exception('Cloning is not alowed.');
}
}
For you is important that keyword static, then this:
class B extends Singleton {
public static function test2() {
echo 'B::test2()';
}
}
$b = B::getInstance();
B::test();
B::test2();
// Singleton::test()
// B::test()
Is this you looking for?

Categories