Utilice segmentos de URL como parámetros de métodos de acción en Zend Framework
-
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?
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:
- Acciones del controlador de Zend Framework con parámetros de función
- ¿Zend_Controller acciones que aceptan parámetros?
@ 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”);
}
}