2010-03-18 17 views
11

Estoy tratando de tomar los resultados de una vista - usando la función views_get_view_result() - y ordenar la matriz de una manera que no pude hacer desde la interfaz de Vistas. Hasta aquí todo bien. Tengo una variable $ rows con todas las cosas que necesito.¿Cómo ordenar los resultados de View programmatically?

Ahora ... ¿Cómo lo devuelvo? :) Antes de necesitar este tipo, usé views_embed_view(), pero ya no puedo hacer eso.

Agradecido por cualquier ayuda en esto, parece que estoy tan cerca de descifrarlo!

$important_var = important_function(); 
$result = views_get_view_result($view, $display, $args); 
$result = sorting_function($result, $important_var); 

//TODO: Put the result back into the view 
+0

¿Puede editar la consulta SQL que genera la interfaz Views para hacer la clasificación en la consulta? – alxp

+0

No, la clasificación depende de algunas variables que no están disponibles en ese contexto. – Ace

Respuesta

17

El módulo vistas provides some hooks de manipulaciones externas '', al igual que el núcleo de Drupal.

Puede implementar hook_views_pre_render(&$view) dentro de un módulo personalizado y manipular la matriz de resultados estén disponibles en $view->result:

/** 
* Implementation of hook_views_pre_render() 
* 
* @param view $view 
*/ 
function YourModuleName_views_pre_render(&$view) { 
    // Check if this is the view and display you want to manipulate 
    // NOTE: Adjust/Remove the display check, if you want to manipulate some/all displays of the view 
    if ('YourViewName' == $view->name && 'YourDisplayName' == $view->current_display) { 
    // EXAMPLE: Just reverse result order 
    // TODO: Replace with your desired (re)ordering logic 
    $view->result = array_reverse($view->result); 
    } 
} 

El gancho es invocada en la mitad del proceso de generación de vistas, después de todo, los datos de resultado ha sido montado, pero antes de que se muestre la salida real, los cambios en la matriz de resultados se reflejarán en el resultado final de las vistas.

EDIT: Como alternativa, puede procesar la vista 'manualmente', copiando el comportamiento de la función views_get_view_result(), pero en lugar de devolver el resultado, manipularlo y seguir prestando la vista:

function yourModule_get_custom_sorted_view($display_id = NULL) { 
    // As the custom sorting probably only works for a specific view, 
    // we 'demote' the former $name function parameter of 'views_get_view_result()' 
    // and set it within the function: 
    $name = 'yourViewName'; 
    // Prepare a default output in case the view definition can not be found 
    // TODO: Decide what to return in that case (using empty string for now) 
    $output = ''; 

    // Then we create the result just as 'views_get_view_result()' would do it: 
    $args = func_get_args(); 
    if (count($args)) { 
    array_shift($args); // remove $display_id 
    } 

    $view = views_get_view($name); 
    if (is_object($view)) { 
    if (is_array($args)) { 
     $view->set_arguments($args); 
    } 
    if (is_string($display_id)) { 
     $view->set_display($display_id); 
    } 
    else { 
     $view->init_display(); 
    } 
    $view->pre_execute(); 
    $view->execute(); 
    // 'views_get_view_result()' would just return $view->result here, 
    // but we need to go on, reordering the result: 
    $important_var = important_function(); 
    $view->result = sorting_function($result, $important_var); 
    // Now we continue the view processing and generate the rendered output 
    // NOTE: $view->render will call $view->execute again, 
    // but the execute method will detect that it ran already and not redo it. 
    $output = $view->render(); 
    // Clean up after processing 
    $view->post_execute(); 
    } 

    return $output; 
} 

Nota: Esto es una gran cantidad de código duplicado y, por lo tanto, propenso a errores: no lo recomiendo y prefiera ir con la implementación de gancho anterior, tratando de encontrar una manera de acceder a su $ important_var desde dentro .

+0

¡Eso suena realmente bien!Pero, ¿y si tengo alguna variable externa que necesito para la clasificación? – Ace

+0

@Ace: O puede obtener el contenido variable externo en la implementación de gancho (llamando 'important_function()' desde allí, o a través de un global previamente poblado, o llamando a una función 'get_x()' que usa una estática para almacenar la variable calculada previamente), o necesita hacer el procesamiento de vista 'manualmente' - Actualizaré mi respuesta para mostrar la última opción. –

+3

El uso de hook_views_pre_render no funciona con un buscapersonas. Solo ordenará los resultados de la página actual. – eSentrik

8

Dependiendo de su lógica de clasificación, puede intentar usar hook_views_query_alter() para implementar su clasificación directamente en la consulta.

Esto puede ser un poco complicado, sin embargo, puede familiarizarse con el objeto views_query.

Aquí hay un ejemplo del mundo real donde apliqué una regla de unión basada en el contexto de la página, luego, agregué reglas de clasificación adicionales.

/** 
* Implementation of hook_views_query_alter(). 
*/ 
function yourmodule_views_query_alter(&$view, &$query) { 
    if ($view->name == 'view_projects' && $view->current_display == 'panel_pane_4') { 
    if (arg(0) == 'node' && is_numeric(arg(1))) { 
     $node = node_load(arg(1)); 
     if ($client_nid = $node->field_ref_client[0]['nid']) { 
     $query->table_queue['node_node_data_field_ref_client']['join']->extra = "field_ref_client_nid = " . $client_nid; 
     $query->add_orderby('node', NULL, 'DESC', 'node_node_data_field_ref_client_nid'); 
     $query->add_orderby('node', 'created', 'DESC'); 
     } 
    } 
    } 
} 

Ver: http://drupalcontrib.org/api/function/hook_views_query_alter/6

+0

Otro ejemplo con una instrucción SQL ['ORDER BY CASE'] (http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case) está en [esta respuesta] (http://drupal.stackexchange.com/a/44871/16305). Permite un orden de clasificación arbitrario para los campos de lista. – tanius

3

utilizo como código para ello:

/** 
* Implementation of hook_views_post_execute() 
* 
* @param view $view 
*/ 
function YourModuleName_views_post_execute(&$view) { 
    // Check if this is the view and display you want to manipulate 
    // NOTE: Adjust/Remove the display check, if you want to manipulate some/all displays of the view 
    if ('YourViewName' == $view->name && 'YourDisplayName' == $view->current_display) { 
    // EXAMPLE: Just reverse result order 
    // TODO: Replace with your desired (re)ordering logic 
    $view->result = array_reverse($view->result); 
    } 
} 

hook_views_pre_render no está funcionando para mí.

0

Combiné los ejemplos anteriores y los reescribí como sigue. En mi caso, tuve que ordenar los artículos individualmente.

NOTA: No incluí la condición de unión y no lo intenté con un campo personalizado. Pero siento que puedes resolverlo fácilmente.

/** 
* Implementation of hook_views_query_alter(). 
*/ 
function yourmodule_views_query_alter(&$view, &$query) { 
    if ($view->name == 'your_view_name' && $view->current_display == 'your_pane_name') { 
    if ($query->orderby[0]['field'] == 'my_order_field') { 
     $query->orderby[0]['field'] = "FIELD(my_order_field, 'ord3','ord1','ord2')"; 
    } 
    } 
} 
Cuestiones relacionadas