I was wondering if its possible to call the parents __construct(), before the child's __construct() with inheritance in PHP.
Example:
class Tag {
__construct() {
// Called first.
}
}
class Form extends Tag {
__construct() {
// Called second.
}
}
new Form();
Ideally, I would be able to do something in between them. If this is not possible, is there an alternative, which would allow me to do this?
The reason I want to do this is to be able to load a bunch of default settings specific to the Tag that Form can use when __construct() is called.
EDIT: Sorry forgot to add this.. I'd rather not call the parent class from the child class. It's simply because it exposes some private data (for the parent) to the child, when you pass it as an argument
This is what I want to do:
$tag = new Tag($privateInfo, $publicInfo);
$tag->extend(new Form()); // Ideal function, prob doesn't work with inheritance.
Tag.php
class Tag {
private $privateInfo;
public $publicInfo;
__construct($private, $public) {
$this->privateInfo = $private;
$this->publicInfo = $public;
}
}
Form.php
class Form extends Tag {
__construct() {
echo $this->publicInfo;
}
}
Make sense?
Thanks!
Matt Mueller
Just call parent::__construct in the child.
class Form extends Tag
{
function __construct()
{
parent::__construct();
// Called second.
}
}
yeah just call parent::__construct() in your construct
Yes, but only internally (i.e., by writing a PHP extension), so if I were you I'd settle with calling parent::__construct(). See this section on the PHP wiki.
Sorry, PHP is not Java. I think not requiring (implicitly or explictly) the super constructor to be called was a very poor design decision.
From the sounds of it you may want to rethink your design so that you don't need to pass the parameters in the constructor. If you don't think it can be done, ask it as a question, you might be surprised by some of the suggestions.
The child class has the ability to override the parent constructor without calling it at all. I would recommend having a final method in the parent class. That way everyone knows you don't want this being overriden, and any inherited class (rightly) has access to do whatever it wants in the constructor.
class Father {
private $_privateData;
final function setPrivateData($privateData) {
$this->_privateData = $privateData;
}
}
Another, not recommended, more "reinventing the wheel", solution would be to define a function in the parent class, say _construct(), that's called in its own construct. Its not really clear, doesn't use language features/constructs, and is very specific to a single application.
One last thing to keep in mind: you can't really hide information from the child class. With Reflection, serialize, var_dump, var_export and all these other convenient APIs in the php language, if there is code that shouldn't do anything with the data, then there's not really much you can do asides from not store it. There are libraries and such that help create sandboxes, but its hard to sandbox an object from itself.
Edit: Somehow I missed Artefacto's answer, and I suppose he is right (I've never tried writing an extension to do that). Still, implementing it breaks developer expectations while making it harder to actually see code to explain what's going in.
Related
Fairly straightforward question. In C++ the parent constructor will be implicitly called before the child constructor, so what logic is there for PHP not to do things this way?
EDIT: I've got a good answer from Lukman, but I was hoping for more of a reason why there is a difference. Maybe the question should be why does C++ not allow custom calling of parent constructors? I guess that's another question though.
I think it's a good thing that PHP makes you call parent's constructor manually, because it allows child's constructor such as following:
public function __construct() {
// set up variables that parent::__construct() requires
$var1 = get_stuff_from_db();
$var2 = get_stuff_from_webservice();
parent::__construct($var1, $var2);
// continue setting up $this var
$this->default = 'Default';
$this->do_some_secret_stuff();
}
Or even:
public function __construct($param) {
// call differently based on condition
if (is_array($param))
$param['id'] = 0;
parent::__construct($param);
}
else {
parent::__construct($param, 0, TRUE);
}
// continue setting up $this var
$this->default = 'Default';
$this->do_some_secret_stuff();
}
Meaning, you are free to call the parent constructor anywhere within the child's and you are free to do stuff before and after the call. Ain't that a feature indeed?
When you don't have a constructor in the child class, then the parent one is automatically called.
If you decided to add a constructor to the child class, then of course you need to explicitly call the parent constructor. If you are already taking the time to add a constructor to your child class, then adding one more line of code parent::__construct(); doesn't seem to be a big deal. But the overriding is actually a convenient flexibility.
to avoid tight coupling that's why inheritance (extend keyword in java) is evil and interface class is prefered see Javaworld article:
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html
Still it would be great if there was some instruction to call the parent at some point with a special keyword like forward but I have not yet seen this in any language (even Rebol) except in an unknown language invented by Paul Allen (yeah the co-founder of Microsoft) which is Openscript.
This is a very basic architectural question and it is thus very hypothetical.
Imagine this simple setup:
I have a class representing a web object, with only one method that renders the object. However, this class extends a parent class which requires certain conditions to be met, so that the method is actually executed (so that the object is being rendered).
Example
class webObject__adminBase {
protected function shouldRender(){
return access::isAdmin();
}
}
class webObject__adminPanel extends webObject__adminBase {
public function invoke(){
if(!parent::shouldRender())
return;
// if still here, render the object
}
}
$panel = new webObject__adminPanel();
$panel->invoke();
The code above serves both: an example plus a practical explanatory approach to the problem.
The issue is: i would like to get around this problem without actually having to call a method in my parent class in the child's rendering method.
I would like to achieve a class design that assures that all i need to do is to extend the parent class webObject__adminBase. Any calls to any methods in my child class should be checked against certain conditions (as in this example systemAccess::isAdmin()) and only render if these conditions are met.
I hope my description is clear.
Since someone actually requested to close this question as "too broad", i decided to rephrase my actual question with a more direct reference to the question title:
Is there a way to intercept the progression (or even execution) of a child's method based on a condition checked for by its parent class (without calling a method on that parent class) ?
Here is one method of doing it, albeit quite simple. I'm sure there are better methods but this one tries to keep to your original methodology.
https://ideone.com/D5hA3H
Render Class
abstract class Render
{
abstract public function main();
public function __construct()
{
}
final public function render()
{
if (!$this->canRender()) return '';
return $this->main();
}
final public function canRender()
{
// Logic here
return true;
}
}
Admin Panel Class
class AdminPanel extends Render
{
public function main()
{
return "Admin Panel";
}
}
Execution
$panel = new AdminPanel();
echo $panel->render();
PeeHaa is right about the naming conventions, it is in the best interest to try and follow a popular coding style which allows you yourself to read code easier and vice versa. You might want to take a look at the PHP-FIG PSR one and two standards which helps in creating consistent code.
PHP The Right Way is also a great website that will help you out the most, it provides information about dependency injection and coding practices amongst other things.
Within a single class, I am able to use the _call/_callStatic functions to call a function before any function is actually run. However, I'm yet to find a solution that I can apply to the parent, and it will be inherited by the children.
The only method I can think of is putting a small snippet of code within each class that calls a function in the parent, which contains my code.
Are there any better solutions that I can implement?
As long as you are at least on php 5.4, you could use traits.
http://php.net/traits
This will need some adjustments in your code but could allow the desired behavior.
Do you have some more information on your use case? I think of logging from your description, is this correct?
Unfortunately there are not magic methods in PHP which get run whenever any method is called.
I think the solution you are looking for is a decorator, see this article for the tips on decorating methods / classes in PHP.
how to implement a decorator in PHP?
It's hard to help you without seeing some code. However, assuming that you don't re-define __call/__callStatic in the subclass, it should simply inherit the method from it's superclass.
If you do re-define __call/__callStatic in the subclass, it overrides the superclass' definition. So you'd somehow have to call the superclass' method. In order to do this you can use the parent keyword. See this example:
class SuperClass
{
public function __call($name, $arguments)
{
// Do some stuff
}
}
class SubClass extends SuperClass
{
public function __call($name, $arguments)
{
// Execute the parent's __call() method
return parent::__call($name, $arguments);
// Do some extra stuff here
}
}
I have a parent class, let's say class main { ... }, and an extension of it, let's call it class extension extends main { ... }.
My question is, how would I build another class, called class messages { ... }, which I can use inside the main class and the extended class of main, extension ? Besides the way I know, calling the class messages like this :
$messages = new messages;
$messages->someMethod();
Is there another way without having to do new ... to make the main and extension class inherit the methods inside the messages class ?
AFAIK, PHP does not support multiple inheritance, as others OOP languages do.
So, no, there is NOT another way.
And yes, you should create a property and instantiate the object inside the main class...
class main {
public $messages; // may be "protected" or "private" instead
public __construct()
{
$this->messages = new messages();
}
public do_something()
{
$this->messages->do_something_else();
}
}
However, there are alternatives to simulate a fake multiple inheritance.
An alternative would be: https://stackoverflow.com/a/356431/370290 - But I don't recommend this (even the own author doesn't).
Another alternative: https://stackoverflow.com/a/358562/370290 - IMHO, as weird as the previous one. :-)
And as of PHP 5.4.0 you can also use traits to achieve a "multiple inheritance" effect: http://php.net/manual/en/language.oop5.traits.php - This is very new at the moment.
You can't extend multiple classes and to exten the main class .. only a good thing if you extend from an abstract class.
But what you could do is add it in the construct of your main class like this:
//member variable for class main
public $_message = null;
public function __construct()
{
$this->_message = new Message();
}
Then whenever you need the message class just call $this->_message + the method you need (eg: $this->_message->addMessage())
don't forget to add this in you subclass:
public function __construct()
{
parent::__construct();
}
The problem you seem to have is that you can't do multiple inheritance (class YourClass extends main, messages).
The common feeling is that if you need multiple enheritance, you're doing something wrong in your design.
Every class is responsible for a single thing. A "extension" in this case "IS A" "main", but it is not a "messages", so it should not be a child of that. IF you need messaging capability, there is no 'shame' at all in just calling it like you suggest: you get yourself a nice object that knows how to message, and play with that. There is no real need to do it differently.
If you're looking for alternatives (which you really don't need as far as I can see!) you could make it a class with a bunch of static methods, and just call it like messages::someMethod(), but I think that would be considered an anti-pattern in this case.
Just go with it: messages are created by an object of type message. So you make one, and call the function. In the end, if you ever need big changes (database connection, logging, etc etc) for you messaging, you can do this all in your nice and cosy messaging class. Everyone happy :)
You should create a class inside a class. Just like in this question.
Then, you can use $this->someclass->function.
Note: construct needs to be $this->someclass = new Whatever() too.
Lets say I have a class called PageBuilder which I instantiate, send parameters to and call functions from through my index file (which acts as a front controller). There are three sub classes associated with the PageBuilder class: Head, Body and Foot, that are accessed by PageBuilder which basically abstracts them for index.
So in theory you could instantiate PageBuilder and have full access to the other classes as if they were part of PageBuilder.
How can I implement a design like this in PHP5 using any combination of classes, abstract classes and interfaces?
I don't think the above is possible with PHP5, not necessarily because PHP has its limitations but maybe because I am going about the design of my application the wrong way.
Common examples of OOP in PHP don't suffice to help me understand how to structure a more complex design.
Thanks.
Some of the other answers are on the right track. The problem you're running into is that your PageBuilder class is doing too much. Just the name sounds wrong for what you're trying to do with it. A PageBuilder sounds like something that would assemble a bunch of parts together into a Page. Let's call these parts Section. Then, what you want to do is use composition, as several of the answers have hinted at.
Inheritance is often described as an is-a relationship, as in if your Section classes extend the PageBuilder class, then a Section is a PageBuilder. What you want though is a has-a relation ship, as in your PageBuilder class has a (or many) Section(s). Any time you need a has-a relationship, you should be looking toward composition rather than inheritance.
So here might be your class hierarchy:
abstract class PageBuilder
{
//#var Section
public $header;
//#var Section
public $body;
//#var Section
public $footer;
public function render()
{
echo $this->header.$this->body.$this->footer;
}
}
class Section
{
protected $content;
}
class LoginPage
extends PageBuilder
{
public function __construct()
{
$this->header=new Section(...);
$this->footer=new Section(...);
$this->body=new Section(...);
}
}
At this point, you're really kind of re-inventing the wheel by making a crappy MVC system. If this is for a project (rather than for learning), you should consider using one of the MVC frameworks for PHP. (I recommend Kohana, but there are several questions regarding the best PHP versions on Stack Overflow.) If you're thinking of these kinds of things, MVC probably won't be a great leap for you.
From what I understand here you could use the composite pattern
http://en.wikipedia.org/wiki/Composite_pattern
Your controller index has only access to an object that implements an interface IPageBuilder (or a name similar), with some standards function like "generatePage". This object would in reality be some kind of container that contain other object of type IPageBuilder. Those leafs object would be able to build some subsection of the page, like Head, Body and Foot. Each of those leaf object would be of a different class, but they will implement the IPageBuilder interface. When your index object call "generatePage", the container will call in order the "generatePage" method of each of its leaf objects, that will in turn take care of rendering the HTML.
Using this approach, if your Body class become too big, you can always turn it into a container that implements the IPageBuilder interface, for example a blog post Body could consist of an Article object and a CommentList object. The body object would then only propagate the "generatePage" method to its children object.
To create your IPageBuilder object, you can use a factory patterns
http://en.wikipedia.org/wiki/Factory_method_pattern
In all honesty, I have tried those kind of approach in the past to generate my HTML and found them to be kind of overkill. My suggestion would be to use a templating engine instead, like Smarty. Your designer will love you (or hate you less) if do that ^^.
http://www.smarty.net/
If you want to know how to use interfaces in PHP, not that it's very hard...
http://ca.php.net/manual/en/language.oop5.interfaces.php
So if I understand correctly you want Head, Body, and Foot to automatically construct as children of PageBuilder?
There are a couple of ways you could maybe do this.
1) Create variables inside of PageBuilder to hold the classes and use a __call method
class PageBuilder{
private _head;
private _body;
private _foot;
function __construct(){
$this->_head = new Head();
$this->_foot = new Foot();
$this->_body = new Body();
}
function __call($name, $args){
if(method_exists($this->_head, $name)) call_user_func_array(array($this->head, $name), $args);
// Repeat for other classes.
}
}
The problem here obviously being if two classes share the same method then the first one to come up wins. You could probably modify it to pick a class based on the function name pretty easily.
2) Chain everything down.
Abstract class Page{
}
class Head extends Page{
}
class Body extends Head{
}
class Foot extends Body{
}
class PageBuilder extends Foot{
}
Either way its somewhat hacked, you just kind of have to make it work.
PHP only allows you to extend one parent class (which can in turn extend another parent class, etc.). There are no interfaces, meaning you can't inherit functions or properties from multiple interfaces as you could in C++.
As such, you will probably need to do something more like this:
class PageBuilder {
protected Head, Body, Foot;
public function __construct($request) {
$view = $this->getView($request);
$this->Head = new PageSection('head.tpl');
$this->Body = new PageSection($view);
$this->Foot = new PageSection('foot.tpl');
}
private function getView($request) {
// #todo return the template filename/path based upon the request URL
}
}
class PageSection {
private $template;
public function __construct($template) {
$this->template = $template;
}
public function render() {
// #todo process and output the $this->template file
}
}