How to allow multiple classes through one parent class in PHP

Let's say I have a class called PageBuilder

that I create, send parameters and call functions from my file index

(which acts like a front controller). There are three sub-classes associated with the class PageBuilder

: Head

, Body

and Foot

accessed by PageBuilder

, which abstracts them mainly for index

.

So, in theory, you can instantiate PageBuilder

and have full access to other classes as if they were part of PageBuilder

.

How can I implement such a design in PHP5 using any combination of classes, abstract classes and interfaces?

I don't think this is possible with PHP5, not necessarily because PHP has its limitations, but perhaps because I am misusing my application design.

Generic examples of OOP in PHP aren't enough to help me understand how to structure more complex designs.

Thank.

+2


source to share


4 answers


Some of the other answers are on the right track. The problem you are having is your class is PageBuilder

doing too much. The name just doesn't sound right for what you're trying to do with it. A PageBuilder

sounds like something that will put a bunch of parts together into Page

. Let me name these parts Section

. Then what you want to do is use composition, as several answers have hinted at.

Inheritance is often described as a relationship is-a

, as is the case if your classes Section

extend a class PageBuilder

then Section

is PageBuilder

. What you want but is the ship of the relationship has-a

, as PageBuilder

there are (or many) Section

(s) in your class . Every time you need a relationship has-a

, you should look at composition, not inheritance.

So, here's 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 really love reinventing the wheel by creating crappy MVCs . If this is for a project (not training), then you should consider using one of the PHP MVC frameworks. (I recommend Kohana , but there are a few questions about the best PHP version on Stack Overflow.) If you think about these things, MVC probably won't be a great jump for you.

+4


source


From what I understand here, you can use a composite pattern

http://en.wikipedia.org/wiki/Composite_pattern

Your controller index only has access to an object that implements the IPageBuilder interface (or a similar name), with some standard functionality such as "generatePage". This object would actually be a kind of container that contains another object of type IPageBuilder. This leaf object could create some kind of subsection of the page, such as Head, Body, and Leg. Each of these leaf objects would be of a different class, but they would implement the IPageBuilder interface. When your index object calls generatePage, the container will call the generatePage method on each of its leaf objects, which in turn will take care of the HTML rendering.

Using this approach, if your Body class gets too large, you can always turn it into a container that implements the IPageBuilder interface, for example, a Body blog post can consist of an Article object and a CommentList object. The body object will then propagate the "generatePage" method to its child object.

To create an IPageBuilder object you can use factory templates



http://en.wikipedia.org/wiki/Factory_method_pattern

To be honest, I have tried this approach in the past to generate my HTML and found them to be overkill. My suggestion would be to use a templating engine like Smarty instead. Your designer will love you (or hate you less) if they do ^^.

http://www.smarty.net/

If you want to know how to use interfaces in PHP, it's not too difficult ...

http://ca.php.net/manual/en/language.oop5.interfaces.php

+2


source


So if I understand correctly that you want Head, Body and Foot to be automatically created as children from PageBuilder?

There are several ways you could do this.

1) Create variables inside PageBuilder to hold classes and use __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 is obviously that the two classes use the same method than the first gain. Perhaps you could change it to easily select a class based on the function name.

2) Chain everything down.

Abstract class Page{
}

class Head extends Page{
}

class Body extends Head{
}

class Foot extends Body{
}

class PageBuilder extends Foot{
}

      

It's been somewhat hacked anyway, you just need to get it to work.

0


source


PHP only allows you to extend one parent class (which in turn can extend another parent class, etc.). There are no interfaces, meaning you cannot inherit functions or properties from multiple interfaces like you could in C ++.

As such, you probably need to do more:

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
    }
}

      

-1


source







All Articles