php kohana uri kohana-3 routes

php - Kohana 3.2.-¿Cómo puedo usar guiones en URI?



kohana-3 routes (5)

No hay forma de asignar directamente una cadena con guiones a una función de PHP, por lo que tendrá que hacer el enrutamiento.

En cuanto al contenido generado por el usuario, podrías hacer algo como Stack Exchange. Cada vez que el contenido del usuario se guarda en la base de datos, se genera un slug ( kohana-3-2-how-can-i-use-hyphens-in-uris ) y lo guarda junto con la otra información. Luego, cuando necesites vincularlo, usa la identificación única y agrega la babosa al final (por ejemplo: http://stackoverflow.com/questions/7404646/kohana-3-2-how-can-i-use-hyphens-in-uris ) para la legibilidad.

Recientemente, he estado investigando el SEO y cómo los URI que usan guiones o guiones bajos se tratan de manera diferente, particularmente por Google que ve los guiones como separadores.

De todos modos, deseoso de adaptar mi proyecto actual para cumplir con este criterio, encontré que debido a que Kohana usa nombres de funciones para definir páginas, recibí la inesperada advertencia ''-''.

Me preguntaba si había alguna forma de habilitar el uso de URI en Kohana como:

http://www.mysite.com/controller/function-name

Obviamente, podría configurar un routeHandler para esto ... pero si tuviera contenido generado por el usuario, es decir, noticias. Tendría que obtener todos los artículos de la base de datos, producir el URI y luego hacer el enrutamiento para cada uno.

¿Hay alguna solución alternativa?


Podrías hacer algo como

Route::set(''route'', ''<controller>/<identifier>'', array( ''identifier'' => ''[a-zA-Z/-]*'' )) ->defaults(array( ''controller'' => ''Controller'', ''action'' => ''show'', ));

Luego, reciba su identificador de contenido en la función con Request::current()->param(''identifier'') y analícelo manualmente para encontrar los datos relacionados.


Después de haber probado varias soluciones, descubrí que la manera más fácil y confiable es anular Kohana_Request_Client_Internal::execute_request . Para hacerlo, agregue un archivo en la carpeta de su application en "application / classes / kohana / request / client / internal.php" y luego configure su contenido en:

<?php defined(''SYSPATH'') or die(''No direct script access.''); class Kohana_Request_Client_Internal extends Request_Client { /** * @var array */ protected $_previous_environment; /** * Processes the request, executing the controller action that handles this * request, determined by the [Route]. * * 1. Before the controller action is called, the [Controller::before] method * will be called. * 2. Next the controller action will be called. * 3. After the controller action is called, the [Controller::after] method * will be called. * * By default, the output from the controller is captured and returned, and * no headers are sent. * * $request->execute(); * * @param Request $request * @return Response * @throws Kohana_Exception * @uses [Kohana::$profiling] * @uses [Profiler] * @deprecated passing $params to controller methods deprecated since version 3.1 * will be removed in 3.2 */ public function execute_request(Request $request) { // Create the class prefix $prefix = ''controller_''; // Directory $directory = $request->directory(); // Controller $controller = $request->controller(); if ($directory) { // Add the directory name to the class prefix $prefix .= str_replace(array(''//', ''/''), ''_'', trim($directory, ''/'')).''_''; } if (Kohana::$profiling) { // Set the benchmark name $benchmark = ''"''.$request->uri().''"''; if ($request !== Request::$initial AND Request::$current) { // Add the parent request uri $benchmark .= '' « "''.Request::$current->uri().''"''; } // Start benchmarking $benchmark = Profiler::start(''Requests'', $benchmark); } // Store the currently active request $previous = Request::$current; // Change the current request to this request Request::$current = $request; // Is this the initial request $initial_request = ($request === Request::$initial); try { if ( ! class_exists($prefix.$controller)) { throw new HTTP_Exception_404(''The requested URL :uri was not found on this server.'', array('':uri'' => $request->uri())); } // Load the controller using reflection $class = new ReflectionClass($prefix.$controller); if ($class->isAbstract()) { throw new Kohana_Exception(''Cannot create instances of abstract :controller'', array('':controller'' => $prefix.$controller)); } // Create a new instance of the controller $controller = $class->newInstance($request, $request->response() ? $request->response() : $request->create_response()); $class->getMethod(''before'')->invoke($controller); // Determine the action to use /* ADDED */ if (strpos($request->action(), ''_'') !== false) throw new HTTP_Exception_404(''The requested URL :uri was not found on this server.'', array('':uri'' => $request->uri())); /* MODIFIED */ $action = str_replace(''-'', ''_'', $request->action()); /* ORIGINAL: $action = $request->action(); */ $params = $request->param(); // If the action doesn''t exist, it''s a 404 if ( ! $class->hasMethod(''action_''.$action)) { throw new HTTP_Exception_404(''The requested URL :uri was not found on this server.'', array('':uri'' => $request->uri())); } $method = $class->getMethod(''action_''.$action); $method->invoke($controller); // Execute the "after action" method $class->getMethod(''after'')->invoke($controller); } catch (Exception $e) { // Restore the previous request if ($previous instanceof Request) { Request::$current = $previous; } if (isset($benchmark)) { // Delete the benchmark, it is invalid Profiler::delete($benchmark); } // Re-throw the exception throw $e; } // Restore the previous request Request::$current = $previous; if (isset($benchmark)) { // Stop the benchmark Profiler::stop($benchmark); } // Return the response return $request->response(); } } // End Kohana_Request_Client_Internal

Luego, para agregar una acción con guiones, por ejemplo, "controller / my-action", crea una acción llamada "my_action ()".

Este método también generará un error si el usuario intenta acceder a "controller / my_action" (para evitar el contenido duplicado).

Sé que a algunos desarrolladores no les gusta este método, pero la ventaja es que no cambia el nombre de la acción, por lo que si compruebas la acción actual, siempre se llamará "mi-acción" en todas partes. Con el método de la función Ruta o lambda, la acción alguna vez se llamará "mi_acción", alguna vez "mi-acción" (ya que ambos métodos renombran la acción).



Nota: Este es el mismo enfoque que en la respuesta de Laurent , solo un poco más OOP-wise. Kohana permite sobrecargar fácilmente cualquier clase de sistema, por lo que podemos usarla para ahorrarnos algo de tipeo y también para permitir actualizaciones más limpias en el futuro.

Podemos conectar el flujo de solicitud en Kohana y corregir los guiones en la parte de acción de la URL. Para hacerlo, anularemos la clase del sistema Request_Client_Internal y su método execute_request (). Allí comprobaremos si request-> action tiene guiones, y si es así los cambiaremos a guiones bajos para permitir que php llame a nuestro método correctamente.

Paso 1. Abre tu aplicación / bootstrap.php y agrega esta línea:

define(''URL_WITH_DASHES_ONLY'', TRUE);

Utiliza esta constante para desactivar rápidamente esta característica en algunas solicitudes, si necesita guiones bajos en la url.

Paso 2. Crea un nuevo archivo php en: application / classes / request / client / internal.php y pega este código:

<?php defined(''SYSPATH'') or die(''No direct script access.''); class Request_Client_Internal extends Kohana_Request_Client_Internal { /** * We override this method to allow for dashes in the action part of the url * (See Kohana_Request_Client_Internal::execute_request() for the details) * * @param Request $request * @return Response */ public function execute_request(Request $request) { // Check the setting for dashes (the one set in bootstrap.php) if (defined(''URL_WITH_DASHES_ONLY'') and URL_WITH_DASHES_ONLY == TRUE) { // Block URLs with underscore in the action to avoid duplicated content if (strpos($request->action(), ''_'') !== false) { throw new HTTP_Exception_404(''The requested URL :uri was not found on this server.'', array('':uri'' => $request->uri())); } // Modify action part of the request: transform all dashes to underscores $request->action( strtr($request->action(), ''-'', ''_'') ); } // We are done, let the parent method do the heavy lifting return parent::execute_request($request); } } // end_class Request_Client_Internal

Lo que esto hace es simplemente reemplazar todos los guiones en la acción $ request-> con guiones bajos, por lo tanto, si url was / something / foo-bar , Kohana lo encaminará felizmente a nuestro método action_foo_bar ().

Al mismo tiempo, bloqueamos todas las acciones con guiones bajos, para evitar los problemas de contenido duplicado.