3

I have a form that $_POSTs an input value, and user's ID that saves the data to the database:

// frontend form 
<form id="form">
    <input type="radio" name="location" id="name1" value="1">
    <label for="name1">Label 1</label>

    <input type="radio" name="location" id="name2" value="2">
    <label for="name2">Label 2</label>

    <input type="radio" name="location" id="name3" value="3">
    <label for="name3">Label 3</label>

    <input type="hidden" name="userid" value="{userid}">
</form>     


// footer script
<script>
$(function() {
    $( "#form" ).change(function(a) {
        a.preventDefault();
        var formdata = new FormData($(this)[0]);

        $.ajax({
            method:         "POST",
            data:           formdata,
            contentType:    false,
            processData:    false
        });
    });
});
</script>


// validation snippet
<?php
    $location = isset( $_POST['location'] ) ? $_POST['location'] : '';
    $userID   = isset( $_POST['userid']   ) ? $_POST['userid']   : '';
    update_user_meta( $userID, 'location_current',  $location );
?>

When the users sets the radio location from their desktop, it send the form to the server, and saves it.

Each user also has a display (tablet) that has no input but echoes out the location value.

I currently have the tablet refreshing every 5 minutes, but wanted it to be more of a push with WP heartbeat.

I tried using this example: https://gist.github.com/strangerstudios/5888123

But wasnt sure how to have the value of the data['client'] = 'marco'; be data['client'] = '<?= $_POST['location']; ?>'; each time as it is printed once and not refreshed once the page is loaded or the location changed.

2 Answers 2

3
+50

Saving data

Based on Heartbeat API, you can add custom data to the sent heartbeat on heartbeat-send event in js. This would be used instead of the ajax function you have in your code example.

jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
  // Grab the required form data
  data.location = jQuery('input[name="location"]:checked').val();
  data.userid = jQuery('input[name="userid"]').val();
});

You can then use the data in PHP with hearbeat_recieved filter. There's also the heartbeat_nopriv_received filter for no-privilege environments.

add_filter( 'heartbeat_received', 'myplugin_save_location_on_heartbeat', 10, 2 );
function myplugin_save_location_on_heartbeat( $response, $data ) {
  // data required
  if ( empty( $data['location'] ) || empty( $data['userid'] ) ) {
    return $response;
  }
  // validate
  if ( ! is_numeric( $data['location'] ) || ! is_numeric( $data['userid'] ) ) {
    return $response;
  }
  // sanitize
  $location = absint( $data['location'] );
  $userID = absint( $data['userid'] );
  // update
  update_user_meta( $userID, 'location_current',  $location );
  // optional response
  $send_data_back = true;
  if ( $send_data_back ) {
    $response['location'] = $location;
    $response['userid'] = $userID;
  }
  // send response
  return $response;
}

You can access the data (response from hearbeat_recieved) again on heartbeat-tick event in js,

jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
  // Check for our data, and use it.
  if ( ! data.location || ! data.userid ) {
    return;
  }
  // use the response as needed
  console.log("location: " + data.location);
  console.log("user: " + data.userid);
});

Get data

With couple of tweaks you can get just the location data instead of saving it.

First send user id with heartbeat-send in js,

jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
  data.userid = jQuery('input[name="userid"]').val();
});

Then respond with current location user meta in PHP on hearbeat_recieved,

add_filter( 'heartbeat_received', 'myplugin_get_location_on_heartbeat', 10, 2 );
function myplugin_get_location_on_heartbeat( $response, $data ) {
  // data required
  if ( empty( $data['userid'] ) ) {
    return $response;
  }
  // validate
  if ( ! is_numeric( $data['userid'] ) ) {
    return $response;
  }
  // sanitize
  $userID = absint( $data['userid'] );
  // update
  $location = get_user_meta( $userID, 'location_current',  true );
  // send response
  return $response['location'] = $location;
}

EDIT 1: I think you could also use get_current_user_id() inside the php response function to get the user id, if you don't want to or can't send it in js on heartbeat-send event.

Last, update your view with the recieved data on heartbeat-tick in js,

jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
  // Check for our data, and use it.
  if ( ! data.location ) {
    return;
  }
  // if using radio buttons
  jQuery('input[name="location"][value='"+data.location+"']').prop('checked', true);
  // if you want to show result in somewhere else
  jQuery('#location-output-element').text(data.location);
});

I hope this helps and answers your question.

2
  • thanks for that! I was wondering, testing this out when two browsers are open they are both overriding each other. if I have a function that detects mobile devices, where would I put this condition to stop mobile devices from sending, but only receiving?
    – markb
    Apr 29, 2019 at 5:30
  • If you're using for example PHP Mobile_Detect class / library to detect mobile devices, then you would add the mobile check as the first thing to the heartbeat_received callback function. This way server would refuse save requests on mobile. Or if you check for mobile devices on front end with js, then add the check to heartbeat-send event function. Third way is to wrap the update_user_meta in a if-else statement, where on true (is mobile) only get_user_meta is used and on false (not mobile) user meta is updated. Apr 29, 2019 at 6:17
0

To send value using HTTP methods, the page must submit data. Only page refresh will not work. Your page must send a post request with the data location and you are using ajax to send form data.

In the API data['client'] = 'marco'; you can use your own data object send from your ajax request.

data['client'] = your formdata;

or you can use your PHP code same as you mentioned above:

data['client'] = '<?php echo $_POST['location']; ?>'; // make sure you validate data first.

If this doesn't help, please show the full implementation of API and usage of your ajax data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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