Utilice segmentos de URL como parámetros de métodos de acción en Zend Framework

StackOverflow https://stackoverflow.com/questions/161443

  •  03-07-2019
  •  | 
  •  

Pregunta

En Kohana / CodeIgniter, puedo tener una URL en este formulario:

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

Y luego lea los parámetros en mi controlador de la siguiente manera:

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

¿Cómo logras esto en Zend Framework?

¿Fue útil?

Solución

Actualización (13/04/2016): El enlace en mi respuesta a continuación se movió y se ha corregido. Sin embargo, en caso de que vuelva a desaparecer, aquí hay algunas alternativas que brindan información detallada sobre esta técnica, además de utilizar el artículo original como material de referencia:


@ Andrew Taylor 's La respuesta es la forma correcta de Zend Framework de manejar los parámetros de URL. Sin embargo, si desea tener los parámetros de URL en la acción de su controlador (como en su ejemplo), consulte este tutorial en Zend DevZone .

Otros consejos

Eche un vistazo a las clases de Zend_Controller_Router:

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

Esto te permitirá definir un Zend_Controller_Router_Route que se asigna a tu URL de la forma que necesitas.

Un ejemplo de tener 4 parámetros estáticos para la acción de índice del controlador de índice es:

$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);

Esto se agrega a su programa de arranque una vez que haya definido su controlador frontal.

Una vez en tu acción, puedes usar:

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

Dentro de su método de acción para acceder a los valores.

Andrew

He ampliado Zend_Controller_Action con mi clase de controlador y he realizado los siguientes cambios:

En el método dispatch ($ action) reemplazado

$this->$action();

con

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

Y agregó el siguiente método

/**
 * 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;
}

Ahora para una URL como /mycontroller/myaction/123/321

en mi acción obtendré todos los parámetros que siguen al controlador y la acción

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

Los parámetros adicionales en la URL no causarán ningún error, ya que puede enviar más parámetros al método definido. Puede obtenerlos todos a través de func_get_args () Y todavía puedes usar getParam () de la forma habitual. Su URL no puede contener el nombre de la acción usando uno predeterminado.

En realidad mi URL no contiene nombres de parámetros. Sólo sus valores. (Exactamente como estaba en la pregunta) Y tiene que definir rutas para especificar las posiciones de los parámetros en la URL para seguir los conceptos del marco y poder construir URL utilizando los métodos de Zend. Pero si siempre conoce la posición de su parámetro en la URL, puede obtenerlo fácilmente de esta manera.

Eso no es tan sofisticado como usar métodos de reflexión, pero supongo que ofrece menos sobrecarga.

El método de envío ahora se ve así:

/**
 * 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();
}    

Para un método más simple que permita configuraciones más complejas, intente esta publicación . En resumen:

Crear 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+

Agregar a 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’);

Publicado originalmente aquí http://cslai.coolsilon.com / 2009/03/28 / extended-zend-framework /

Mi solución actual es la siguiente:

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”); 
    } 
} 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top