php 如何以编程方式对查看结果进行排序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2471361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:35:46  来源:igfitidea点击:

How to sort View results programmatically?

phpdrupalsortingdrupal-views

提问by Ace

I'm trying to take the results of a view - using the function views_get_view_result()- and sort the array in a way I couldn't do from within the Views interface. So far so good. I've got a $rows variable with all of the stuff I need.

我正在尝试获取视图的结果 - 使用该函数views_get_view_result()- 并以我无法在 Views 界面中执行的方式对数组进行排序。到现在为止还挺好。我有一个 $rows 变量,里面有我需要的所有东西。

Now... How do I put it back? :) Before I needed this sort, I used views_embed_view(), but I can't do that anymore.

现在......我如何把它放回去?:) 在我需要这种类型之前,我使用了views_embed_view(),但我不能再这样做了。

Grateful for any help on this, feels like I'm so close to cracking it!

感谢您对此的任何帮助,感觉我快要破解它了!

$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

回答by Henrik Opel

The views module provides some hooksfor 'external' manipulations, just like Drupal core.

视图模块为“外部”操作提供了一些钩子,就像 Drupal 核心一样。

You can implement hook_views_pre_render(&$view)within a custom module and manipulate the result array available in $view->result:

您可以hook_views_pre_render(&$view)在自定义模块中实现并操作以下可用的结果数组$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);
  }
}

The hook is invoked in the middle of the view generation process, after all result data has been assembled, but before the actual output gets rendered, so changes to the result array will be reflected in the views final output.

该钩子在视图生成过程的中间调用,在所有结果数据已组装之后,但在实际输出呈现之前,因此对结果数组的更改将反映在视图最终输出中。

EDIT:Alternatively, you could process the view 'manually', by copying the behavior of the views_get_view_result()function, but instead of returning the result, you manipulate it and continue to render the view:

编辑:或者,您可以通过复制views_get_view_result()函数的行为来“手动”处理视图,但不是返回结果,而是操作它并继续呈现视图:

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

Note:This is a lot of code duplication and thus error prone - I do not recommend this and would rather go with the hook implementation above, trying to find a way to get access to your '$important_var' from within that.

注意:这是很多代码重复,因此容易出错 - 我不推荐这样做,而是宁愿使用上面的钩子实现,试图找到一种方法来从其中访问您的“$important_var”。

回答by speedytwenty

Depending on your sorting logic, you might trying using hook_views_query_alter() to implement your sort directly into the query.

根据您的排序逻辑,您可能会尝试使用 hook_views_query_alter() 直接在查询中实现您的排序。

This can be a little tricky though, you may to familiarize yourself with the views_query object.

不过,这可能有点棘手,您可能会熟悉 views_query 对象。

Here is a real world example where I applied a join rule based on the context of the page, then additionally added sorting rules.

这是一个真实世界的示例,我根据页面的上下文应用了连接规则,然后另外添加了排序规则。

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

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

请参阅:http: //drupalcontrib.org/api/function/hook_views_query_alter/6

回答by Denis Borisov

I use such code for it:

我使用这样的代码:

/**
 * 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 is not working for me.

hook_views_pre_render 对我不起作用。

回答by user6200216

I combined the above examples and rewrote it as the following. In my case, I had to sort the items individually.

我把上面的例子结合起来,改写如下。就我而言,我必须单独对项目进行排序。

NOTE: I didn't include the join condition and I didn't try it with custom field. But I feel you can easily figure it out.

注意:我没有包含连接条件,也没有尝试使用自定义字段。但我觉得你可以很容易地弄清楚。

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