How to pass an array from javascript ajax function into into php script?

I have an ajax function that connects to a php file. I’m trying to pass arguments (‘tax_query’) collected on the page to a query running on php. How can I create an array (or maybe just a string) in javascript and pass that as an argument to the function inside php. Everything is working except that I have query arguments in the php file hard coded where I want them to be dynamic based on what I pass through the ajax request.

Here is my jQuery function that grabs data from user selections, saves the variables and connects to php via ajax

(function($) {

  function getFilters () {
    var filters = {}
    
    $('.checked').each(function () {
      filters[this.dataset.filter] = this.dataset.value
    })
    
      return filters
    }

    $(".dropdown-menu li a").click(function (event) {
      var $this = $(this)
      var $dropdown = $this.parents('.dropdown')
      var html = $this.text() + ' <span class="caret"></span>'
      
      $dropdown.find(".btn").html(html);  
      $dropdown.find('a').removeClass('checked');
      $this.addClass('checked');

      var filters = getFilters();

      //var level = filters["level"];
      var level = filters.level;
      var location = filters.location;
      var specialty = filters.specialty;
      
      alert("Level: "+level+" Location: "+location+" Specialty: "+specialty);

      console.log(getFilters());

      event.preventDefault();

      alert("made it up to ajax");
   
      $.ajax({
          type: 'POST',
          url: '<?php echo admin_url('admin-ajax.php');?>',
          dataType: "html", // add data type
          data: { action : 'get_ajax_posts' },
          success: function( response ) {
              console.log( response );

              $( '.posts-area' ).html( response ); 
          }
      });      
    })

})(jQuery);

here is my php function that runs a Wordpress post query and returns back to jquery.

function get_ajax_posts() {
    // Query Arguments
    $args = array(
      'post_type' => 'the-talent',
      'tax_query' => array(
          'relation' => 'AND',
          array(
              'taxonomy' => 'level',
              'field'    => 'term_id',
              'terms'    => array( '25' ),// needs to be 3 and up? maybe use if statements?
          ),
          array(
              'taxonomy' => 'location',
              'field'    => 'term_id',
              'terms'    => array( '20' ),
          ),
          array(
              'taxonomy' => 'specialty',
              'field'    => 'term_id',
              'terms'    => array( '4' ),
          ),
          
      ),
    );

    // The Query
    $ajaxposts = new WP_Query( $args );

    $response = '';

    // The Query
    if ( $ajaxposts->have_posts() ) {
        while ( $ajaxposts->have_posts() ) {
            $ajaxposts->the_post();
            //$response .= get_template_part('products');

            $response .= 

            $name = get_field('name');
            $main_image = get_field('main_image');

         ?>

        <div class="col-sm-6 col-md-3 talent">
          <div class="talent">
            <a type="button" href="<?php the_permalink() ?>">
             <img class="img-responsive" src="<?php echo $main_image; ?>">
             <h3 class="dark"><?php echo $name; ?></h3> 
            </a>
          </div><!-- close talent -->
        </div><!-- close col -->

       <?php

       ;
        }
    } else {
        $response .= get_template_part('none');
    }

    //echo $response;

    exit; // leave ajax call
}

// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_ajax_posts');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_ajax_posts');

Hi @aaron4osu, simply add the filters to the data you’re sending:

$.ajax({
  // ...
  data: { action : 'get_ajax_posts' , filters: filters }
})

Then these filters are available in your PHP script as $_POST['filters'], and you can create your query like e.g.:

$query = ['relation' => 'AND'];

foreach ($_POST['filters'] as $key => $value) {
    $query[] = [
        'field' => 'term_id',
        'taxononomy' => $key,
        'terms' => [$value]
    ];
}

Thanks for the help, but I’m still having issues…I tried that but now response is coming back empty (I think)… here is my updated code…

function get_ajax_posts() {

	$tax_query = ['relation' => 'AND'];

	foreach ($_POST['filters'] as $key => $value) {
	    $tax_query[] = [
	        'field' => 'term_id',
	        'taxononomy' => $key,
	        'terms' => [$value]
	    ];
	}

    // Query Arguments
    $args = array(
      'post_type' => 'the-talent',
      'tax_query' => $tax_query,
      // 'tax_query' => array(
      //     'relation' => 'AND',
      //     array(
      //         'taxonomy' => 'level',
      //         'field'    => 'term_id',
      //         'terms'    => array( '25' ),// needs to be 3 and up? maybe use if statements?
      //     ),
      //     array(
      //         'taxonomy' => 'location',
      //         'field'    => 'term_id',
      //         'terms'    => array( '20' ),
      //     ),
      //     array(
      //         'taxonomy' => 'specialty',
      //         'field'    => 'term_id',
      //         'terms'    => array( '4' ),
      //     ),
          
      // ),
    );

    // The Query
    $ajaxposts = new WP_Query( $args );

    $response = '';

    // The Query
    if ( $ajaxposts->have_posts() ) {
        while ( $ajaxposts->have_posts() ) {
            $ajaxposts->the_post();
            //$response .= get_template_part('products');

            $response .= 

            $name = get_field('name');
            $main_image = get_field('main_image');

         ?>

        <div class="col-sm-6 col-md-3 talent">
          <div class="talent">
            <a type="button" href="<?php the_permalink() ?>">
             <img class="img-responsive" src="<?php echo $main_image; ?>">
             <h3 class="dark"><?php echo $name; ?></h3> 
            </a>
          </div><!-- close talent -->
        </div><!-- close col -->

       <?php

       
        }// end while
    } else {
        $response .= get_template_part('none');
    }

    exit; // leave ajax call
}// end get_ajax_posts

// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_ajax_posts');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_ajax_posts');

js

(function($) {


function getFilters () {
  var filters = {}
  
  $('.checked').each(function () {
    filters[this.dataset.filter] = this.dataset.value
  })
  
    return filters
  }

  $(".dropdown-menu li a").click(function (event) {
    var $this = $(this)
    var $dropdown = $this.parents('.dropdown')
    var html = $this.text() + ' <span class="caret"></span>'
    
    $dropdown.find(".btn").html(html);  
    $dropdown.find('a').removeClass('checked');
    $this.addClass('checked');

    var filters = getFilters();

    //var level = filters["level"];
    var level = filters.level;
    var location = filters.location;
    var specialty = filters.specialty;
    
    alert("Level: "+level+" Location: "+location+" Specialty: "+specialty);

    console.log(getFilters());


    event.preventDefault();

    alert("made it up to ajax");
 
    $.ajax({
        type: 'POST',
        url: '<?php echo admin_url('admin-ajax.php');?>',
        dataType: "html", // add data type
       // data: { action : 'get_ajax_posts' },
        data: { action : 'get_ajax_posts' , filters: filters },
        success: function( response ) {
            console.log( response );

            alert("responce: "+response.toString() );

            $( '.posts-area' ).html( response ); 
        }
    });      
  })

})(jQuery);

Well the JS looks right… what is the exact response you’re getting though? You might check the network panel of the browser dev tools to directly get the status, headers etc. without having to log anything; e.g. see here for firefox.

PS: This line in your PHP looks like you’re missing something, you’re just appending the following assignment to the $response here:

I was just suggesting to use the network monitor so that you don’t need those annoying alerts. :-) BTW if anything why not just also log the response to the console?

Anyway there is indeed no response body, but the payload gets sent correctly and the status is 200 OK… so there seems to be an issue with your PHP script. Are you actually appending any data to the $response if $ajaxposts->have_posts()? What do you get when you var_dump() the query and the posts (you should see the output in the network panel then)?

I’m not really sure how to do that. I tried adding this but keep getting null … even if I switch to the hard coded tax_query which is working

echo var_dump($arg);

so right now the code is returned to the hardcoded version of the tax_query

function get_ajax_posts() {

	$tax_query = ['relation' => 'AND'];

	foreach ($_POST['filters'] as $key => $value) {
	    $tax_query[] = [
	        'field' => 'term_id',
	        'taxononomy' => $key,
	        'terms' => [$value]
	    ];
	}

    // Query Arguments
    $args = array(
      'post_type' => 'the-talent',
      //'tax_query' => $tax_query,
      'tax_query' => array(
          'relation' => 'AND',
          array(
              'taxonomy' => 'level',
              'field'    => 'term_id',
              'terms'    => array( '25' ),// needs to be 3 and up? maybe use if statements?
          ),
          array(
              'taxonomy' => 'location',
              'field'    => 'term_id',
              'terms'    => array( '20' ),
          ),
          array(
              'taxonomy' => 'specialty',
              'field'    => 'term_id',
              'terms'    => array( '4' ),
          ),
          
      ),
    );

    var_dump($arg);
    print_r($arg);
    

    // The Query
    $ajaxposts = new WP_Query( $args );

    $response = '';

    // The Query
    if ( $ajaxposts->have_posts() ) {
        while ( $ajaxposts->have_posts() ) {
            $ajaxposts->the_post();
            //$response .= get_template_part('products');

            $response .= "";

            $name = get_field('name');
            $main_image = get_field('main_image');

         ?>

        <div class="col-sm-6 col-md-3 talent">
          <div class="talent">
            <a type="button" href="<?php the_permalink() ?>">
             <img class="img-responsive" src="<?php echo $main_image; ?>">
             <h3 class="dark"><?php echo $name; ?></h3> 
            </a>
          </div><!-- close talent -->
        </div><!-- close col -->

       <?php

       var_dump($response);
       print_r($response);

       
        }// end while
    } else {
        $response .= get_template_part('none');
    }
    
    
    exit; // leave ajax call
}// end get_ajax_posts

// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_ajax_posts');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_ajax_posts');

It’s just var_dump() (without the echo), it already prints to the output.

Here you have it right but $arg is not defined as far as I can tell… you might increase the error reporting level to get more immediate feedback on such issues.

Finally got it working with queries for each situation depending which of the 3 filters (level, location, and/or specialty) is selected. Curious if there is a better way than having 7 if/else statements?

(function($) {

  function getFilters () {
    var filters = {}
    
    $('.checked').each(function () {
      filters[this.dataset.filter] = this.dataset.value
    })   
      return filters
    }

    $(".dropdown-menu li a").click(function (event) {
      var $this = $(this)
      var $dropdown = $this.parents('.dropdown')
      var html = $this.text() + ' <span class="caret"></span>'
      
      $dropdown.find(".btn").html(html);  
      $dropdown.find('a').removeClass('checked');
      $this.addClass('checked');

      var filters = getFilters();

      //var level = filters["level"];
      // var level = filters.level;
      // var location = filters.location;
      // var specialty = filters.specialty;

      event.preventDefault();
   
      $.ajax({
          type: 'POST',
          url: '<?php echo admin_url('admin-ajax.php');?>',
          dataType: "html", // add data type
         // data: { action : 'get_ajax_posts' },
          data: { action : 'get_ajax_posts' , filters: filters },
          success: function( response ) {
              $( '.posts-area' ).html( response ); 
          }
      });      
    })

})(jQuery);
function get_ajax_posts() {

    // get filters from 3 drop down menus 
	$tax_query = $_POST['filters'];
	
	$location = $tax_query['location'];
	$specialty = $tax_query['specialty'];

	$levels = $tax_query['level'];
	switch ($levels) {
		    case 23:
		        $level = array('23', '24', '25', '26', '27'); // Level 1 through 5
		        break;
		    case 24:
		       $level = array('24', '25', '26', '27'); // Level 2 through 5
		        break;
		    case 25:
		        $level = array('25', '26', '27');// Level 3 through 5
		        break;
			case 26:
		        $level = array('26', '27');// Level 4 and 5
		        break;
			case 27:
		        $level = '27';// Level 5
		        break;
		    default:
		        $level = array('23', '24', '25', '26', '27');
		}

	// Display Talent if only Level is selected
	if(isset($tax_query['level']) && empty($tax_query['location']) && empty($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND',
	          array(
	              'taxonomy' => 'level',
	              'field'    => 'term_id',
	              'terms'    => $level,// 23 (4), 24(4), 25(7), 26(3), 27(3) // array( 25, 26, 27 )
	              
	          ),   
	       ),
	    );
	}
	// Display Talent if only Level and Location is selected
	else if(isset($tax_query['level']) && isset($tax_query['location']) && empty($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND',
	          array(
	              'taxonomy' => 'level',
	              'field'    => 'term_id',
	              'terms'    => $level,// 23 (4), 24(4), 25(7), 26(3), 27(3) // array( 25, 26, 27 )
	              
	          ), 
	          array(
	              'taxonomy' => 'location',
	              'field'    => 'term_id',
	              'terms'    => $location,
              ),  
	      ),
	    );
	}
	// Display Talent if all three are selected
	else if(isset($tax_query['level']) && empty($tax_query['location']) && isset($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND',
	          array(
	              'taxonomy' => 'level',
	              'field'    => 'term_id',
	              'terms'    => $level,// 23 (4), 24(4), 25(7), 26(3), 27(3) // array( 25, 26, 27 )  
	          ), 
              array(
	              'taxonomy' => 'specialty',
	              'field'    => 'term_id',
	              'terms'    => $specialty,
              ),  
	      ),
	    );
	}
	// Display Talent if Level and specialty is selected
	else if(isset($tax_query['level']) && isset($tax_query['location']) && isset($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND',
	          array(
	              'taxonomy' => 'level',
	              'field'    => 'term_id',
	              'terms'    => $level,// 23 (4), 24(4), 25(7), 26(3), 27(3) // array( 25, 26, 27 )  
	          ), 
	          array(
	              'taxonomy' => 'location',
	              'field'    => 'term_id',
	              'terms'    => $location,
              ),
              array(
	              'taxonomy' => 'specialty',
	              'field'    => 'term_id',
	              'terms'    => $specialty,
              ),  
	      ),
	    );
	}
	// Display Talent if only Location is selected
	else if(empty($tax_query['level']) && isset($tax_query['location']) && empty($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND', 
	          array(
	              'taxonomy' => 'location',
	              'field'    => 'term_id',
	              'terms'    => $location,
              ),  
	      ),
	    );
	}
	// Display Talent if Location and specialty is selected
	else if(empty($tax_query['level']) && isset($tax_query['location']) && isset($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND',
	          array(
	              'taxonomy' => 'location',
	              'field'    => 'term_id',
	              'terms'    => $location,
              ),
              array(
	              'taxonomy' => 'specialty',
	              'field'    => 'term_id',
	              'terms'    => $specialty,
              ),  
	      ),
	    );
	}
	// Display Talent if only specialty is selected
	else if(empty($tax_query['level']) && empty($tax_query['location']) && isset($tax_query['specialty'])){

		// Query Arguments
	    $args = array(
	      'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'the-talent',
          'posts_per_page'=>-1,
	      'tax_query' => array(
	          'relation' => 'AND',
              array(
	              'taxonomy' => 'specialty',
	              'field'    => 'term_id',
	              'terms'    => $specialty,
              ),  
	      ),
	    );
	}
	
	else{
		$args = null;
		//echo "else Args: ". $args;
	}

	wp_reset_query();

    // The Query
    $ajaxposts = new WP_Query( $args );

    $response = '';

    // The Query
    if ( $ajaxposts->have_posts() ) {
        while ( $ajaxposts->have_posts() ) {
            $ajaxposts->the_post();
            //$response .= get_template_part('products');

            $response .= "";

            $name = get_field('name');
            $main_image = get_field('main_image');

         ?>

        <div class="col-sm-6 col-md-3 talent">
          <div class="talent">
            <a type="button" href="<?php the_permalink() ?>">
             <img class="img-responsive" src="<?php echo $main_image; ?>">
             <h3 class="dark"><?php echo $name; ?></h3> 
            </a>
          </div><!-- close talent -->
        </div><!-- close col -->

       <?php
     
       }// end while
    } else {
        $response .= get_template_part('none');
    }
    
    exit; // leave ajax call
}// end get_ajax_posts

// Fire AJAX action for both logged in and non-logged in users
add_action('wp_ajax_get_ajax_posts', 'get_ajax_posts');
add_action('wp_ajax_nopriv_get_ajax_posts', 'get_ajax_posts');

There certainly is… so the crucial difference is that you’re now mapping the single terms to a range of terms? But then why not simply include all the terms as filter values in the first place, maybe as a comma-separated list (you might also set a default checked class):

In your HTML:

<ul class="dropdown-menu">
  <li><a data-filter="level" data-value="23,24,25,26,27" class="checked">Level 1 and above</a></li>
  <li><a data-filter="level" data-value="24,25,26,27">Level 2 and above</a></li>
  <li><a data-filter="level" data-value="25,26,27">Level 3 and above</a></li>
  <li><a data-filter="level" data-value="26,27">Level 4 and above</a></li>
  <li><a data-filter="level" data-value="27">Level 5</a></li>
</ul>

Adjusted JS:

function getFilters () {
  var filters = {}

  $('.checked').each(function () {
    filters[this.dataset.filter] = this.dataset.value.split(',')
  })

  return filters
}

And then in your PHP:

$query = ['relation' => 'AND'];

foreach ($_POST['filters'] as $key => $terms) {
    $query[] = [
        'field' => 'term_id',
        'taxononomy' => $key,
        'terms' => $terms
    ];
}

$args = [
    'orderby' => 'title',
    'order' => 'ASC',
    'post_type' => 'the-talent',
    'posts_per_page'=>-1,
    'tax_query' => $query
];
1 Like

Think we’re going around-the-world to solve an A-B problem.

Change your comparator on the level funciton:

	          array(
	              'taxonomy' => 'level',
	              'field'    => 'term_id',
	              'terms'    => $level
	              'compare' => ">=" 
	          ), 

and pass it the singular minimum level value.

Sorry, my brain failed to parse that it was a taxonomy query. I would still do it from a single value though, just for readability.

Leave out the compare,

'terms', then is set to range($level,27)

if(isset($_POST['filters']['level'])) { $_POST['filters']['level'] = range($_POST['filters']['level'],27);
foreach ($_POST['filters'] as $key => $value) {
    $query[] = [
        'field' => 'term_id',
        'taxonomy' => $key,
        'terms' => $value
    ];
}
1 Like