[PHP/ZF]Routing met meerdere iteraties in dispatch loop

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik heb een idee waarbij ik graag het Zend Framework wil gebruiken. Daarbij zit ik met een probleempje:

Ik gebruik alleen custom routes. Deze routes gaan naar een bepaalde "page". Deze page is een definitie van een of meerdere modules. Zo kan ik een tweekolommen-pagina aanmaken waarbij twee keer een bepaalde module/controller/actie wordt aangeroepen. Ik zou ook graag definiëren in welke key van de layout deze verschillende aanroepen terecht komen.

Even schematisch een voorbeeld:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<nav>
  <page>
    <name>twocolumn</name>
    <config>
      <element>
        <module>default</module>
        <controller>index</controller>
        <action>index</action>
        <key>left</key>
      </element>
      <element>
        <module>default</module>
        <controller>index</controller>
        <action>index</action>
        <key>right</key>
      </element>
    </config>
  </page>
  <!-- hier meer pagina's -->
</nav>
Dan heb ik in (bijvoorbeeld) een database alle pagina's van de website staan. Deze entries van de database bevatten de url en een verwijzing naar het type pagina (dus bijv. twocolumn). Ik heb dan een bijbehorende layout waar dan dit mogelijk is:
HTML:
1
2
3
4
<!-- layout gedeelte -->
<div id="left"><?= $this->layout()->left ?></div>
<div id="right"><?= $this->layout()->right ?></div>
<!-- meer layout -->



Ik heb onderdelen van de documentatie gelezen zoals named segments van het response object en configuratie opties van Zend_Layout (bijvoorbeeld met de contentKey() setter).

Toch kom ik nu er _niet_ uit. Ik heb gewoonweg geen idee hoe ik hiermee kan starten. Er staat nog weinig code op papier, omdat ik liever eerst wil weten wat ik moet doen, dan het 100 keer proberen. Het komt kortweg op 2 punten neer:
  • In de dispatch loop meerdere acties aanroepen
  • Deze verschillende uitkomsten in verschillende keys van de layout stopppen.
Ik _gok_ dat er een mogelijkheid zit in een postDispatch plugin. Deze zal na de eerste dispatch iteratie een method op het request object aanroepen. De request zal zijn module/controller/action wijzigen naar het volgende element in de page. Door de reset wordt een nieuwe iteratie van de dispatch uitgevoerd. Ergens moet tussendoor dan ook nog even contentKey van de Zend_Layout worden aangeroepen.
Maar dit lijkt me nogal omslachtig. Moet het zo, of zijn er andere mogelijkheden?

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Ik snap niet helemaal wat je bedoelt, maar komt het ongeveer hier op neer: je hebt een layout met 2 div-jes, links en rechts, en elke div moet gevuld worden met het resultaat van een bepaalde action?

Dat kan gewoon met een Action View Helper. Dan doe je het volgende in je view:

PHP:
1
2
3
4
5
6
7
8
9
10
<!-- layout gedeelte --> 
<div id="left"><?php echo $this->action('action',
                                        'controller',
                                        'module',
                                        array('key' => 'left')); ?></div> 
<div id="right"><?php echo $this->action('otheraction',
                                         'othercontroller',
                                         'othermodule',
                                         array('key' => 'right')); ?></div> 
<!-- meer layout -->


Of is dat niet wat je bedoelt?

Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Nou, op zich heb je daar wel gelijk in. Het punt is dat ik geen mogelijkheden zie in de layout te vertellen welke acties uitgevoerd moeten worden.
Als ik in het xml bestand 10 soorten pagina's definieer. Een aantal daarvan hebben een specifieke layout template, het gros kan echter gepompt worden in de "content" key van de standaard layout. In de database staan 100 pagina's. Deze entries in de database wijzen dus naar een pagina en geven wat extra parameters mee.

Misschien is het handig om nog een voorbeeldje te geven:
XML:
1
2
3
4
5
6
7
8
9
10
11
<page>
  <name>standard</name>
  <config>
    <element>
      <module>default</module>
      <controller>index</controller>
      <action>index</action>
      <required>id</required>
    <element>
  </config>
</page>
Dan heb ik in de database een menu entry staan. Ergens op een op een punt in de boom van mijn menu staat een pagina gedefinieerd (zeg mijnsite.nl/about/vision) . Deze pagina is "standard" (verwijst dus naar de standard page in de xml). Ook is in de db een id = 9 gedefinieerd.
Als ik de pagina mijnsite.nl/about/vision opvraag, krijgt de default module met de index controller en index action de opdracht om "iets" terug te geven met een id van 9. Deze staat dan in de content key van de standaard layout (het is niet gedefinieerd in de xml page, dus hij pakt standaard key -content- en de standaard layout).

Ik hoop dat het nu iets duidelijker is :) Ik zag mogelijkheden in de bootstrap die het menu ophaalt en deze in een config plaatst en als paden aangeeft in de router. En dan gaat de router die meerdere elementen van een pagina intern opslaan. Dan moet ik dus nog in de dispatcher alle onderdelen van die pagina loopen.

De layout heeft dus geen idee welke blokken met welke parameters worden opgevraagd. Ik zou wel action helpers kunnen gebruiken wanneer ik een meer statische vorm in ogen had. Maar deze toepassing (eigenlijk gewoon een cms) is veel breder.
Misschien dat ik gewoon wat ga klooien met postDispatch() en contentKey(). Het is voor mij allemaal wat nieuw en ik heb nog nooit met Zend gewerkt. Als ik gewoon wél ga klooien krijg ik het misschien wel voor elkaar (al heb ik liever een goed uitgedacht systeem dan een in elkaar geprutst systeem) :p

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Dan maak je een Zend_Layout met ongeveer het volgende:

PHP:
1
2
3
<!-- begin van de layout -->
<?php echo $this->content; ?>
<!-- einde van de layout -->


Vervolgens maak je een controller aan met actions als standardAction() en twocolumnAction():

PHP:
1
2
3
4
5
6
7
8
9
10
class indexController extends ...
{
  public function standardAction() {
    $this->view->element = $db::fetchRow('id = '. (int)$this->_request->getParam('id')); 
  }

  public function twocolumnAction() {
    $this->view->elements = $xml::getElementsOfMenuItem(); // zoiets?
  }
}


Met ieder hun eigen view:

PHP:
1
2
<!-- standard -->
<?php echo $this->element->content; ?>


PHP:
1
2
3
4
5
6
7
8
9
<!-- twocolumn -->
<div id="left"><?php echo $this->action('standard', 
                                        'controller', 
                                        'module', 
                                        array('key' => 'left', 'element' => $this->elements[0]->id)); ?></div>  
<div id="right"><?php echo $this->action('standard', 
                                         'controller', 
                                         'module', 
                                         array('key' => 'right', 'element' => $this->elements[1]->id)); ?></div>


Dus afhankelijk van wat je page is (standard of twocolumn) kies je de juiste action. De standardAction() gooit gewoon de inhoud van je pagina naar de layout toe en de twocolumnAction() doet dat ook, maar roept in z'n view nog tweemaal de standardAction() aan om de content van beide elementen te renderen.

Je router bepaalt dan welke action er aangeroepen wordt op basis van het gekozen menu-item en geeft de juiste parameters mee.

Dit is maar een ideetje, zo uit het hoofd opgeschreven, dus misschien is het wel onhandig of kan het niet, maar misschien heb je er wat aan. Het kan vast nog verbeterd worden :P.

Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
Mm, hier zit wel iets van potentieel in :)

De enige twee zaken waar ik met jouw methode zit is het volgende:
[list=1]
• Graag wil ik voor optimale deployment niet in de modules klooien. Mocht er nu ineens een klant zijn die drie kolommen wil, moet ik in de module een extra methode toevoegen, een extra view maken etc. Dat behoeft ook specifieke php/zf kennis. Het liefste zou ik de definities slechts in een xml format houden, zodat iedere werknemer het cms kan configureren naar wens, zonder iets van php te kennen (alleen het echo'en van wat variabelen in de layout template).
• De views met meerdere acties behoren tot een enkele module. Wat nu als ik een contactpagina wil met een inleidend tekstje (default/index/index), een contactformulier (contact/form/index) en een kaartje van Google Maps (map/google/index). Dan heb ik dus drie acties van drie verschillende modules. Dat lijkt me lastig in te passen wanneer ik het in een view stop van een enkele module.
Ik ga met die idee nog wel even verder kijken. Sowieso wel bedankt voor je hulp voor :D Ik ben alleen volgens mij wel goed in het verzinnen van complexe modulaire én generieke configuraties :p

Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Punt 1 gaat je sowieso niet lukken, of wil je dat als iemand "threecolumn" invoert in de XML je systeem automatisch snapt dat het driekoloms moet zijn? Als iemand een andere pagina-opmaak wil zal er toch een andere view voor gemaakt moeten worden. Dus je zit sowieso vast aan bepaalde stramienen, want voor een driekoloms lay-out heb je toch echt andere HTML en CSS nodig dan voor een tweekoloms.

Voor punt 2 kun je nog steeds die Action View Helper gebruiken, want daar kun je gewoon module/controller/action specificeren. Het maakt dan niet uit van welke module of controller bepaalde actions zijn, dan werkt gewoon. Vanuit module A kun je best acties in module B aanroepen.
Pagina: 1