Template en Controller

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Tom Swinkels

Tom Swinkels

20/09/2013 00:21:52
Quote Anchor link
Beste Programmeurs,

In mijn ander topic heb ik het gehad over een registry, er werd mij verteld geen registry te gaan gebruiken.

Moet ik vanuit mijn Controllers elke keer alle object opnieuw maken? Er zijn bijvoorbeeld een aantal objecten die ik in alle controllers nodig heb, denk aan het Template object.

Verder kom ik er niet helemaal uit hoe ik dan de data naar de template stuur e.t.c.

Ik zie dat er een aantal mensen een array aanmaken, maar hoe gaat het dan met de objecten?

Een voorbeeld hoe ik het nu doe:

ArticleController
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class ArticleController
{
    private $_template;
    
    function
__construct()
    {

        $this->_template = new Template();
    }

    
    public function index()
    {

        $this->_template->setVars( 'test', 'DIT IS EEN TEST' );
        $this->_template->setVars( 'tekst', 'Dit is tekst, leuk he!' );
        $this->_template->show( 'article' );
    }
}

?>


Template
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
class Template
{
    private $_vars;
    
    function
__construct()
    {

        $this->_vars = array();
    }


    public function setVars( $name, $value )
    {

        $this->_vars[$name] = $value;
    }

    function
show( $name )
    {

    $path = dirname(__FILE__) . '/../../../test.112pers.nl/public_html/view/' . $name . '.view.tpl';
    if ( file_exists( $path ) == false )
    {

            throw new Exception( 'Template not found in '. $path );
            return false;
    }


    // Load variables
        if( $this->_vars )
        {

            foreach ( $this->_vars as $key => $value )
            {

                $$key = $value;
            }
        }

    include ( $path );
    }
}

?>
 
PHP hulp

PHP hulp

19/04/2024 22:55:35
 
Ward van der Put
Moderator

Ward van der Put

20/09/2013 08:52:58
Quote Anchor link
Tom Swinkels op 20/09/2013 00:21:52:
Er zijn bijvoorbeeld een aantal objecten die ik in alle controllers nodig heb, denk aan het Template object.

Waarom kies je hiervoor? Elke controller een eigen template geven lijkt mij namelijk een tamelijk inflexibele keuze. En elke controller hetzelfde template meegeven is nog vele malen erger.

Kijk bijvoorbeeld eens naar het onderstaande MVC-pattern. Jij bent nu in de weer met relatie 3, maar je vergeet de relaties 1 en 2. Je hebt nu een ArticleController waar niets inkomt uit 1 (input van buiten) en niets inkomt uit 2 (het model). De controller heeft daardoor nu niets via 3 door te geven aan de view; dáárom zit je nu met deze vraag.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   +------------------------------------+
   |                                    |
   |   +------------+       +-------+   |
--(1)->| Controller |<-(2)->| Model |   |
   |   +------------+       +-------+   |
   |         |                          |
   |        (3)                         |
   |         |                          |
   |         ?                          |
   |      +------+                      |
   |      | View |                      |
   |      +------+                      |
   |         |                          |
   +--------(4)-------------------------+
             |
             ?
Gewijzigd op 20/09/2013 08:56:03 door Ward van der Put
 
Reshad F

Reshad F

20/09/2013 08:56:44
Quote Anchor link
Even iets anders is die include in je template class niet een beetje dirty manier van programmeren?
 
Tom Swinkels

Tom Swinkels

20/09/2013 12:42:52
Quote Anchor link
De bedoeling is dat het systeem werkt op basis van het HMVC-pattern.

Ik snap de bedoeling nog niet helemaal.

De Controller krijgt een Model terug en het Model wordt naar de view gestuurd?
Ik dacht dat ik voor simpele tekst teksten dit direct in de controller kon doen, maar dat is natuurlijk tegen het principe in.

Uiteindelijk heb ik toch nog een Model object dat ik uiteindelijk wil ophalen in mijn view?

Hoe denken jullie verder over het registry, zijn jullie ook van mening om het niet te gebruiken, en waarom?

@Reshad: Dit komt af van een voorbeeld waar ik heb gekeken, dit kan later ook anders meer eerst het ander probleem.
Gewijzigd op 20/09/2013 12:59:05 door Tom Swinkels
 
Ward van der Put
Moderator

Ward van der Put

20/09/2013 13:53:45
Quote Anchor link
Laten we even aannemen dat je ArticleController een tekstartikel afhandelt. Dan krijg je sterk vereenvoudigd dit:

1. De controller ontvangt van de client (via 1) een HTTP-verzoek om een artikel.

2. De controller controleert de geldigheid van het verzoek. De ArticleController zal veelal de unieke ID van een artikel nodig hebben om iets te kunnen doen.

3. De ArticleController vraagt het gevraagde artikel (via 2) op uit het (data)model. Dat kan een databasetabel met alle artikelen zijn.

4. De ArticleController ontvangt het artikel (terug via 2) van het model en verwerkt de data.

5. De ArticleController geeft de verwerkte data (via 3) door aan de view.

6. De view genereert daarmee output voor de client (voor 4). Dat zal meestal HTML zijn.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   +------------------------------------+
   |                                    |
   |   +------------+       +-------+   |
--(1)->| Controller |<-(2)->| Model |   |
   |   +------------+       +-------+   |
   |         |                          |
   |        (3)                         |
   |         |                          |
   |         ?                          |
   |      +------+                      |
   |      | View |                      |
   |      +------+                      |
   |         |                          |
   +--------(4)-------------------------+
             |
             ?


Bij HMVC bouw je een webpagina op met meerdere views/objecten. Je hebt nu een artikel in HTML, maar de webpagina bevat bijvoorbeeld ook nog reacties op dat artikel, een navigatiebalk, een zoekvak, een paar banners, een footer, enzovoort. Een deel daarvan heeft een eigen controller, vooral wanneer een object niet statisch maar dynamisch is, bijvoorbeeld het zoeksysteem en het bannermanagement.

Op elke lijn in het bovenstaande MVC-model kun je nog een uitbreiding toevoegen. Bij 1 voor de input van de client bijvoorbeeld een front controller (of dispatcher) die de juiste controller aanroept. Een verzoek om een artikel moet bijvoorbeeld naar je ArticleController, maar een zoekopdracht naar een SearchController. De controller laten we via 2 meestal niet direct met een database communiceren maar indirect via een data mapper.
Gewijzigd op 20/09/2013 14:33:23 door Ward van der Put
 
Tom Swinkels

Tom Swinkels

23/09/2013 10:27:36
Quote Anchor link
Laten we even beginnen met een makkelijke pagina, het artikel overzicht.

Via de FrontController vraag ik aan de Router de juiste Route die vervolgens de juiste Controller en Action aan de FrontController terug geeft. In de FrontController roep ik dus de nieuwe Controller aan.

ArticleController: In ArticleController haal ik de data op via mapper, in dit geval gaat het zoals ik het noem een Note. Via de NoteMapper krijg ik dus het Note object terug. Verder heb ik een StateMapper en UserMapper nodig om de ids te koppelen.

Vervolgens moet ik dat Note object + alle andere objecten die ik nodig heb meegeven aan het ArticleModel.

Is bovenstaande zoals het zou moeten?

Hoe krijg ik verder, het Model en eventueel andere object denk aan Request object in mijn view? Moet ik die objecten ook allemaal aanmaken en meegeven in het Model?

Verder zeg je dat een deel van views een eigen controller kan hebben? Maar ik mag toch maar één controller gebruiken?
 
Ward van der Put
Moderator

Ward van der Put

23/09/2013 10:36:05
Quote Anchor link
Je combineert één MVC-eenheid tot één module. Maar je HMVC-webpagina bouw je vervolgens op uit meerdere van die modules. Een "view" is dus niet één webpagina, maar een webpagina bouw je op uit meerdere views.

Afbeelding
 
Tom Swinkels

Tom Swinkels

23/09/2013 10:59:49
Quote Anchor link
Dit plaatje ziet er precies uit zoals ik het ook zou willen.

Alleen hoe roep ik de meerdere controllers dan aan?

Klopt mijn gedachten over het model wel?
 
Ward van der Put
Moderator

Ward van der Put

23/09/2013 11:31:07
Quote Anchor link
Je hebt ergens een kernel of dispatcher nodig die de juiste modules aan het werk zet via hun controller. Dat kan, bijvoorbeeld, een template voor een complete webpagina zijn met daarin includes van de PHP-modules.

(Bijvoorbeeld Zen Cart werkt zo, met allerlei sideboxes die elk andere content tonen: navigatiemenu's, best verkochte producten, nieuwe aanwinsten, de gevoerde merken, een advertentie, enzovoort. Elke sidebox bestaat uit verschillende PHP-bestanden. De configuratie in de database regelt welke sideboxes zijn ingeschakeld en waar ze op de webpagina staan.)

Een deel van de aanroepen is een "nested dispatch", zo ontstaat die H van hiërarchie in het HMVC-pattern. Het plaatje toont bijvoorbeeld bij 1 een event en daaronder bij 2 de reviews van die event. Dat is vergelijkbaar met een artikel/blogpost en de reacties van lezers daarop. Hier kan de dispatcher bijvoorbeeld een true/false voor succes van de controller van 1 doorgeven aan de controller van 2.

In sommige gevallen kun je rechtstreeks een view laden zonder een controller. Denk bijvoorbeeld aan een footer met een copyrightvermelding. Of aan een div'je met de bedrijfs- en contactgegevens. Dit kunnen views (V) zijn die niet dynamisch veranderen via variabelen in een controller (C) of die niet afhankelijk zijn van data uit het datamodel (M).
 
Tom Swinkels

Tom Swinkels

27/09/2013 23:49:21
Quote Anchor link
Het klinkt inderdaad allemaal heel leuk. Heb ook nog wat op internet lopen zoeken, maar kan verder geen goede voorbeelden vinden.

Het probleem is dat ik hier nu tegen aanloop en nu niet verder kom met mijn applicatie.

En op de manier zoals jij het beschrijft roept mijn router dan geen controller meer aan? Of de router roept een controller aan, en in die controller worden de andere controllers dan weer verwerkt?

Ik loop nu een beetje vast waar ik moet gaan beginnen en wat ik nu wel en niet goed doe.
 
Ward van der Put
Moderator

Ward van der Put

28/09/2013 07:59:52
Quote Anchor link
De voorbeeldcode bij het plaatje zegt eigenlijk al veel:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
# 2. Event Reviews (nested dispatch)
# dispatch is a raw, direct internal request. No modifications are made.

echo $kernel->dispatch('Reviews', 'listForType', array('event', $event->id));

# 3. Map (nested view partial)
# Returns new view template object; echo converts it to string and renders it

echo $view->partial('_map', array('venue' => $event->venue));

# 4. Event Recommentations (nested dispatchRequest)
# dispatchRequest re-uses current Request object just like direct web request
# Will resolve this as 'indexAction($request)'

echo $kernel->dispatchRequest('Events_Recommended', 'index');

# 5. Food Nearby (nested dispatchRequest w/params)
# Will resolve this as 'indexAction($request, $lat, $lon)'

echo $kernel->dispatchRequest('Restaurants_Nearby', 'index', array($event->lat, $event->lon));
?>

Je zit hier dat de $kernel fungeert als dispatcher, zeg maar een telefoniste die verzoeken doorsluist naar de juiste MVC-module. De dispatch doet dat min of meer zo:

dispatch ( $module , $opdracht , $data )
 
Tom Swinkels

Tom Swinkels

12/12/2013 23:11:08
Quote Anchor link
@Ward;

Ik had dit gedeelte even neergelegd omdat ik er niet helemaal meer uitkwam.
Toch wil ik het weer gaan oppakken zodat ik verder kan met mijn website :)

Laten we eventjes beginnen met de stappen:

/artikel/

- ArticleController
- HeaderController
- NavigationController
- FooterView

Dit heb ik nodig wanneer ik /artikel/ opvraag.

Nu is de vraag waar handig ik dit af? Bijvoorbeeld het verhaal van de dispatch?
 
Ward van der Put
Moderator

Ward van der Put

13/12/2013 07:27:07
Quote Anchor link
Ik zou minstens twee onderdelen toevoegen: een front controller of router die bepaalt wat er moet gebeuren (bijvoorbeeld een webpagina tonen) en een template engine die de complete webpagina opbouwt. Je hebt immers nog een view nodig waarin de header bovenaan en de footer onderaan komt, niet ergens anders.

Als je alle URL's herschrijft naar www·example·com/index.php, dan regelt dit PHP-bestand de routing. Dit wordt dan de dispatcher die bepaalt wat er bij een bepaalde URL moet worden gedaan door andere controllers.
 
Tom Swinkels

Tom Swinkels

13/12/2013 17:54:09
Quote Anchor link
@Ward;

Wat ik nu doe zal ik even proberen uit te leggen.

Alles wordt door gestuurd naar index.php.

Index.php
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?
            $frontController
= new FrontController();
            $frontController->execute( $request );
?>


De FrontController haalt vervolgens de Router op die geeft de juiste Route terug.
En vervolgens aan de hand van die Route de juiste Controller en Action.

Waar zou ik nu de afhandeling van de dispatcher moeten doen, en wat doet die dan precies?
 
Ward van der Put
Moderator

Ward van der Put

14/12/2013 07:41:43
Quote Anchor link
Tom Swinkels op 13/12/2013 17:54:09:
De FrontController haalt vervolgens de Router op die geeft de juiste Route terug.
En vervolgens aan de hand van die Route de juiste Controller en Action.

Waar zou ik nu de afhandeling van de dispatcher moeten doen, en wat doet die dan precies?
De dispatch heb je dan al: aan de hand van de gevonden route de juiste controller een bepaalde actie laten uitvoeren.
 
Tom Swinkels

Tom Swinkels

14/12/2013 15:04:36
Quote Anchor link
Precies, dit doet dus mijn frontController.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?
    public function execute( $request )
    {

        $router = $this->getRouter();
        
        $route = $router->getRoute( $request->server( 'REDIRECT_URL' ) );
        if( $route )
        {

            $data = $route->getData();
            
            $controllerName = ucfirst( $data['controller'] ) . 'Controller';
            if( class_exists( $controllerName ) )
            {

                $controller = new $controllerName( $route );
                if( in_array( $data['action'], get_class_methods( $controllerName ) ) )
                {

                    $controller->$data['action']();
                    return true;
                }
            }
        }
    }

?>


Maar nu kom ik terug bij het voorbeeld dat je gaf.

"Bij HMVC bouw je een webpagina op met meerdere views/objecten. Je hebt nu een artikel in HTML, maar de webpagina bevat bijvoorbeeld ook nog reacties op dat artikel, een navigatiebalk, een zoekvak, een paar banners, een footer, enzovoort. Een deel daarvan heeft een eigen controller, vooral wanneer een object niet statisch maar dynamisch is, bijvoorbeeld het zoeksysteem en het bannermanagement."

Wat ik nu moet doen is dus in de juiste controller, in dit voorbeeld ArticleController de juiste models en views bij elkaar zoeken die ik nodig heb om de webpagina op de bouwen. (artikelen zelf, header, navigatie en footer)

Of denk ik nu al verkeerd?
 
Ward van der Put
Moderator

Ward van der Put

14/12/2013 15:12:49
Quote Anchor link
Dat is prima, alleen heb je waarschijnlijk verschillende soorten pagina's. Je moet op dit punt dus beslissen wat de ArticleController eigenlijk doet: een artikel tonen of ruimer een webpagina?
 
Tom Swinkels

Tom Swinkels

14/12/2013 15:14:42
Quote Anchor link
Ik zou zeggen dat een ArticleController eigenlijk alleen een artikel toont... (daarom heet hij ook ArticleController).

Zou je er dan voor kiezen om een tussen controller te maken? ArticlePageController die dan de juiste controllers en views oproept?
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.