2

I have a custom view but now I want to put the nodes created by a specific user role on top.

I want to do this using code so I can easily implement this throughout multiple web pages.

I'm thinking to alter the query or to put an array sort before the nodes are rendered.

But I don't know which hook would be useful for this.

edit: using hook_views_pre_render as suggested by Jimajamma

function vacancies_views_pre_render(&$view) {
  dsm($view->result);
  $view->result = array_reverse($view->result);
  dsm($view->result);
}

But that doesn't change the order of the nodes in the view ( putting a dsm($view); in the if statement ensures me that it is this view that is called. )

3 Answers 3

6

You can use View's prerender hook to modify the view's results anyway you want.

For example,

function YOURMODULE_views_pre_render(&$view) {

   if ($view->name=='xyzzy') {

      // modify/sort the $view->result array to your heart's content here
      // for example, reverse it...
      $view->result=array_reverse($view->result);

   }

 }

Basically $view->result is an array of row results, so, just go through it and grab the rows you want first, then follow that up with the remaining rows.

ADDITION:

I created a quick view and did the above reversing and it certainly reversed the order so I am not sure what you are doing ever so slightly wrong to not see similar behavior on your site.

8
  • Helpful, but changing the $view->result order doesn't change the order that is output on the screen. ( while removing items does remove nodes from the view ) but no matter what items I remove the order doesn't change.
    – FLY
    Apr 19, 2013 at 12:26
  • see code addition above...not sure what you are doing differently
    – Jimajamma
    Apr 19, 2013 at 19:45
  • 2
    Changing the result order in hook_views_pre_render() definitely works.
    – rooby
    Apr 21, 2013 at 12:23
  • Thanks for testing jimajamma and rooby for confirming that this works. Must be something else that's wrong in my installation. But for the question asked this is the answer so I'll accept it. I'll post an update if I find what was wrong.
    – FLY
    Apr 22, 2013 at 7:50
  • feel free to post your code -- these tiny little errors are sometimes right there and all it takes is a second person to look and see them.
    – Jimajamma
    Apr 22, 2013 at 15:19
1

Since this is still high on the list of search results: in Drupal 9 (unsure of which versions this , the index property of each view row determines the order, not the array of rows itself. So, if you get the row objects ordered to your liking, you can do something like this:

// Optionally set the array keys to start at zero and count up first.
$my_ordered_results_array = $array_values($my_ordered_results_array);

// Iterate over the rows and set index values.
foreach ($my_ordered_results_array as $key => $row) {
  $row->index = $key;
}
0

I came across this looking for a possible solution using Drupal 10.1, and I got something that seems to be working well. I believe this will also work on Drupal 9, but I have personally not tested it. I combined a couple of the previous solutions together:

function vacancies_views_pre_render(&$view) {
  // Reverse the resulting array order
  $newResultOrder = array_reverse($view->result);

  // Now we have the new order so we can set the indexes for each result row.
  $newResultOrder = array_values($newResultOrder);
  foreach ($newResultOrder as $key => $row) {
    // Set index for each result item since it is now in the correct order.
    $row->index = $key;
  }

  $view->result = $newResultOrder;
}

I also created a ViewExecutable object that I was able to change the order (in my own case) based upon contextual items in an array. You could replace this with whatever order you need them. This was tested and is working on Drupal 10.1 at the moment:

$view = Views::getView('whatever_view_machine_name');

if (is_object($view)) {
  $view->setArguments($argsIfYouNeedThem);
  $view->setDisplay('default');
  $view->preExecute();
  $view->execute();

  // If $resultOrder was built, handle re-ordering.
  // This checks if there was a result order from context (code not shown),
  // but this array could be any array with Node ID values in
  // the order you need the final results to be in.
  if ($resultOrder) {
    $newResultOrder = [];
    // Get the current results.
    $results = $view->result;

    // Loop through the final resulting Node ID order.
    // (from my example, $resultOrder is an array of Node IDs from context).
    foreach ($resultOrder as $newResultNid) {
      // Loop through view results to compare order of IDs.
      foreach ($results as $result) {
        // Get the Node ID so we can compare against our $newResultNid
        $currentResultNid = $result->nid;

        if ($currentResultNid == $newResultNid) {
          $newResultOrder[] = $result;
          break;
        }
      }
    }

    // Now we have the new order so we can set the indexes for each result row.
    $newResultOrder = array_values($newResultOrder);
    foreach ($newResultOrder as $key => $row) {
      // Set index for each result item since it is now in the correct order.
      $row->index = $key;
    }

    $view->result = $newResultOrder;
  }

  // Since I am rendering in a twig template, we are setting a variable
  // for the view results to be passed back.
  $variables['rc_view'] = $view->buildRenderable('default', $args);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.