Zend Framework: Controller in Unterverzeichnissen verwalten

Noch etwas spärlich dokumentiert ist die seit dem Release 0.6.0 neue Möglichkeit, im Zend Framework Controller auch in Unterverzeichnissen verwalten zu können. Deshalb schreibe ich hier mal meine Notizen dazu nieder.

Als erstes muss ich dem Controller mitteilen, dass ich Controller als Module verwenden möchte. Außerdem muss ich die Verzeichnisse angeben, in denen sich die Controller befinden. Dies könnte dann in etwa wie folgt aussehen:

PHP:
  1. $controller = Zend_Controller_Front::getInstance();
  2. $controller->setControllerDirectory('/path/to/controller');
  3. $controller->addControllerDirectory('/path/to/controller/test', 'test');
  4. $controller->setParam('useModules', true);

Durch den Aufruf von setControllerDirectory() wird das Default Verzeichnis für die Controller gesetzt. Danach füge ich noch ein weiteres Verzeichnis für das Modul 'test' mit Hilfe von addControllerDirectory() hinzu. Zum Schluss setze ich den Parameter 'useModules' auf den Wert true.

Als nächstes lege ich dann das Unterverzeichnis '/path/to/controller/test' an und lege dort einen einfachen Controller mit dem Dateinamen 'MeinController.php' an:

PHP:
  1. <?php
  2. class Test_MeinController extends Travello_Controller_Action
  3. {
  4.     public function indexAction()
  5.     {
  6.         echo "Test_MeinController::indexAction";
  7.     }
  8.  
  9.     public function showAction()
  10.     {
  11.         echo "Test_MeinController::showAction";
  12.     }
  13.    
  14.     public function __call($methodName, $args)
  15.     {
  16.         echo "Test_MeinController::" . $methodName;
  17.     }
  18. }
  19. ?>

Das war es auch schon, jetzt kann ich das ganze mit folgenden Routen testen:

http://mein.projekt-dev.de/test/mein/
http://mein.projekt-dev.de/test/mein/show/
http://mein.projekt-dev.de/test/mein/wasauchimmer/

Was ich leider noch nicht hinbekommen habe, ist, dass der RewriteRouter automatisch das Modul erkennt und ich nicht jedes Verzeichnis separat über addControllerDirectory() angeben muss. Man kann übrigens an setControllerDirectory() auch ein Array übergeben, so dass man in einem Rutsch alle Controller Verzeichnisse übergeben kann.

12 Antworten für “Zend Framework: Controller in Unterverzeichnissen verwalten”

  1. sas171 sagt:

    Wenn die Controller schon in Unterverzeichnissen liegen, dann kann man die auch einfach MeinController nennen (ohne Prefix). Obwohl ich mir da nicht sicher bin...

  2. Warui sagt:

    Die schmutzige Variante wäre an sich ja, ein kleines Skript davorzuhängen, das das ModulVerzeichnis parst und die Unterverzeichnisse übergibt ... aber schön ist das nicht ^^

  3. Axel sagt:

    Was aber wohl nicht richtig funktioniert ist

    http://mein.projekt-dev.de/test/

    Unter dieser Route wird nach meinen Versuchen nicht indexAction() des Test_IndexController sondern von IndexController aktiviert.

  4. Axel sagt:

    @sas171: Man muss sie Test_... nennen, sonst geht's nicht - man kommt in eine Endlosschleife.

  5. Axel sagt:

    Das Modulverhalten ist etwas merkwürdig. Wie oben gesagt führt http://mein.projekt-dev.de/test/ auf den IndexController. Aber nicht nur .../test (der Modulname), sondern jeder andere Wert auch. Ich würde erwarten, dass ich unter /test die Funktionen des Moduls "Test" erreiche, ohne /test aber alle anderen Funktionen, wie z.B. in Tutorial /article/show usw. und bei /badroute auf die norouteAction.

  6. Warui sagt:

    Und wenn man das mit AddControllerDirectory umdreht? Statt
    $controller->setControllerDirectory('/path/to/controller');
    $controller->addControllerDirectory('/path/to/controller/test', 'test');
    schreibt man das:
    $controller->addControllerDirectory('/path/to/controller/test', 'test');
    $controller->setControllerDirectory('/path/to/controller');

    Ich hab jetzt wenig Lust. extra was aufzusetzen um die Uhrzeit .... :D

  7. Ralf Eggert sagt:

    @Axel

    Und wenn du einen Controller Test_IndexController einrichtest? Funktioniert das dann? Wäre nämlich meiner Meinung nach logisch, weil http://mein.projekt-dev.de/test/ dann wie folgt aufgelöst werden sollte:

    Module => Test
    Controller => Index
    Action => Index

    Wenn es aber keinen Test_IndexController gibt, wird stattdessen wohl der IndexController angesteuert.

    Gruß,

    Ralf

  8. Axel sagt:

    Das habe ich gemacht.

    Ich babe mir mal das Request-Objekt in Dispatcher::_getController() ausgegeben

    wenn ich http://localhost/_sc5_demo/test/ aufrufe:

    Zend_Controller_Request_Http Object
    (
    [_requestUri:protected] => /_sc5_demo/test/
    [_baseUrl:protected] => /_sc5_demo
    [_basePath:protected] =>
    [_pathInfo:protected] => /test/
    [_params:protected] => Array
    (
    [controller] => index
    )

    [_aliases:protected] => Array
    (
    )

    [_dispatched:protected] => 1
    [_controllerKey:protected] => controller
    [_actionKey:protected] => action
    )

    Wenn ich http://localhost/_sc5_demo/test/mein aufrufe:

    Zend_Controller_Request_Http Object
    (
    [_requestUri:protected] => /_sc5_demo/test/mein
    [_baseUrl:protected] => /_sc5_demo
    [_basePath:protected] =>
    [_pathInfo:protected] => /test/mein
    [_params:protected] => Array
    (
    [module] => test
    [controller] => mein
    [action] => index
    )

    [_aliases:protected] => Array
    (
    )

    [_dispatched:protected] => 1
    [_controllerKey:protected] => controller
    [_actionKey:protected] => action
    )

    bei http://localhost/_sc5_demo/article (entspr. Tutorial):

    Zend_Controller_Request_Http Object
    (
    [_requestUri:protected] => /_sc5_demo/article
    [_baseUrl:protected] => /_sc5_demo
    [_basePath:protected] =>
    [_pathInfo:protected] => /article
    [_params:protected] => Array
    (
    [controller] => index
    )

    [_aliases:protected] => Array
    (
    )

    [_dispatched:protected] => 1
    [_controllerKey:protected] => controller
    [_actionKey:protected] => action
    )

    d.h. es wird auch wieder der Index-Controller aufgerufen.

    Das ist der Modul-Test in Http::_getController()

    $module = (string) $request->getParam('module', false);
    if ($module && isset($directories[$module]))

    Was setzt den Paramater 'module' im Request-Objekt? Ich konnte die Stelle bisher noch nicht finden.

    Der Vorschlag von Warui bringt nichts. Dadurch wird lediglich das Modul-Directory nicht gesetzt.

  9. Axel sagt:

    Habe gerade die Version 0.7.0 eingespielt. Leider ist das Verhalten immer noch so.

  10. Stefan Riedel sagt:

    [zitat]Die schmutzige Variante wäre an sich ja, ein kleines Skript davorzuhängen, das das ModulVerzeichnis parst und die Unterverzeichnisse übergibt ... aber schön ist das nicht ^^[/zitat]

    Ne Möglichkeit wär auch alle Module aus der Datenbank zu holen im Actioncontroller schon, denn übergebe ich nur noch ein Array und fertig...^^
    Genauso siehts denn halt auch mit den Views aus, wobei ich die wohl eher seperat in jedem Controller definieren würde, da sich das Skript bei sehr vielen Modulen wohl tot sucht. :P

  11. Wolfi sagt:

    Hallo,

    ich stehe derzeit vor dem gleichen Problem, dass nicht die richtige IndexAction aufgerufen wird. Gibt es da schon eine Lösung wie mans jetzt richtig macht, denn ich würde es SEHR SEHR dringend brauchen!

    Danke im Voraus!

  12. Nikolas Lessmann sagt:

    Mit der aktuellen Version 1.0.1 bin ich zuerst ebenfalls auf dieses Problem gestoßen. Wenn ich ein "nicht default" Modul aufgerufen habe, endete dies in einer Endlosschleife.

    Der Fehler lag allerdings daran, dass ich ein "404 Plugin" verwende, das überprüft, ob es der aufgerufene Controller und die Action existieren. Da bei der Weiterleitung im Plugin zu einer "404 Action" das Modul nicht explizit ausgewählt wurde, suchte das Framework nun nach einer "404 Action" im Controller des Moduls. Da dort aber keiner vorhanden war, führte dies natürlich wieder zu einem "404 Fehler" usw.

    Eventuell handelt es sich bei Ihnen um ein ähnliches Problem?

Hinterlasse eine Antwort