Multiple inheritance simulation in PHP, how to optimize the code - php

I have two classes A and B. Class C may be extends A and B. I need to do it optimally.
class A {
public function testA() {
echo "this is function testA \n";
}
}
class B {
public function testB() {
echo "this is function testB \n";
}
}
class C extends A {
public function __call($method, $args){
$this->b =new B();
try {
return !method_exists ($this->b , $method ) || !$this->b->$method($args[0]);
} catch(Exception $e) {
echo "error";
}
}
}
$object = new C();
$object->testA();
$object->testB();
$object->testD();
How I can optimize this code?

Multiple "inheritance" in PHP is handled by Traits, which are available as of 5.4.0
More info here: http://php.net/manual/en/language.oop5.traits.php
trait A {
public function testA() {
echo "this is function testA \n";
}
}
trait B {
public function testB() {
echo "this is function testB \n";
}
}
class C {
use A, B;
public function __call($method, $args){
// Called method does not exists.
}
}

Related

PHP Use child variable to create a class in parent class

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.

Php, inheritance, late static binding, unexpected calling chain

consider this code:
class C
{
public function get()
{
echo 'C';
static::get();
}
public function save()
{
self::get();
}
}
class B extends C
{
public function get()
{
echo 'B';
static::get();
}
}
class A extends B
{
public function get()
{
echo 'A';
}
}
$x = new A();
$x->save();
it echoes CA while I was expected CBA
To get this to work the way you want, reverse the logic - get your save to call the static::get() so it will start at the top of the inheritence tree; and use calls to parent::get() in each inherited class in the tree (except the base level) before echoing its own output
class C
{
public function get()
{
echo 'C';
}
public function save()
{
static::get();
}
}
class B extends C
{
public function get()
{
parent::get();
echo 'B';
}
}
class A extends B
{
public function get()
{
parent::get();
echo 'A';
}
}
$x = new A();
$x->save();
Demo

A way to require trait is used in a specific class

http://hacklang.org/tutorial/ - see last exercise (24).
...
trait T {
require extends C;
...
How would you achive this in PHP?
I'd like to use that in PHP Unit tests, like below:
class EventsTest extends TrafficWebTestCase
{
use EntityRepositoryMock;
use ValidatorMock;
use EventsDataProviderTrait;
An example of trait:
trait ValidatorMock
{
...
protected function getValidatorMock($validateObject, $return = [])
{
if (!method_exists($this, 'getMockForAbstractClass')) {
throw new InvalidTraitUseException();
}
$this->validatorMock = $this->getMockForAbstractClass(
'Symfony\Component\Validator\Validator\ValidatorInterface'
);
$this->validatorMock->expects($this->once())
->method('validate')
->with($this->equalTo($validateObject))
->willReturn($return);
return $this->validatorMock;
}
Those trait create some specific mocks or do other stuff that's only related to a unit test. In those traits I use methods from the \PHPUnit_Framework_TestCase, so I'd like to check if trait is used in a valid context.
I think you want something like that:
trait T
{
public function __construct()
{
if (!($this instanceof C)) {
die('Not an instance of C');
}
echo "Everything fine here<br />";
$this->someMethod();
}
}
class C
{
public function someMethod()
{
echo "required method<br />";
}
}
class A extends C
{
use T;
public function doSomething()
{
}
}
class B
{
use T;
public function doSomething()
{
}
}
$a = new A();
$b = new B();
Using instanceof you can check if object extends some class.
For the following code result will be:
Everything fine here
required method
Not an instance of C
More complex code (without checking in constructor):
trait T
{
public function myFunction()
{
$this->checkHierarchy();
echo "normal actions<br />";
}
public function secondFunction()
{
$this->checkHierarchy('D');
echo "normal actions<br />";
}
private function checkHierarchy($className = 'C')
{
if (!($this instanceof $className)) {
throw new \Exception('Not an instance of ' . $className . "<br />");
}
echo "Everything fine here<br />";
}
}
class C
{
public function someMethod()
{
echo "required method<br />";
}
}
class A extends C
{
use T;
public function doSomething()
{
}
public function __construct()
{
echo "aaa<br />";
}
}
class B
{
use T;
public function doSomething()
{
}
public function __construct()
{
echo "bbb<br />";
}
}
$a = new A();
try {
$a->myFunction();
} catch (\Exception $e) {
echo $e->getMessage();
}
try {
$a->secondFunction();
} catch (\Exception $e) {
echo $e->getMessage();
}
$b = new B();
try {
$b->myFunction();
} catch (\Exception $e) {
echo $e->getMessage();
}

PHP - Which class invoked my static method?

I need to know what kind invokes a static method, without sending as parameter
class foo
{
public static function test($clase)
{
echo "Class invoke:" . FUNCTION();
}
}
class A { public function x { foo::test(); } }
class B { public function y { foo::test(); } }
class C { public function z { foo::test(); } }
You can use late static bindings and get_called_class() (PHP >= 5.3) if you make all of your classes extend foo, like this:
class foo
{
public static function test($clase)
{
echo "Class invoke:" . get_called_class();
}
}
class A extends foo { public function x() { self::test(''); } }
class B extends foo { public function y() { self::test(''); } }
class C extends foo { public function z() { self::test(''); } }
With these objects:
$a = new A; $a->x();
$b = new B; $b->y();
$c = new C; $c->z();
You'll get as output:
Class invoke:A
Class invoke:B
Class invoke:C

php class function wrapper

this is my class:
class toyota extends car {
function drive() {
}
function break() {
}
}
class car {
function pre() {
}
}
Is there any way I can do so that when I run $car->drive(), $car->break() (or any other function in toyota), it would call $car->pre() first before calling the functions in toyota?
Yep. You could use protected and some __call magic:
class toyota extends car {
protected function drive() {
echo "drive\n";
}
protected function dobreak() {
echo "break\n";
}
}
class car {
public function __call($name, $args)
{
if (method_exists($this, $name)) {
$this->pre();
return call_user_func_array(array($this, $name), $args);
}
}
function pre() {
echo "pre\n";
}
}
$car = new toyota();
$car->drive();
$car->dobreak();
http://ideone.com/SGi1g
You could do the following, but I don't think that is what you want.
class toyota extends car {
function drive() {
$this->pre();
}
function break() {
$this->pre();
}
}
class car {
function pre() {
}
}
You may want to look into PHP specific magic methods. http://php.net/manual/en/language.oop5.magic.php
This will better done with the magic methods called __call()
public function __call($name, $arguments)
{
$this -> pre();
return $this -> $name($arguments);
}
What is this method? It overrides the default method call, so that preCall State can be invoked.
Your toyota class
class toyota extends car {
public function __call($name, $arguments)
{
$this -> pre();
return call_user_func_array(array($this, $name), $arguments);
}
function drive() {
}
function break() {
}
}
If you are using PHP5 (>=5.3.2), there is a solution that works with declaring all methods as private. This will enforce method call from single function call:
exec_method()
To run at: http://ideone.com/cvfCXm
The code snippet is here:
<?php
class car {
//method to get class method
public function get_method($method_name) {
$class = new ReflectionClass(get_class($this));
$method = $class->getMethod($method_name);
$method->setAccessible(true);
return $method;
}
public function exec_method($method_name, $arg_args=array()) {
//execute the pre() function before the specified method
$this->pre();
//execute the specified method
$this->get_method($method_name)->invokeArgs($this, $arg_args);
}
public function pre() {
echo 'pre';
echo '<br />';
}
}
class toyota extends car {
private function drive() {
echo 'drive';
echo '<br />';
}
private function brake() {
echo 'brake';
echo '<br />';
}
}
$toyota = new toyota();
$toyota->exec_method('drive');
$toyota->exec_method('brake');
?>
Reference:
Answer to Best practices to test protected methods with PHPUnit [closed]
Just add a constructor, like this...
class toyota extends car {
function __construct() {
$this->pre();
}
function drive() {
echo "drive!";
}
function dobreak() {
echo "break!";
}
}
class car {
function pre() {
echo "Hello!";
}
}
$car = new toyota();
$car->drive();
$car->dobreak();
Classes which have a constructor method call this method on each
newly-created object, so it is suitable for any initialization that
the object may need before it is used.
break is reserved, so you shouldn't use this as a function name.

Categories