Alias method from Trait in Parent Class - php

I'm wondering if this is possible in PHP:
trait SomeTrait
{
public function someMethod() { /* ... */ }
}
class Parent
{
use SomeTrait;
}
class Child extends Parent
{
/* Do something to rename someMethod() to someOtherMethod() */
use someMethod as someOtherMethod; // Example
public function someMethod()
{
// Do something different than SomeTrait::someMethod()
}
}
In my actual use-case, the Parent class is a parent to several children (and none of them actually use the someMethod() that comes from the trait applied to the parent class. The Parent class is also part of an external library, so I cannot directly modify the source code.
The Child class in my actual use-case also relies on protected properties from the Parent class, so I'm fairly certain that I need to keep the inheritance.
Is this actually possible, or do I just need to deal with it, and use a different method name on the Child class in question?

What you've got in the question should work fine if you just want to override it. As per the manual:
The precedence order is that members from the current class override Trait methods, which in turn override inherited methods.
If you need to provide an alias in the child class, then you can re-use the trait in the child class, making use of the as operator to define an alias in the current class:
class Child extends Foo
{
// This will re-import the trait into your child class, aliasing
// any specified methods.
use SomeTrait {
someMethod as someOtherMethod;
}
public function someMethod() {
$this->someOtherMethod();
}
}
You can also control the visibility of the new alias, e.g.
use SomeTrait {
someMethod as private someOtherMethod;
}
All that said, I don't really see the benefit of this, when you could just call
parent::someMethod();
after over-riding it. But it might be useful if you've got a particularly complex inheritance tree.
Full example here: https://eval.in/868453

I literally tested this yesterday with the following code :-)
<?php
trait CanWhatever
{
public function doStuff()
{
return 'result!';
}
}
class X
{
use CanWhatever;
public function doStuff()
{
return 'overridden!';
}
}
$x = new X();
echo $x->doStuff();
echo "\n\$x has ";
echo (class_uses($x, 'CanWhatever')) ? 'the trait' : 'no trait';
The output was:
overridden!
$x has the trait
So keeping the name the same just overrides as per normal.
Check it out here https://3v4l.org/Vin2H

Related

Calling a child class function if not exist in parent class

I have a code like following ---
class CartItem{
var $v;
function __construct(){
$this->f();
}
function f(){
echo 'In parent';
}
}
class m extends CartItem{
function f(){
echo 'In child';
}
}
new m();
Now when creating instance of m()... it doesn't have any constructor, so it is calling parent classes constructor. Now inside that a function f is called.
What I want is -
if class m() have defined function f()... is should call it instead of parent class's function f().
But anyway it is calling parent classes function, as it was called from parent's constructor, irrespective of child class/ context :(
You want to call in __construct() a method that is not defined in the class. This is a sign that the CartItem class is an abstract concept and you don't intend to instantiate it (because an instance of CartItem probably doesn't contain enough information or behaviour for your project).
An abstract concept is implemented using an abstract class that defines as much as it can and defines abstract methods to be implemented in the concrete classes that extend it. The method f() is such a method that cannot be defined in the abstract concept and has to be defined in each class that extend it:
abstract class CartItem
{
public function __construct()
{
$this->f();
}
abstract protected function f();
}
class m extends CartItem
{
protected function f()
{
// Implement behaviour specific to this class
}
}
This is actually a really interesting question.
so, as I understand it, you're asking (if this isnt right please say):
can you call a function of a class that's extending a parent?
yes, you can... sort of, if the method in the child is static.
Take this example (Ive not used it in the constructor for simplicity of example, but it will work there too):
class ClassA {
public function testMeAsWell() {
return ClassB::testMe();
}
}
class ClassB extends ClassA {
static function testMe() {
return 'do something';
}
}
$child = new ClassB();
echo $child->testMe();
// outputs 'do something'
$parent = new ClassA();
echo $parent->testMeAsWell();
// also outputs 'do something'
the reason this works needs more research, but as a guess I would say that because PHP is compiled, it will know about both classes at run-time and therefore will be able to figure out what we wanted it to do.
So, further on, you want to use variables. Yes you can, but they would have to be static as well.
working example

Use final on traits in PHP

What i want is the ability to make "final traits" with the behaviour as described below. I realise this is not possible with traits(or is it? that would make me so happy), but I'm just trying to convey what I want to do.
So, i want to have a trait that is
trait Content {
public final function getPostContent(){ /*...*/ }
public final function setPostContent($content){ /*...*/ }
}
What I want is
Marking the functions in the traits as final making sure that if a class uses this trait, the trait implementation is the guaranteed implementation
class MyClass {
use Content;
public function getPostContent() { // This should not be allowed
return null;
}
}
I want to be able to somehow check if a class uses a trait(i.e. $myObject instanceof Content)
class MyClass {}
class MyClassWithContent {
use Content;
}
var_dump((new MyClass) instanceof Content); // "bool(false)"
var_dump((new MyClassWithContent) instanceof Content; // "bool(true)"
Making sure that when the trait is being used, the methods name/visibility can not be changed. So, none of this should be allowed.
class MyDeceptiveClass {
use Content {
Content::getPostContent as nowItsNotCalledGetPostContentAnymore();
Content::setPostContent as protected; // And now setPostContent is protected
}
}
Methods in traits are overwritten by methods defined in a class, even if the trait method is final:
<?php
trait Bar {
final public function fizz() {
echo "buzz\n";
}
}
class Baz {
use Bar;
public function fizz() {
echo "bam\n";
}
}
$x = new Baz;
$x->fizz(); // bam
Taking a look at the precedence section in the traits documentation:
An inherited member from a base class is overridden by a member inserted by a Trait. The precedence order is that members from the current class override Trait methods, which in turn override inherited methods.

Call child method from parent class

I have a Class that is used as an extender by several other Classes, and in one instance, a method from the parent Class needs to call back to a method from the child Class. Is there a way of doing this?
I realise PHP contains abstract Classes and functions, but would require each child Class to have the declared abstract function(s), which I do not require in this case.
For example (these are examples, not real life) -
Class parent{
function on_save_changes(){
some_parent_function();
if($_POST['condition'] === 'A') :
// Call 'child_1_action()'
elseif($_POST['condition'] === 'B') :
// Call 'child_2_action()'
endif
some_other_parent_function();
}
function some_parent_function(){
// Do something here, required by multiple child Classes
}
}
Class child_1 Extends parent{
function __construct(){
$this->on_save_changes();
}
function child_1_action(){
// Do something here, only every required by this child Class
}
}
Class child_2 Extends parent{
function __construct(){
$this->on_save_changes();
}
function child_2_action(){
// Do something here, only every required by this child Class
}
}
You can do this by just simply calling the child method, e.g.:
if($_POST['condition'] === 'A') :
$this->some_parent_function();
$this->child_1_action();
However, you should avoid doing this. Putting checks in the parent that call methods only existing in a child class is a very bad design smell. There is always a way to do things in a more structured manner by utilizing well-known design patterns or simply thinking the class hierarchy through better.
A very simple solution you can consider is implementing all of these methods in the parent class as no-ops; each child class can override (and provide implementation for) the method that it's interested in. This is a somewhat mechanical solution so there's no way to know if it's indeed the best approach in your case, but even so it's much better than cold-calling methods that technically are not guaranteed to exist.
Try this:
class ParentClass{
private $childActionMethod;
public function on_save_changes(){
if(method_exists($this, $this->childActionMethod)) {
call_user_func_array(array($this, $this->childActionMethod), func_get_args());
}
else {
throw new Exception('Child Method has not been set');
}
}
protected function setChildActionMethod($methodName) {
$this->childActionMethod = $methodName;
}
}
class ChildClass1 extends ParentClass{
function __construct(){
$this->setChildActionMethod('child_1_action');
}
function child_1_action(){
echo('Hello First World<br />');
}
}
class ChildClass2 extends ParentClass{
function __construct(){
$this->setChildActionMethod('child_2_action');
}
function child_2_action(){
echo('Hello Second World<br />');
}
}
$child1 = new ChildClass1();
$child1->on_save_changes();
// Hello First World
$child2 = new ChildClass2();
$child2->on_save_changes();
// Hello Second World
The parent class has the protected method setChildActionMethod, callable by the children. When the children are instantiated, they tell the parent the name of the method they would like it to call on save.
If the method exists then it is called with any arguments, or it throws an exception (you can change the error handling).
I'm sure theres a name for this pattern, but I am unsure what it is called.
You may use "Template method" pattern, if you need to create some action sequence in parent that child classes should implement on their own but in some predefined manner. But you should avoid referring to future defined arbitrary methods.
In general: any method you use in your parent should be declared either as abstract or have default implementation. Children will override these methods.
abstract class parent{
function on_save_changes(){
some_parent_function();
some_child_action();
some_other_parent_function(); // added to follow changes of question
}
function some_parent_function(){
// Do something here, required by multiple child Classes
}
abstract public function some_child_action();
}
class child_1 Extends parent{
function some_child__action(){
if($_POST['condition'] === 'A') :
// Do something here, only every required by this child Class
endif;
}
}
class child_2 Extends parent{
function some_child_action(){
if($_POST['condition'] === 'B') :
// Do something here, only every required by this child Class
endif;
}
}

Overriding methods in PHP?

In other OO languages like Java we can override a function, possible using keywords/annotations like implements, #override etc.
Is there a way to do so in PHP? I mean, for example:
class myClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
I want user to implement their own myClass::reImplementThis() method.
How can I do that in PHP? If it is possible, can I make it optional?
I mean, if the user is not implementing the method, can I specify a default method or can I identify that the method is not defined (can I do this using method_exists)?
<?php
abstract class Test
{
abstract protected function test();
protected function anotherTest() {
}
}
class TestTest extends Test
{
protected function test() {
}
}
$test = new TestTest();
?>
This way the class TestTest must override the function test.
Yes, there is. You have the option to override a method by extending the class and defining a method with the same name, function signature and access specifier (either public or protected) it had in the base class. The method should not be declared abstract in the base class or you will be required to implement it in the derived class. In you example it would look something like this:
class MyClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
class MyDerivedClass extends MyClass {
public static function reImplmentThis() { //the method you want to call
}
}
If the user does not overrides it, MyDerivedClass will still have a reImplmentThis() method, the one inherited from MyClass.
That said, you need to be very careful when invoking extended static methods from your derived class to stay out of trouble. I encourage you to refactor your code to extend instance methods unless you have a very specific need to extend static classes. And if you decide there is no better way than extending static classes please be sure to understand Late Static Binding pretty well.
Yes, its possible to check if the method is implemented or not and get a whole lot more of information about a class using PHP Reflection.
This touches on several OOP subjects.
First, simply overriding an method declared in a parent class is as simple as re-declaring the method in an inheriting class.
E.g:
class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
}
class Tommy extends Person {
public function greet(string $whom = "everyone") {
echo "Howdy $whom! How are you?";
}
}
$a = new Tommy();
$a->greet('World');
// outputs:
// Howdy World! How are you?
If on the overriding method you wan to reuse the logic of the overriden one, it's just a matter of calling the parent's method from the extending class::
class Tommy
{
public function greet(string $whom)
{
// now with more emphasis!!!
echo parent::greet(strtoupper($whom)) . "!!!!";
}
}
Now Tommy::greet() calls Person::greet(), but modifies the result before returning it.
One thing to note is that overriding methods have to be compatible with the overriden one: the method visibility can't be more restrictive than the original one (it's OK to increase visibility), and the number and type of required arguments can't conflict with the original delcaration.
This works, because the type of the arguments does not clash with the original, and we have less required arguments than on the parent:
class Leo extends Person {
public function greet(string $whom = "gorgeous", string $greet = "Whatsup" ) {
echo "$greet $whom. How are you?";
}
}
But this doesn't, since there are additional required arguments. This would make impossible to switch the original class for this one transparently, and thus would throw a Warning:
class BadBob extends Person {
public function greet(string $whom, string $greet ) {
echo "$greet $whom. How are you?";
}
}
Additionally, you mention in your question that "this method should be overriden by the user". If you require client classes to actually implement the method, you have a couple of options:
Abstract classes & methods
These are methods where the implementation is left empty, and that extending classes have to implement to be valid. In we changed our original class Person to:
abstract class Person {
public function greet(string $whom) {
echo "hello $whom!";
}
public abstract function hide();
}
Since now the class contains an abstract method, it needs to be declared as an abstract class as well.
Now it is not possible to instantiate Person directly, you can only extend it in other classes.
Now all our existing Person extending classes would be wrong, and trying to execute the previous code would throw a fatal error.
An example of a valid class extending Person now would be:
class Archie extends Person {
public function hide() {
echo "Hides behind a bush";
}
}
Any class that extends Person must declare a public hide() method.
Interfaces
Finally, you mention interfaces. Interfaces are contracts that implementing classes have to fulfill. They declare a group of public methods without an implementation body.
E.g.:
interface Policeman {
public function arrest(Person $person) : bool;
public function help($what): bool;
}
Now we could have class that extended Person and implemented Policeman:
class Jane extends Person implements Policeman {
public function hide() {
echo "Jane hides in her patrol-car";
}
public function arrest(Person $person): bool{
// implement arrest method
return false;
}
public function shoot($what): bool {
// implements shoot() method
return false;
}
}
Importantly, while it's possible to extend only one class (there is no multiple inheritance in PHP), it is possible to implement multiple interfaces, and the requirements for each of those have to be fulfilled for the class to be valid.

Is it proper for a parent class to reference a property that exists only in the child?

In the project my team is currently working on, we're modifying a commercial PHP application. The app is strewn with code where a parent class checks for and works with a property that doesn't exist in the parent class, like so:
class A
{
function doSomething()
{
if (property_exists($this, 'some_property'))
{
$this->some_property = $_REQUEST['val'];
}
}
}
class B extends A
{
protected $some_property;
function doSomething()
{
parent::doSomething();
}
}
We feel vaguely dirty having to modify this code; is this proper design? What are the ways (other than the obvious) something like this can be avoided?
You might consider abstracting the parent class. So the methods that the children must have are declared in the parent, but not implemented.
Relying upon methods that must exist in a subclass is not dirty, as long as you can declare them as abstract.
However, it is not good practice to rely on and manipulate properties outside of a class. It's best to use abstract setters, like this:
abstract class A
{
abstract protected function setSomeProperty($data);
public function doSomething()
{
$this->setSomeProperty($_REQUEST['val']);
}
}
class B extends A
{
private $some_property;
public function doSomething()
{
parent::doSomething();
}
protected function setSomeProperty($data)
{
$this->some_property = $data;
}
}
More info here: PHP Class Abstraction
However, since you said you're not allowed to modify the parent class, I would suggest making a subclass that acts as an Adapter to what the parent class "expects", and a class that you're able to design "properly".
You can create a virtual method hook in the parent class which can later be overridden by children.
I think it's more neat to create a sub-class, where all members have function doSomething(). In that case you don't create a not-working function in a parent class (with eventual hacks), but still have the general "super-function".
class A
{
}
class C extends A {
protected $some_property;
function doSomething()
{
$this->some_property = $_REQUEST['val'];
}
}
class B extends C
{
protected $some_property;
function doSomething()
{
parent::doSomething();
}
}

Categories