Extending PHP library with traits or inheritance? - php

As a software developer I want to provide an extended library for my customers. The original library of the library provider should not be changed.
There are several ways to do this. Traits come into mind but also inheritance.
Assuming there is a class in the original library defined as:
class Super {}
First approach: Extending the original library using traits:
trait MyTrait {
public function func() {
echo "func in MyTrait\n";
}
}
// Customer writes in his code:
class Sub1 extends Super {
use MyTrait;
}
$sub1 = new Sub1;
$sub1->func();
Second approach:Extending the original library using inheritance:
class LibExtension extends Super {
public function func() {
echo "func in LibExtension\n";
}
}
// Customer writes in his code:
class Sub2 extends LibExtension {
}
$sub2 = new Sub2;
$sub2->func();
What are advantages of using traits vs. inheritace in this scenario?
Which approach is more limited in which case? Which one gives more flexibility for me as software developer or the customer?
Is there any difference in these approaches if we are in the open source or closed source domain?
Are there better approaches for this scenario?

It is very difficult to recommend some approach over another one, but in many cases composition is more suitable way of providing flexibility to the end user.
Considering your trait sample:
trait MyTrait {
public function func() {
echo "func in MyTrait\n";
}
}
// Customer writes in his code:
class Sub1 extends Super {
use MyTrait;
}
$sub1 = new Sub1;
$sub1->func();
it could be rewritten as such:
interface FuncPrinterInterface
{
public function funcPrint();
}
class FuncPrinter implements FuncPrinterInterface
{
public function funcPrint()
{
echo "func in MyTrait\n";
}
}
class UserClass
{
/**
* #var FuncPrinterInterface
*/
protected $printer;
/**
* Sub1 constructor.
*
* #param FuncPrinterInterface $printer
*/
public function __construct(FuncPrinterInterface $printer)
{
$this->printer = $printer;
}
public function doSomething()
{
$this->printer->funcPrint();
}
}
$sub1 = new UserClass(new FuncPrinter());
$sub1->doSomething();

Related

php same method in different classes

I have various classes with a method having the same code. Maintenance point of view is a very bad practice.
This is an example of this classes:
Class accountController:
<?php
namespace controller\admin;
class accountController extends \controller\baseController
{
private $table = 'account';
public function itemslist()
{
list($res, $totalcount) = $this->getResultAndCount();
return $this->twig->render('/admin/accounts.html.twig');
}
.
... other methods
.
private function getResultAndCount()
{
$sql = 'SELECT * FROM ' . $this->table;
$count = $this->pdo->rowCount();
$rows = $this->pdo->resultset();
return array($rows, $count);
}
}
Class userController:
<?php
namespace controller\admin;
class userController extends \controller\baseController
{
private $table = 'user';
public function itemslist()
{
list($res, $totalcount) = $this->getResultAndCount();
return $this->twig->render('/admin/users.html.twig');
}
.
... other methods
.
private function getResultAndCount()
{
$sql = 'SELECT * FROM ' . $this->table;
$count = $this->pdo->rowCount();
$rows = $this->pdo->resultset();
return array($rows, $count);
}
}
As shown the method getResultAndCount, having the same code, is duplicated. Not being an expert in OOP I have been searching the way to have just one code somewhere and reference ti it in the itemslistAction() method.
I have seen ways to do this, like having another class with this method and calling it, interfaces, method in the parent class, ... but I'm confused and I wonder wich will be the best way to implemented it and how.
Both of your classes extends \controller\baseController class. You could put the duplicate function in the \controller\baseController class but if you have other classes that extends \controller\baseController and if you are going to use this function only in the classes you declared, you could create a new class that extends \controller\baseController and implement the duplicate function in this class.
<?php
namespace controller\admin;
class bridgeClass extends \controller\baseController
{
//...
protected function getResultAndCount()
{
$sql = 'SELECT * FROM ' . $this->table;
$count = $this->pdo->rowCount();
$rows = $this->pdo->resultset();
return array($rows, $count);
}
}
?>
We implemented the function in the bridgeClass as declared above. Also notice that we changed the visibility of function from private to protected so the child classes can access the function without a problem. Then you can make both of your classes extends bridgeClass. So in that case now both of your classes have bridgeClass and \controller\baseController as their parents.
<?php
namespace controller\admin;
abstract class baseController
{
private $table;
public function itemslist()
{
list($res, $totalcount) = $this->getResultAndCount();
return $this->twig->render('/admin/accounts.html.twig');
}
private function getResultAndCount()
{
$sql = 'SELECT * FROM ' . $this->table;
$count = $this->pdo->rowCount();
$rows = $this->pdo->resultset();
return array($rows, $count);
}
}
Class accountController:
<?php
namespace controller\admin;
class accountController extends \controller\baseController
{
private $table = 'account';
// more method ....
}
Class userController:
<?php
namespace controller\admin;
class userController extends \controller\baseController
{
private $table = 'user';
// more method ....
}
Just scratch:
interface IValue{
public function value();
}
class DBQuery implements IValue{
private $pdo;
private $sql;
public function __construct(...){
....
}
public function value(){
// execute $this->sql
}
}
class LazyTemplate{
private $twig;
private $template;
private $data;
public function __construct(..., IValue $data){
....
}
public function render(){
return $this->twig->render(
$this->template,
$this->data->value()
);
}
}
namespace controller\admin;
class accountController extends \controller\baseController
{
private $items;
public function __construct(...){
$this->items = new LazyTemplate(
$this->twig,
'/admin/accounts.html.twig',
new DBQuery($this->pdo, 'SELECT * FROM account')
);
}
public function itemslist()
{
return $this->items->render();
}
}
class userController extends \controller\baseController
{
private $items;
public function __construct(...){
$this->items = new LazyTemplate(
$this->twig,
'/admin/users.html.twig',
new DBQuery($this->pdo, 'SELECT * FROM user')
);
}
public function itemslist()
{
return $this->items->render();
}
}
P. s. I don't know Twig API, so there may be better way.
Many suggested using inheritance to remove duplication of code. Indeed, inheritance allows you to do this quickly and simply, but consider the shortcomings of this approach:
Our classes are getting bigger, although the domain model does not require it.
We might easily need a few lists, but we have provided only one inheritance. Blow up the base class even more?
Lists may be required elsewhere. Copy the code there and get duplication again?
We just complicate the testing. It was necessary to add a very small aspect that is easy to test, but now we have this part of the whole hierarchy.
It follows from our intentions. What did we really want to say with duplicate code? - I would put it this way: "it is necessary somehow to get the data and * somehow* transfer them to the template". "somehow" is, I would say, the boundaries of abstraction, those places that should be highlighted in separate entities.
"somehow transfer them (data) to a template" - is some kind of entity that, on demand, takes data, gives it to the template and returns the result of the render. I called this entity LazyTemplate, because it performs" lazy calculations "(even without caching, as it usually happens).
LazyTemplate could receive data immediately or through a closure, but I chose the interfaceIValue. Interfaces are "strict types" and we can easily provide parameter checking by PHP itself (5.0+). Also, we do not require these data until the moment of emergency. If our list is hidden, then there is no sense in executing the query to the DB. IValue is simply a contract betweenLazyTemplate and its environment.
"somehow get the data" - this is another entity. Ideally, this entity should not specify the source of this data, but, for simplicity, I decided to immediately describe the class DBQuery. In addition, we already have IValue, which performs the same function.
Of course, we had to introduce several additional abstractions (very small ones, worth noting), but now we can re-use them, extend them (for example, by creating the class CachedValue,DynamicTemplate, etc.) and test only a specific functional.
The controllers still have similar lines of code, but do not blindly try to eradicate duplication. The list of users and the list of accounts are two different lists and they can, in the future, become absolutely incompatible.
P. s. I apologize for any mistakes.

PHP Traits: How to circumvenient constructors or force them to be called?

Have a look at the following trait:
trait PrimaryModelRest {
use RestController;
protected $primaryModel;
public function __construct() {
$mc = $this->getPrimaryModelClass();
try {
$this->primaryModel = new $mc();
if(!($this->primaryModel instanceof Model)) {
throw new ClassNotFoundException("Primary Model fatal exception: The given Class is not an instance of Illuminate\Database\Eloquent\Model");
}
} catch (Exception $e) {
throw new WrongImplementationException("Primary Model Exception: Class not found.");
}
}
/**
* #return string: Classname of the primary model.
*/
public abstract function getPrimaryModelClass();
// various functions here
}
As you can see the trait makes sure that the using class holds a certain model instance and it implements certain methods. This works as long as the implementing class does not override the constructor.
So here is my question: I want to make sure that either the constructor is called or a better solution, such that I can instantiate this model on initialization.
Please make in answer which respects Multiple inheritance as well es Multi-Level inheritance.
I think you are trying to make the trait do a job it is not designed for.
Traits are not a form of multiple inheritance, but rather "horizontal reuse" - they're often described as "compiler-assisted copy-and-paste". As such, the job of a trait is to provide some code, so that you don't have to copy it into the class manually. The only relationship it has is with the class where the use statement occurs, where the code is "pasted". To aid in this role, it can make some basic requirements of that target class, but after that, the trait takes no part in inheritance.
In your example, you are concerned that a sub-class might try to access $primaryModel without running the constructor code which initialises it, and you are trying to use the trait to enforce that; but this is not actually the trait's responsibility.
The following definitions of class Sub are completely equivalent:
trait Test {
public function foo() {
echo 'Hello, World!';
}
}
class ParentWithTrait {
use Test;
}
class Sub inherits ParentWithTrait {
}
vs:
class ParentWithMethodDefinition {
public function foo() {
echo 'Hello, World!';
}
}
class Sub inherits ParentWithMethodDefinition {
}
In either case, class Sub could have its own definition of foo(), and by-pass the logic you'd written in the parent class.
The only contract that can prevent that is the final keyword, which in your case would mean marking your constructor as final. You can then provide an extension point that can be overridden for sub-classes to add their own initialisation:
class Base {
final public function __construct() {
important_things(); // Always run this!
$this->onConstruct(); // Extension point
}
protected function onConstruct() {
// empty default definition
}
}
class Sub {
protected function onConstruct() {
stuff_for_sub(); // Runs after mandatory important_things()
}
}
A trait can also mark its constructor as final, but this is part of the code being pasted, not a requirement on the class using the trait. You could actually use a trait with a constructor, but then write a new constructor as well, and it would mask the trait's version completely:
trait Test {
final public function __construct() {
echo "Trait Constructor";
}
}
class Noisy {
use Test;
}
class Silent {
use Test;
public function __construct() {
// Nothing
}
}
As far as the trait is concerned, this is like buying a bottle of beer and pouring it down the sink: you asked for its code and didn't use it, but that's your problem.
Crucially, though, you can also alias the methods of the trait, creating a new method with the same code but a different name and/or a different visibility. This means you can mix in code from traits which declare constructors, and use that code in a more complex constructor, or somewhere else in the class altogether.
The target class might also use the "final + hook" pattern:
trait TestOne {
final public function __construct() {
echo "Trait TestOne Constructor\n";
}
}
trait TestTwo {
final public function __construct() {
echo "Trait TestTwo Constructor\n";
}
}
class Mixed {
final public function __construct() {
echo "Beginning\n";
$this->testOneConstructor();
echo "Middle\n";
$this->testTwoConstructor();
echo "After Traits\n";
$this->onConstruct();
echo "After Sub-Class Hook\n";
}
use TestOne { __construct as private testOneConstructor; }
use TestTwo { __construct as private testTwoConstructor; }
protected function onConstruct() {
echo "Default hook\n";
}
}
class ChildOfMixed extends Mixed {
protected function onConstruct() {
echo "Child hook\n";
}
}
The trait hasn't forced the Mixed class to implement this pattern, but it has enabled it, in keeping with its purpose of facilitating code reuse.
Interestingly, the below code doesn't work, because the as keyword adds an alias, rather than renaming the normal method, so this ends up trying to override the final constructor from Mixed:
class ChildOfMixed extends Mixed {
use TestTwo { __construct as private testTwoConstructor; }
protected function onConstruct() {
$this->testTwoConstructor();
echo "Child hook\n";
}
}
Use a base class, this will let you handle the trait as a parent.
<?php
trait StorageTrait
{
public function __construct()
{
echo "Storage Trait";
}
}
class StorageAttempt
{
use StorageTrait;
public function __construct()
{
parent::__construct();
echo " - Storage Attempt";
}
}
abstract class StorageBase
{
use StorageTrait;
}
class MyStorage extends StorageBase
{
public function __construct()
{
parent::__construct();
echo ' - My Storage';
}
}
new StorageAttempt(); // won't work - will trigger error
new MyStorage(); // will display "Storage Trait - My Storage"
Also if you are using traits you can also work with properties and getters & setters.
Example: A Storage trait involves that a Storage Engine will be used. You can add the storageEngine property and its getters and setters. (with or without Type Hinting)
interface StorageEngineInterface{}
trait StorageTrait
{
/**
* #var StorageEngineInterface
*/
protected $storageEngine;
/**
* #return StorageEngineInterface
*/
public function getStorageEngine(): StorageEngineInterface
{
return $this->storageEngine;
}
/**
* #param StorageEngineInterface $storageEngine
*/
public function setStorageEngine(StorageEngineInterface $storageEngine)
{
$this->storageEngine = $storageEngine;
return $this;
}
}
Note: this is just an explanation so you can better understand how Traits work
UPDATE
To avoid conflict you can use aliases for trait methods. This way you can use both constructors (from trait and from extended class) you can do the following
class DifferentStorage
{
public function __construct()
{
echo ' diff ';
}
}
class MyDifferentStorage extends DifferentStorage
{
use StorageTrait {
StorageTrait::__construct as otherConstructor;
}
public function __construct()
{
parent::__construct();
self::otherConstructor();
}
}
You could use the interface injection pattern: implement an interface iPrimaryModelRest into the same class that uses the trait PrimaryModelRest:
interface iPrimaryModelRest {
public function init();
public abstract function getPrimaryModelClass();
}
The class that uses the trait woud look like this:
class cMyClass implements iPrimaryModelRest {
use PrimaryModelRest;
}
Then, whenever the class is instantiated (not only autoloaded) you could call a special factory-like initialisation function like this:
class cMyApp {
public function start() {
/** #var cMyClass $oClass */ // enlighten IDE
$oClass = $this->init(new cMyClass);
}
public function init($oClass) {
if ($oClass instanceof iPrimaryModelRest) {$oClass->init();}
if ($oClass instanceof whateverinterface) {
// pass optional stuff, like database connection
}
}
}
The interface is used to determine the capabilities of the class, and sets data/runs corresponding functions. If I'm not mistaken then this pattern is called a Service Locator.
I needed a trait for database connection. To avoid using the __construct in a trait, I've used a magic getter instead:
trait WithDatabaseConnection
{
public function __get(string $name)
{
if ($name === 'pdo') {
return App::make(\PDO::class);
}
trigger_error("Property $name does not exist.");
return null;
}
}
class Foo {
use WithDatabaseConnection;
public function save() {
$this->pdo->query('...');
}
}

Real world implementation of interfaces

This question might sound obvious and might be stupid as well. But I am trying to figure out why do I need to use interfaces? I think I can handle most of the things which interfaces do using classes then what's the point of using them? It's true that I might end up in problems if I don't interfaces but I am trying to figure out what problems are caused by not using interfaces?
One use of interfaces is that they allow us to define behaviors and put restrictions on of classes which implement them.
Another use is that interface work as types and I can use interfaces for type hinting as shown below.
//Java example
public interface IPaintable{
void Paint(System.Drawing.Color color);
}
public void Paint(IPaintable item, System.Drawing.Color color){
item.Paint(color);
}
But are there any other use of interfaces in PHP?
I.e. What advantages do I get by using interfaces in the code below.
//Non interface implementation
<?php
class DBPersonProvider
{
public function getPerson($givenName, $familyName)
{
/* go to the database, get the person... */
$person = new Person();
$person->setPrefix("Mr.");
$person->setGivenName("John");
return $person;
}
}
/* I need to get person data... */
$provider = new DBPersonProvider();
$person = $provider->getPerson("John", "Doe");
echo($person->getPrefix());
echo($person->getGivenName());
?>
//Implementation with interface
<?php
interface PersonProvider
{
public function getPerson($givenName, $familyName);
}
class DBPersonProvider implements PersonProvider
{
public function getPerson($givenName, $familyName)
{
/* pretend to go to the database, get the person... */
$person = new Person();
$person->setPrefix("Mr.");
$person->setGivenName("John");
return $person;
}
}
/* I need to get person data... */
$provider = new DBPersonProvider();
$person = $provider->getPerson("John", "Doe");
echo($person->getPrefix());
echo($person->getGivenName());
?>
I write a nice library that interacts with the database. And I use MySQL. When you purchase my library, you know it's MySQL based but you roll with SQL Server. I was considerate enough to create interfaces for the Database access. And I provided an implementation for MySQL. Now you can implement your own SQL Server wrapper around my database access interface, and then use it as a __construct() argument for the classes in the library you will use to change move storage to SQL Server.
Interfaces are very useful for library / reusable code writers like me :) They are code contracts that have to be obeyed. You know that any class that implements them WILL have a set of functions exactly as the Interface declared them. And you can also statically type them in function arguments like function(MyInterface $Object) which enforces, at PHP compiler level, that $Object must be implementing MyInterface.
PS: Abstract classes are good enough for the rest of self-written code consuming developers...
UPDATE:
/**
* Database Access functionality blueprint.
*/
interface IDatabaseAccess {
public function Connect();
public function Query();
public function Fetch();
}
/**
* Database Access functionality implementation for MySQL.
*/
class MySqlDatabaseAccess implements IDatabaseAccess {
public function Query(){
// do mysql stuff
}
public function Fetch(){
// do mysql stuff
}
}
/**
* Database Access functionality implementation for SQLServer.
*/
class SqlServerDatabaseAccess implements IDatabaseAccess {
public function Query(){
// do sqlserver stuff
}
public function Fetch(){
// do sqlserver stuff
}
}
/**
* Database Access consumer that's database system agnostic.
*/
class DatabaseAccessConsumer {
protected $_Provider = null;
public function __construct(IDatabaseAccess $Provider){
$this->_Provider = $Provider;
$this->_Provider->Connect();
}
public function Query(){
return $this->_Provider->Query();
}
public function Fetch(){
return $this->_Provider->Fetch();
}
}
^ code that should speak for itself.
Interfaces actually provide less features than abstract classes (you cannot implement anything).
But they resolve the problem of multiple inheritance. Most modern language do not allow a class to derive more than one class. By using an interface, which does not implement any method, you are sure there is no ambiguity when you invoke a method from the interface (because there is no implementation).
Example (syntactically not valid):
class A {
public foo() {
echo 'I am A and I foo';
};
public
}
class B {
public foo() {
echo 'I am B and I foo';
}
}
class C extends A, B { // invalid
public bar() {
foo(); // which one? A's or B's?
}
}
Second example:
class A {
public foo() {
echo 'I am A and I foo';
};
}
interface iB {
public foo();
public bar();
}
interface iC {
public foo();
public qux();
}
class D extends A implements iB, iC {
public bar() {
foo(); // no ambiguity, this is A::foo(), even if the method is also declared in the interfaces
}
public qux() {}
}
Interfaces are just blueprints of classes - they are ways of saying "If you are going to be doing something with this type of class, it must have this and do this." It allows you to control - to an extent - what another class will have/do at a minimum for a given situation. Not every situation calls for an iterface. Interfaces are best used in situations when you need to have some control over the basic code of certain classes but you may not be the one writing them. If you know that the extended classes will have x properties and y methods, then you can do basic future class support.

Nested or Inner Class in PHP

I'm building a User Class for my new website, however this time I was thinking to build it little bit differently...
C++, Java and even Ruby (and probably other programming languages) are allowing the use of nested/inner classes inside the main class, which allows us to make the code more object-oriented and organized.
In PHP, I would like to do something like so:
<?php
public class User {
public $userid;
public $username;
private $password;
public class UserProfile {
// some code here
}
private class UserHistory {
// some code here
}
}
?>
Is that possible in PHP? How can I achieve it?
UPDATE
If it's impossible, will future PHP versions might support nested classes?
Intro:
Nested classes relate to other classes a little differently than outer classes. Taking Java as an example:
Non-static nested classes have access to other members of the enclosing class, even if they are declared private. Also, non-static nested classes require an instance of the parent class to be instantiated.
OuterClass outerObj = new OuterClass(arguments);
outerObj.InnerClass innerObj = outerObj.new InnerClass(arguments);
There are several compelling reasons for using them:
It is a way of logically grouping classes that are only used in one place.
If a class is useful to only one other class, then it is logical to
relate and embed it in that class and keep the two together.
It increases encapsulation.
Consider two top-level classes, A and B, where B needs access to
members of A that would otherwise be declared private. By hiding class
B within class A, A's members can be declared private and B can access
them. In addition, B itself can be hidden from the outside world.
Nested classes can lead to more readable and maintainable code.
A nested class usually relates to it's parent class and together form a "package"
In PHP
You can have similar behavior in PHP without nested classes.
If all you want to achieve is structure/organization, as Package.OuterClass.InnerClass, PHP namespaces might sufice. You can even declare more than one namespace in the same file (although, due to standard autoloading features, that might not be advisable).
namespace;
class OuterClass {}
namespace OuterClass;
class InnerClass {}
If you desire to emulate other characteristics, such as member visibility, it takes a little more effort.
Defining the "package" class
namespace {
class Package {
/* protect constructor so that objects can't be instantiated from outside
* Since all classes inherit from Package class, they can instantiate eachother
* simulating protected InnerClasses
*/
protected function __construct() {}
/* This magic method is called everytime an inaccessible method is called
* (either by visibility contrains or it doesn't exist)
* Here we are simulating shared protected methods across "package" classes
* This method is inherited by all child classes of Package
*/
public function __call($method, $args) {
//class name
$class = get_class($this);
/* we check if a method exists, if not we throw an exception
* similar to the default error
*/
if (method_exists($this, $method)) {
/* The method exists so now we want to know if the
* caller is a child of our Package class. If not we throw an exception
* Note: This is a kind of a dirty way of finding out who's
* calling the method by using debug_backtrace and reflection
*/
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
if (isset($trace[2])) {
$ref = new ReflectionClass($trace[2]['class']);
if ($ref->isSubclassOf(__CLASS__)) {
return $this->$method($args);
}
}
throw new \Exception("Call to private method $class::$method()");
} else {
throw new \Exception("Call to undefined method $class::$method()");
}
}
}
}
Use case
namespace Package {
class MyParent extends \Package {
public $publicChild;
protected $protectedChild;
public function __construct() {
//instantiate public child inside parent
$this->publicChild = new \Package\MyParent\PublicChild();
//instantiate protected child inside parent
$this->protectedChild = new \Package\MyParent\ProtectedChild();
}
public function test() {
echo "Call from parent -> ";
$this->publicChild->protectedMethod();
$this->protectedChild->protectedMethod();
echo "<br>Siblings<br>";
$this->publicChild->callSibling($this->protectedChild);
}
}
}
namespace Package\MyParent
{
class PublicChild extends \Package {
//Makes the constructor public, hence callable from outside
public function __construct() {}
protected function protectedMethod() {
echo "I'm ".get_class($this)." protected method<br>";
}
protected function callSibling($sibling) {
echo "Call from " . get_class($this) . " -> ";
$sibling->protectedMethod();
}
}
class ProtectedChild extends \Package {
protected function protectedMethod() {
echo "I'm ".get_class($this)." protected method<br>";
}
protected function callSibling($sibling) {
echo "Call from " . get_class($this) . " -> ";
$sibling->protectedMethod();
}
}
}
Testing
$parent = new Package\MyParent();
$parent->test();
$pubChild = new Package\MyParent\PublicChild();//create new public child (possible)
$protChild = new Package\MyParent\ProtectedChild(); //create new protected child (ERROR)
Output:
Call from parent -> I'm Package protected method
I'm Package protected method
Siblings
Call from Package -> I'm Package protected method
Fatal error: Call to protected Package::__construct() from invalid context
NOTE:
I really don't think trying to emulate innerClasses in PHP is such a good idea. I think the code is less clean and readable. Also, there are probably other ways to achieve similar results using a well established pattern such as the Observer, Decorator ou COmposition Pattern. Sometimes, even simple inheritance is sufficient.
Real nested classes with public/protected/private accessibility were proposed in 2013 for PHP 5.6 as an RFC but did not make it (No voting yet, no update since 2013 - as of 2021/02/03):
https://wiki.php.net/rfc/nested_classes
class foo {
public class bar {
}
}
At least, anonymous classes made it into PHP 7
https://wiki.php.net/rfc/anonymous_classes
From this RFC page:
Future Scope
The changes made by this patch mean named nested classes are easier to implement (by a tiny bit).
So, we might get nested classes in some future version, but it's not decided yet.
You cannot do this in PHP. However, there are functional ways to accomplish this.
For more details please check this post:
How to do a PHP nested class or nested methods?
This way of implementation is called fluent interface: http://en.wikipedia.org/wiki/Fluent_interface
As per Xenon's comment to Anıl Özselgin's answer, anonymous classes have been implemented in PHP 7.0, which is as close to nested classes as you'll get right now. Here are the relevant RFCs:
Nested Classes (status: withdrawn)
Anonymous Classes (status: implemented in PHP 7.0)
An example to the original post, this is what your code would look like:
<?php
public class User {
public $userid;
public $username;
private $password;
public $profile;
public $history;
public function __construct() {
$this->profile = new class {
// Some code here for user profile
}
$this->history = new class {
// Some code here for user history
}
}
}
?>
This, though, comes with a very nasty caveat. If you use an IDE such as PHPStorm or NetBeans, and then add a method like this to the User class:
public function foo() {
$this->profile->...
}
...bye bye auto-completion. This is the case even if you code to interfaces (the I in SOLID), using a pattern like this:
<?php
public class User {
public $profile;
public function __construct() {
$this->profile = new class implements UserProfileInterface {
// Some code here for user profile
}
}
}
?>
Unless your only calls to $this->profile are from the __construct() method (or whatever method $this->profile is defined in) then you won't get any sort of type hinting. Your property is essentially "hidden" to your IDE, making life very hard if you rely on your IDE for auto-completion, code smell sniffing, and refactoring.
Since PHP version 5.4 you can force create objects with private constructor through reflection. It can be used to simulate Java nested classes. Example code:
class OuterClass {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function forkInnerObject($name) {
$class = new ReflectionClass('InnerClass');
$constructor = $class->getConstructor();
$constructor->setAccessible(true);
$innerObject = $class->newInstanceWithoutConstructor(); // This method appeared in PHP 5.4
$constructor->invoke($innerObject, $this, $name);
return $innerObject;
}
}
class InnerClass {
private $parentObject;
private $name;
private function __construct(OuterClass $parentObject, $name) {
$this->parentObject = $parentObject;
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getParent() {
return $this->parentObject;
}
}
$outerObject = new OuterClass('This is an outer object');
//$innerObject = new InnerClass($outerObject, 'You cannot do it');
$innerObject = $outerObject->forkInnerObject('This is an inner object');
echo $innerObject->getName() . "\n";
echo $innerObject->getParent()->getName() . "\n";
You can't do it in PHP. PHP supports "include", but you can't even do that inside of a class definition. Not a lot of great options here.
This doesn't answer your question directly, but you may be interested in "Namespaces", a terribly ugly\syntax\hacked\on\top\of PHP OOP:
http://www.php.net/manual/en/language.namespaces.rationale.php
I think I wrote an elegant solution to this problem by using namespaces. In my case, the inner class does not need to know his parent class (like the static inner class in Java). As an example I made a class called 'User' and a subclass called 'Type', used as a reference for the user types (ADMIN, OTHERS) in my example. Regards.
User.php (User class file)
<?php
namespace
{
class User
{
private $type;
public function getType(){ return $this->type;}
public function setType($type){ $this->type = $type;}
}
}
namespace User
{
class Type
{
const ADMIN = 0;
const OTHERS = 1;
}
}
?>
Using.php (An example of how to call the 'subclass')
<?php
require_once("User.php");
//calling a subclass reference:
echo "Value of user type Admin: ".User\Type::ADMIN;
?>
You can, like this, in PHP 7:
class User{
public $id;
public $name;
public $password;
public $Profile;
public $History; /* (optional declaration, if it isn't public) */
public function __construct($id,$name,$password){
$this->id=$id;
$this->name=$name;
$this->name=$name;
$this->Profile=(object)[
'get'=>function(){
return 'Name: '.$this->name.''.(($this->History->get)());
}
];
$this->History=(object)[
'get'=>function(){
return ' History: '.(($this->History->track)());
}
,'track'=>function(){
return (lcg_value()>0.5?'good':'bad');
}
];
}
}
echo ((new User(0,'Lior','nyh'))->Profile->get)();
It is waiting for voting as RFC
https://wiki.php.net/rfc/anonymous_classes
This page keeps coming up in my Internet searches on this subject so figured I should chime in even though this is an 8-year old post. The documentation for PHP5 demonstrates that anonymous classes can be defined within a class method. The object created can extend, implement, and even use other classes, interfaces, and traits. Consider the following OOP paradigm of factory object production. Similar to what #e-i-pi pointed out ...
class Factory {
/**
* Method to manufacture an inner-class object.
*
* #param string $args Arguments to be passed to
* the inner-class constructor.
*/
static function manufacture_object($args) {
/**
* Here's the definition of the inner-class.
*/
return new class($args) {
static $remembers = 'Nothing';
private $args;
function __construct($args) {
$this->$args = $args;
}
function says() {
return $this->args;
}
};
}
}
/**
* Create an inner-class object and have it do its thing.
*/
$mort = Factory::manufacture_object("Hello World!");
echo $mort->says(); // Echoes "Hello World!"
The objects are one-off, so one would expect the static values of the objects returned would not bind from one instance to another. After all, the anonymous class is unique from one object to another. However, late static binding works as one would otherwise expect from a nested class.
$mort = Factory::manufacture_object("I can remember that.");
$mort2 = Factory::manufacture_object("I'll live vicariously through you.");
$mort::$remembers = 'Something';
echo $mort2::$remembers; // Echoes "Something"
So, there you go: inner/nested classes and creation of their objects with static functionality has been possible since September 22, 2013 (right about the time this question was asked).
Put each class into separate files and "require" them.
User.php
<?php
class User {
public $userid;
public $username;
private $password;
public $profile;
public $history;
public function __construct() {
require_once('UserProfile.php');
require_once('UserHistory.php');
$this->profile = new UserProfile();
$this->history = new UserHistory();
}
}
?>
UserProfile.php
<?php
class UserProfile
{
// Some code here
}
?>
UserHistory.php
<?php
class UserHistory
{
// Some code here
}
?>

Can I extend a class using more than 1 class in PHP?

If I have several classes with functions that I need but want to store separately for organisation, can I extend a class to have both?
i.e. class a extends b extends c
edit: I know how to extend classes one at a time, but I'm looking for a method to instantly extend a class using multiple base classes - AFAIK you can't do this in PHP but there should be ways around it without resorting to class c extends b, class b extends a
If you really want to fake multiple inheritance in PHP 5.3, you can use the magic function __call().
This is ugly though it works from class A user's point of view :
class B {
public function method_from_b($s) {
echo $s;
}
}
class C {
public function method_from_c($s) {
echo $s;
}
}
class A extends B
{
private $c;
public function __construct()
{
$this->c = new C;
}
// fake "extends C" using magic function
public function __call($method, $args)
{
$this->c->$method($args[0]);
}
}
$a = new A;
$a->method_from_b("abc");
$a->method_from_c("def");
Prints "abcdef"
You cannot have a class that extends two base classes. You could not have the following:
// this is NOT allowed (for all you google speeders)
Matron extends Nurse, HumanEntity
You could however have a hierarchy as follows...
Matron extends Nurse
Consultant extends Doctor
Nurse extends HumanEntity
Doctor extends HumanEntity
HumanEntity extends DatabaseTable
DatabaseTable extends AbstractTable
and so on.
You could use traits, which, hopefully, will be available from PHP 5.4.
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way, which reduces complexity and avoids the typical problems associated with multiple inheritance and Mixins.
They are recognized for their potential in supporting better composition and reuse, hence their integration in newer versions of languages such as Perl 6, Squeak, Scala, Slate and Fortress. Traits have also been ported to Java and C#.
More information: https://wiki.php.net/rfc/traits
Classes are not meant to be just collections of methods. A class is supposed to represent an abstract concept, with both state (fields) and behaviour (methods) which changes the state. Using inheritance just to get some desired behaviour sounds like bad OO design, and exactly the reason why many languages disallow multiple inheritance: in order to prevent "spaghetti inheritance", i.e. extending 3 classes because each has a method you need, and ending up with a class that inherits 100 method and 20 fields, yet only ever uses 5 of them.
There are plans for adding mix-ins soon, I believe.
But until then, go with the accepted answer. You can abstract that out a bit to make an "extendable" class:
class Extendable{
private $extender=array();
public function addExtender(Extender $obj){
$this->extenders[] = $obj;
$obj->setExtendee($this);
}
public function __call($name, $params){
foreach($this->extenders as $extender){
//do reflection to see if extender has this method with this argument count
if (method_exists($extender, $name)){
return call_user_func_array(array($extender, $name), $params);
}
}
}
}
$foo = new Extendable();
$foo->addExtender(new OtherClass());
$foo->other_class_method();
Note that in this model "OtherClass" gets to 'know' about $foo. OtherClass needs to have a public function called "setExtendee" to set up this relationship. Then, if it's methods are invoked from $foo, it can access $foo internally. It will not, however, get access to any private/protected methods/variables like a real extended class would.
Use traits as base classes. Then use them in a parent class. Extend it .
trait business{
function sell(){
}
function buy(){
}
function collectMoney(){
}
}
trait human{
function think(){
}
function speak(){
}
}
class BusinessPerson{
use business;
use human;
// If you have more traits bring more
}
class BusinessWoman extends BusinessPerson{
function getPregnant(){
}
}
$bw = new BusinessWoman();
$bw ->speak();
$bw->getPregnant();
See now business woman logically inherited business and human both;
EDIT: 2020 PHP 5.4+ and 7+
As of PHP 5.4.0 there are "Traits" - you can use more traits in one class, so the final deciding point would be whether you want really an inheritance or you just need some "feature"(trait). Trait is, vaguely said, an already implemented interface that is meant to be just used.
Currently accepted answer by #Franck will work but it is not in fact multiple inheritance but a child instance of class defined out of scope, also there is the `__call()` shorthand - consider using just `$this->childInstance->method(args)` anywhere you need ExternalClass class method in "extended" class.
Exact answer
No you can't, respectively, not really, as manual of extends keyword says:
An extended class is always dependent on a single base class, that is,
multiple inheritance is not supported.
Real answer
However as #adam suggested correctly this does NOT forbids you to use multiple hierarchal inheritance.
You CAN extend one class, with another and another with another and so on...
So pretty simple example on this would be:
class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...
Important note
As you might have noticed, you can only do multiple(2+) intehritance by hierarchy if you have control over all classes included in the process - that means, you can't apply this solution e.g. with built-in classes or with classes you simply can't edit - if you want to do that, you are left with the #Franck solution - child instances.
...And finally example with some output:
class A{
function a_hi(){
echo "I am a of A".PHP_EOL."<br>".PHP_EOL;
}
}
class B extends A{
function b_hi(){
echo "I am b of B".PHP_EOL."<br>".PHP_EOL;
}
}
class C extends B{
function c_hi(){
echo "I am c of C".PHP_EOL."<br>".PHP_EOL;
}
}
$myTestInstance = new C();
$myTestInstance->a_hi();
$myTestInstance->b_hi();
$myTestInstance->c_hi();
Which outputs
I am a of A
I am b of B
I am c of C
<?php
// what if we want to extend more than one class?
abstract class ExtensionBridge
{
// array containing all the extended classes
private $_exts = array();
public $_this;
function __construct() {$_this = $this;}
public function addExt($object)
{
$this->_exts[]=$object;
}
public function __get($varname)
{
foreach($this->_exts as $ext)
{
if(property_exists($ext,$varname))
return $ext->$varname;
}
}
public function __call($method,$args)
{
foreach($this->_exts as $ext)
{
if(method_exists($ext,$method))
return call_user_method_array($method,$ext,$args);
}
throw new Exception("This Method {$method} doesn't exists");
}
}
class Ext1
{
private $name="";
private $id="";
public function setID($id){$this->id = $id;}
public function setName($name){$this->name = $name;}
public function getID(){return $this->id;}
public function getName(){return $this->name;}
}
class Ext2
{
private $address="";
private $country="";
public function setAddress($address){$this->address = $address;}
public function setCountry($country){$this->country = $country;}
public function getAddress(){return $this->address;}
public function getCountry(){return $this->country;}
}
class Extender extends ExtensionBridge
{
function __construct()
{
parent::addExt(new Ext1());
parent::addExt(new Ext2());
}
public function __toString()
{
return $this->getName().', from: '.$this->getCountry();
}
}
$o = new Extender();
$o->setName("Mahdi");
$o->setCountry("Al-Ahwaz");
echo $o;
?>
I have read several articles discouraging inheritance in projects (as opposed to libraries/frameworks), and encouraging to program agaisnt interfaces, no against implementations.
They also advocate OO by composition: if you need the functions in class a and b, make c having members/fields of this type:
class C
{
private $a, $b;
public function __construct($x, $y)
{
$this->a = new A(42, $x);
$this->b = new B($y);
}
protected function DoSomething()
{
$this->a->Act();
$this->b->Do();
}
}
Multiple inheritance seems to work at the interface level.
I made a test on php 5.6.1.
Here is a working code:
<?php
interface Animal
{
public function sayHello();
}
interface HairyThing
{
public function plush();
}
interface Dog extends Animal, HairyThing
{
public function bark();
}
class Puppy implements Dog
{
public function bark()
{
echo "ouaf";
}
public function sayHello()
{
echo "hello";
}
public function plush()
{
echo "plush";
}
}
echo PHP_VERSION; // 5.6.1
$o = new Puppy();
$o->bark();
$o->plush();
$o->sayHello(); // displays: 5.6.16ouafplushhello
I didn't think that was possible, but I stumbled upon in the SwiftMailer source code, in the Swift_Transport_IoBuffer class, which has the following definition:
interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
I didn't play with it yet, but I thought it might be interesting to share.
I just solved my "multiple inheritance" problem with:
class Session {
public $username;
}
class MyServiceResponsetype {
protected $only_avaliable_in_response;
}
class SessionResponse extends MyServiceResponsetype {
/** has shared $only_avaliable_in_response */
public $session;
public function __construct(Session $session) {
$this->session = $session;
}
}
This way I have the power to manipulate session inside a SessionResponse which extends MyServiceResponsetype still being able to handle Session by itself.
If you want to check if a function is public see this topic : https://stackoverflow.com/a/4160928/2226755
And use call_user_func_array(...) method for many or not arguments.
Like this :
class B {
public function method_from_b($s) {
echo $s;
}
}
class C {
public function method_from_c($l, $l1, $l2) {
echo $l.$l1.$l2;
}
}
class A extends B {
private $c;
public function __construct() {
$this->c = new C;
}
public function __call($method, $args) {
if (method_exists($this->c, $method)) {
$reflection = new ReflectionMethod($this->c, $method);
if (!$reflection->isPublic()) {
throw new RuntimeException("Call to not public method ".get_class($this)."::$method()");
}
return call_user_func_array(array($this->c, $method), $args);
} else {
throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()");
}
}
}
$a = new A;
$a->method_from_b("abc");
$a->method_from_c("d", "e", "f");
You are able to do that using Traits in PHP which announced as of PHP 5.4
Here is a quick tutorial for you, http://culttt.com/2014/06/25/php-traits/
One of the problems of PHP as a programming language is the fact that you can only have single inheritance. This means a class can only inherit from one other class.
However, a lot of the time it would be beneficial to inherit from multiple classes. For example, it might be desirable to inherit methods from a couple of different classes in order to prevent code duplication.
This problem can lead to class that has a long family history of inheritance which often does not make sense.
In PHP 5.4 a new feature of the language was added known as Traits. A Trait is kind of like a Mixin in that it allows you to mix Trait classes into an existing class. This means you can reduce code duplication and get the benefits whilst avoiding the problems of multiple inheritance.
Traits
PHP does not yet support multiple class inheritance, it does however support multiple interface inheritance.
See http://www.hudzilla.org/php/6_17_0.php for some examples.
PHP does not allow multiple inheritance, but you can do with implementing multiple interfaces. If the implementation is "heavy", provide skeletal implementation for each interface in a seperate class. Then, you can delegate all interface class to these skeletal implementations via object containment.
Always good idea is to make parent class, with functions ... i.e. add this all functionality to parent.
And "move" all classes that use this hierarchically down. I need - rewrite functions, which are specific.
class A extends B {}
class B extends C {}
Then A has extended both B and C

Categories