12 Stimmen

Verwendung von URL-Segmenten als Parameter für Aktionsmethoden im Zend Framework

In Kohana/CodeIgniter, kann ich eine URL in dieser Form haben:

http://www.name.tld/controller_name/method_name/parameter_1/parameter_2/parameter_3 ...

Und dann lese ich die Parameter in meinem Controller wie folgt:

class MyController 
{
    public function method_name($param_A, $param_B, $param_C ...)
    {
        // ... code
    }
}

Wie erreicht man dies im Zend Framework?

11voto

Andrew Taylor Punkte 1850

Werfen Sie einen Blick auf die Zend_Controller_Router Klassen:

http://framework.zend.com/manual/en/zend.controller.router.html

Diese erlauben es eine Zend_Controller_Router_Route zu definieren die auf die URL in der Art und Weise abbildet die man benötigt.

Ein Beispiel mit 4 statischen Parametern für die Index-Aktion des Index-Controllers ist:

$router = new Zend_Controller_Router_Rewrite();

$router->addRoute(
    'index',
    new Zend_Controller_Router_Route('index/index/:param1/:param2/:param3/:param4', array('controller' => 'index', 'action' => 'index'))
);

$frontController->setRouter($router);

Dies wird zu Ihrem Bootstrap hinzugefügt, nachdem Sie Ihren Frontcontroller definiert haben.

Sobald Sie die Aktion gestartet haben, können Sie sie nutzen:

$this->_request->getParam('param1');

innerhalb Ihrer Aktionsmethode, um auf die Werte zuzugreifen.

Andrew

6voto

leek Punkte 11253

Update (13.04.2016): Der Link in meiner Antwort unten hat sich verschoben und wurde korrigiert. Aber nur für den Fall, dass er wieder verschwindet - hier sind ein paar Alternativen, die einige ausführliche Informationen über diese Technik bieten, sowie den Originalartikel als Referenzmaterial verwenden:


@ Andrew Taylor Antwort ist der richtige Weg des Zend Frameworks um URL Parameter zu behandeln. Wenn man jedoch die URL Parameter in der Aktion des Controllers haben möchte (wie in Ihrem Beispiel) - sehen Sie sich dieses Tutorial auf Zend DevZone .

4voto

Victor Punkte 710

Ich habe die Zend_Controller_Action mit meiner Controller-Klasse und nahm die folgenden Änderungen vor:

En dispatch($action) Methode ersetzt

$this->$action();

mit

call_user_func_array(array($this,$action), $this->getUrlParametersByPosition());

Und fügte die folgende Methode hinzu

/**
 * Returns array of url parts after controller and action
 */
protected function getUrlParametersByPosition()
{
    $request = $this->getRequest();
    $path = $request->getPathInfo();
    $path = explode('/', trim($path, '/'));
    if(@$path[0]== $request->getControllerName())
    {
        unset($path[0]);
    }
    if(@$path[1] == $request->getActionName())
    {
        unset($path[1]);
    }
    return $path;
}

Jetzt für eine URL wie /mycontroller/myaction/123/321

in meiner Aktion erhalte ich alle Parameter nach Controller und Aktion

public function editAction($param1 = null, $param2 = null)
{
    // $param1 = 123
    // $param2 = 321
}

Zusätzliche Parameter in der URL führen nicht zu einem Fehler, da Sie mehr Parameter an die Methode senden können als definiert. Sie können alle Parameter erhalten durch func_get_args() Und Sie können weiterhin getParam() auf die übliche Weise. Ihre URL darf keinen Aktionsnamen enthalten, wenn Sie den Standardnamen verwenden.

Meine URL enthält eigentlich keine Parameternamen. Nur ihre Werte. (Genau wie es in der Frage stand) Und man muss Routen definieren, um die Positionen der Parameter in der URL zu spezifizieren, um den Konzepten des Frameworks zu folgen und um in der Lage zu sein, URLs mit Zend-Methoden zu erstellen. Aber wenn man immer die Position des Parameters in der URL kennt, kann man ihn leicht wie folgt erhalten.

Das ist nicht so ausgeklügelt wie die Verwendung von Reflexionsmethoden, aber ich schätze, dass es weniger Overhead bedeutet.

Die Dispatch-Methode sieht nun wie folgt aus:

/**
 * Dispatch the requested action
 *
 * @param string $action Method name of action
 * @return void
 */
public function dispatch($action)
{
    // Notify helpers of action preDispatch state
    $this->_helper->notifyPreDispatch();

    $this->preDispatch();
    if ($this->getRequest()->isDispatched()) {
        if (null === $this->_classMethods) {
            $this->_classMethods = get_class_methods($this);
        }

        // preDispatch() didn't change the action, so we can continue
        if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) {
            if ($this->getInvokeArg('useCaseSensitiveActions')) {
                trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"');
            }
            //$this->$action();
            call_user_func_array(array($this,$action), $this->getUrlParametersByPosition()); 
        } else {
            $this->__call($action, array());
        }
        $this->postDispatch();
    }

    // whats actually important here is that this action controller is
    // shutting down, regardless of dispatching; notify the helpers of this
    // state
    $this->_helper->notifyPostDispatch();
}

3voto

Andy Punkte 16773

Eine einfachere Methode, die auch komplexere Konfigurationen zulässt, ist die folgende diese Stelle . Zusammengefasst:

erstellen. application/configs/routes.ini

routes.popular.route = popular/:type/:page/:sortOrder
routes.popular.defaults.controller = popular
routes.popular.defaults.action = index
routes.popular.defaults.type = images
routes.popular.defaults.sortOrder = alltime
routes.popular.defaults.page = 1
routes.popular.reqs.type = \w+
routes.popular.reqs.page = \d+
routes.popular.reqs.sortOrder = \w+

Hinzufügen zu bootstrap.php

// create $frontController if not already initialised
$frontController = Zend_Controller_Front::getInstance(); 

$config = new Zend_Config_Ini(APPLICATION_PATH . ‘/config/routes.ini’);
$router = $frontController->getRouter();
$router->addConfig($config,‘routes’);

1voto

Jeffrey04 Punkte 5738

Ursprünglich hier veröffentlicht http://cslai.coolsilon.com/2009/03/28/extending-zend-framework/

Meine derzeitige Lösung sieht folgendermaßen aus:

abstract class Coolsilon_Controller_Base 
    extends Zend_Controller_Action { 

    public function dispatch($actionName) { 
        $parameters = array(); 

        foreach($this->_parametersMeta($actionName) as $paramMeta) { 
            $parameters = array_merge( 
                $parameters, 
                $this->_parameter($paramMeta, $this->_getAllParams()) 
            ); 
        } 

        call_user_func_array(array(&$this, $actionName), $parameters); 
    } 

    private function _actionReference($className, $actionName) { 
        return new ReflectionMethod( 
            $className, $actionName 
        ); 
    } 

    private function _classReference() { 
        return new ReflectionObject($this); 
    } 

    private function _constructParameter($paramMeta, $parameters) { 
        return array_key_exists($paramMeta->getName(), $parameters) ? 
            array($paramMeta->getName() => $parameters[$paramMeta->getName()]) : 
            array($paramMeta->getName() => $paramMeta->getDefaultValue()); 
    } 

    private function _parameter($paramMeta, $parameters) { 
        return $this->_parameterIsValid($paramMeta, $parameters) ? 
            $this->_constructParameter($paramMeta, $parameters) : 
            $this->_throwParameterNotFoundException($paramMeta, $parameters); 
    } 

    private function _parameterIsValid($paramMeta, $parameters) { 
        return $paramMeta->isOptional() === FALSE 
            && empty($parameters[$paramMeta->getName()]) === FALSE; 
    } 

    private function _parametersMeta($actionName) { 
        return $this->_actionReference( 
                $this->_classReference()->getName(), 
                $actionName 
            ) 
            ->getParameters(); 
    } 

    private function _throwParameterNotFoundException($paramMeta, $parameters) { 
        throw new Exception(”Parameter: {$paramMeta->getName()} Cannot be empty”); 
    } 
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X