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
<?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
<?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 );
}
}
?>
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.
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.
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.
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.
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?
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.
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).
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.
De voorbeeldcode bij het plaatje zegt eigenlijk al veel:
<?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: