2012-08-08 10 views
6

Yii-jedis!Cómo utilizar beforeAction en problemas con Yii o slug

Estoy trabajando en un viejo proyecto Yii y debo agregar algunas características. Yii es un marco bastante lógico pero tiene algunas cosas que no pude entender. Quizás todavía no lo haya entendido. Así que describiré mi problema paso a paso. Para impacientes: pregunta brevemente al final.

Introducción: Quiero agregar URL legibles por humanos a mi proyecto. Ahora URL será similar a: www.site.com/article/359
Y quiero que se vean así: www.site.com/article/how-to-make-pretty-urls~~V~~3rd
muy importante: los artículos antiguos deben estar disponibles en las URL de formato antiguo y las nuevas URL nuevas.

Paso 1: En primer lugar, he actualizado las reglas de reescritura en config/main.php:

'<controller:\w+>/<id:\S+>' => '<controller>/view', 

Y he añadido nueva columna texturl a la mesa artículo. Así que almacenaremos aquí human-legible-part-of-url para nuevos artículos. Luego, he actualizado un artículo con texturl para las pruebas.

Paso 2: Aplicación muestran artículos en ActionView de ArticleController así que no he añadido el código para preproccessing parámetro ID:

if (is_numeric($id)) { 
    // User try to get /article/359 
    $model = $this->loadModel($id); // Article::model()->findByPk($id); 
    if ($model->text_url !== null) { 
     // If article with ID=359 have text url -> redirect to /article/text-url 
     $this->redirect(array('view', 'id' => $model->text_url), true, 301); 
    } 
} else { 
    // User try to get /article/text-url 
    $model = Article::model()->findByAttributes(array('text_url' => $id)); 
    $id = ($model !== null) ? $model->id : null ; 
} 

y luego comenzar código heredado:

$model = $this->loadModel($id); // Load article by numeric ID 
// etc 

Es funciona perfectamente! Pero ...

Paso 3: ¡Pero tenemos muchas acciones con el parámetro ID! ¿Que tenemos que hacer? ¿Actualizar todas las acciones con ese código? Creo que es feo. He encontrado el método CController::beforeAction. ¡Se ve bien! Así Declaro beforeAction y lugar preproccessing ID no:

protected function beforeAction($action) { 
    $actionToRun = $action->getId(); 
    $id = Yii::app()->getRequest()->getQuery('id'); 
    if (is_numeric($id)) { 
     $model = $this->loadModel($id); 
     if ($model->text_url !== null) { 
      $this->redirect(array('view', 'id' => $model->text_url), true, 301); 
     } 
    } else { 
     $model = Article::model()->findByAttributes(array('text_url' => $id)); 
     $id = ($model !== null) ? $model->id : null ; 
    } 
    return parent::beforeAction($action->runWithParams(array('id' => $id))); 
} 

Sí, funciona con ambas URL-formatos, pero se ejecuta ActionViewdos veces y muestra la página dos veces! ¿Qué puedo hacer con esto? Estoy totalmente confundido. ¿He elegido una forma correcta de resolver mi problema?

En pocas palabras: ¿Puedo proceder al ID (parámetro GET) antes de ejecutar cualquier acción y luego ejecutar la acción solicitada (una vez) con el parámetro de ID modificado solamente?

+0

puede intentar con el parámetro en blanco .. return parent :: beforeAction(); ¿Qué es salida? – VibhaJ

+0

@VibhaJ parent :: beforeAction() devuelve 404 y parent :: beforeAction ($ action) devuelve 404 –

+0

actualizó mi código ... Comprueba ahora – VibhaJ

Respuesta

12

última línea debe ser:

return parent::beforeAction($action); 

también a pedir que no tuve su paso: 3.

Como dijiste, tienes muchos controladores y no necesitas escribir código en cada archivo, entonces estás usando beforeAction: pero solo tienes text_url relacionado con el artículo para todos los controladores ??

$ model = Artículo :: modelo() -> findByAttributes (array ('text_url' => $ id));

===== ====== actualizan respuesta

He cambiado esta función, compruebe ahora.

Si $ id no es numérico, entonces encontraremos que está usando el modelo y configuraremos $ _GET ['id'], por lo que en el controlador adicional usará esa identificación numérica.

protected function beforeAction($action) {   
     $id = Yii::app()->getRequest()->getQuery('id'); 
     if(!is_numeric($id)) // $id = how-to-make-pretty-urls 
     { 
      $model = Article::model()->findByAttributes(array('text_url' => $id)); 
      $_GET['id'] = $model->id ; 
     } 
     return parent::beforeAction($action); 
    } 
+0

No. Tengo MUCHAS acciones con el parámetro $ id en UN controlador (_ArticleController_). Ahora, estas acciones obtienen una identificación numérica como parámetro ... Todo lo que necesito es preprocesar esta identificación (de GET) y luego ejecutar la acción con ella. –

+0

¿ha verificado la respuesta actualizada y la funciónAcción previa que he agregado arriba? – VibhaJ

+0

¡El código de acciones antiguas debe ejecutarse con el parámetro $ id numérico! Entonces primero debemos 'convertir' $ id del formato slug a numérico (_load model by slug y return id_). Si usamos: 'return parent :: beforeAction ($ action);' action se ejecutará con el parámetro $ id sin cambios. –

2

Lo sentimos, no he leído todo con cuidado, pero ¿ha considerado el uso de this extension?

+0

Si lo vi antes, tal vez lo hubiera elegido para mi tarea :) –

+0

nunca es demasiado tarde. Sé que el autor de la extensión debe "comprarla" ;-) –

Cuestiones relacionadas