Multiple taxonomy And acf filter group by

First off, in your tax queries (tax_query), you should use 'field' => 'term_id' and not 'field' => 'id' — i.e. use term_id and not id. But the default value/field is term_id (term ID), though.

So you can achieve the grouped display like so, and you’d use the code in place of those lines starting from the <ul class="event_entries"> up to that wp_reset_query(); — you don’t need to reset the global/main query because you’re just making a secondary query which doesn’t touch the global $wp_query variable:

<?php
// First, group the posts by the city.
$groups = array();
foreach ( $upcoming_events->posts as $i => $p ) {
    $city = get_field( 'ville', $p->ID );

    if ( ! isset( $groups[ $city ] ) ) {
        $groups[ $city ] = array();
    }
    $groups[ $city ][] =& $upcoming_events->posts[ $i ];
}

// Optional, sort the city names.
ksort( $groups, SORT_FLAG_CASE );

// Then display the posts.
if ( ! empty( $groups ) ) {
    echo '<ul class="event_entries">';
    foreach ( $groups as $city => $posts ) {
        if ( ! empty( $posts ) ) {
            // Display city name.
            echo '<h3>' . $city . '</h3>';

            // Display posts in that city.
            echo '<ul>';
            foreach ( $posts as $post ) {
                $event_start_date = get_field( 'date_de_debut', $post->ID );
                $event_end_date   = get_field( 'date_de_fin', $post->ID );

                echo '<li>Du' . $event_start_date . ' au ' . $event_end_date . '</li>';
            }
            echo '</ul>';
        }
    }
    echo '</ul>'; // close .event_entries
}

Note that I’m assuming all the posts always have a valid city.

Also, the above technique doesn’t alter the original posts in the $upcoming_events object, and if you called setup_postdata() in your code, you should also call wp_reset_postdata() at the end of your code/function.

UPDATE: In response to your comment.

Sorry, I can’t give a full tutorial or detailed guide on The Loop, but check that linked article and you’d at least understand what is, and how to use or work with The Loop.

However, what I can tell you from the above code, are:

  1. When you do $upcoming_events = new WP_Query(), the $upcoming_events variable becomes an instance of the WP_Query class and therefore, the variable will inherit/contain all the (public) properties (e.g. $upcoming_events->posts) and methods/functions (e.g. $upcoming_events->query()) of the class. And you can find out about those properties and methods by checking the official reference here.

  2. I also don’t understand what is $upcoming_events->posts as $i => $p‘..what are $i and $p??” – $i is the index of the current item in the $upcoming_events->posts which is being looped through, whereas $p is the value of that current item (i.e. $upcoming_events->posts[ $i ]) which is a WP_Post instance — but if you’re having trouble understanding that “current item”, then you need to check the PHP manual on foreach, or you can ask or search for “What is foreach in PHP?” on Stack Overflow..

  3. I also don’t understand $groups[ $city ][] =& $upcoming_events->posts[ $i ];” – well, that is just an alternative to $groups[ $city ][] = $upcoming_events->posts[ $i ]; (copying; note the = versus =&). And it’s called “assigning by reference” which basically helps improve performance in that we don’t need to copy the post objects to $groups and simply reference to them in the original $upcoming_events->posts.

    See this Stack Overflow question and/or this article for more details.

    But basically, think of references like shortcuts in your computer; e.g. an icon on the desktop that points to a file, e.g. a text file. So $my_var =& $file; is like making a shortcut to that text file, whereas $my_var = $file; (once again, note the = vs =&) is like you copied the file to your desktop.

  4. I don’t understand what is inside the $posts variable” – if you mean that foreach ( $groups as $city => $posts ), then that $posts is an array of post object references, so $posts[0] for example, is a reference to $upcoming_events->posts[0] which is a post object. I.e. They both point to the exact same WP_Post instance (see point #2 above).

So I hope those 4 points help you, but for more information about PHP-specific things like foreach/loop and references, please ask on Stack Overflow or search on Google, etc. 🙂