Jump to content

Self submitting AJAX


Go to solution Solved by mac_gyver,

Recommended Posts

For simplicity, I've sometimes created a form with

<form action="" method="POST">

which had the form self-check its file to run PHP.

Now I have a file with a form and I am using AJAX where the URL link is the same file.

It didn't work with "" but does with the file name.

However, because it is regurgitating the file, a by-product of the process is that the webpage displays the form twice.

Is there a fix to stop this under these conditions. Or is an external PHP file the only solution?

Edited by phppup
Typos
Link to comment
https://forums.phpfreaks.com/topic/319149-self-submitting-ajax/
Share on other sites

  • Solution
Posted (edited)

provided the code for the page is laid out in this general order -

  1. initialization
  2. post method form processing
  3. get method business logic - get/produce data needed to display the page
  4. html document

at the end of item #2, if the request was an AJAX request, you would build and output the response to the ajax request, then exit/die, so that the rest of the code on the page isn't executed.

here's a snippet of code to detect an AJAX request -

define('IS_AJAX_REQUEST', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');

you can then conditionally run AJAX request only code using -

if(IS_AJAX_REQUEST)
{
	// build and output the response to the AJAX request
	// typeically json_encode([some meaningful error or success data]);

	// stop php code execution
	die;
}

 

Edited by mac_gyver

This is where an MVC-style approach to the server-side code comes in handy. The display logic is in the view, and the controller decides what to return. If the request to the controller is AJAX-based (or POST, in this case) the controller returns JSON-encoded data whereas if it's not, it returns the full compiled HTML.

Edited by maxxd
Posted (edited)

@mac_gyver A follow-up to your solution (which initially failed).

The AJAX road has been grimy for me, so this time around, instead of using the usual format of

        $.ajax({ 
        type: "POST", 
        url: "check.php", 
        data: "email="+ usr,
        dataType: 'text',
            success: function(msg){
                if(msg == 'OK'){
                 alert ("success");
                // ..... etc.

I tried a format from W3 that looks like this

function loadDoc() {
  const xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      // ....blah blah blah

I don't really know the difference between the two, but in building my script it seemed to be accomplishing the assigned task.

I plugged in the code you provided, and then added some troubleshooting to determine that

if(IS_AJAX_REQUEST)

was determining a NO response.

Ultimately, I modified your code and seem to have success with

if($_SERVER["REQUEST_METHOD"] == "POST")
{
    // build and output the response to the AJAX request
    // typeically json_encode([some meaningful error or success data]);
echo "<br>yes AJAX request detected<br>"; die; } else { echo "<br>no AJAX request NOT detected<br>";
    // stopped php code execution in affirmative only
    
}


Now I have new questions (if you (or anyone else) would be so kind):

Is my revision safe to use?

Does it create any security issues or functional dilemmas?

I can see why my code (built on your assistance) works, but why does the original not detect the AJAX submission as was expected?

Edited by phppup
Typos
29 minutes ago, phppup said:
new XMLHttpRequest()

if you use this, you must specifically set the request header, between the .open() and .send() calls - xhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

If the only POST method request made to the page will be via an ajax request, then simply testing for a post method request will work.

34 minutes ago, phppup said:

Does it create any security issues

all data submitted to your site can come from anywhere, not just your form, links, cookies, ajax requests, ..., can be set to anything, and cannot be trusted. you must validate all input data to make sure it meets the business needs of your application and use all data securely in whatever context it is being used in.

Posted (edited)

Hey @mac_gyver , I want to thank you tremendously for your responses.

After scrolling further in the tutorial that I was using I spotted a section that states EXACTLY what you mentioned above with an added caveat that there is an exception if

Quote

using the FormData object to send form data

and it then provides the necessary JavaScript.

I'm not sure why there's a difference, but at this point I'm just happy to have working components that suit my needs.

Nonetheless, curiosity did have me wondering, would the solution that you provided initially have worked if I had used the "more traditional" AJAX format?

And yes, I understand the need for validating and sanitizing form data (but thanks for the reminder) and was more concerned that the alternate method of JavaScripting might (in itself) open a vulnerability.

Edited by phppup
Typos

XMLHttpRequest is a bit outdated these days with the rise of the fetch API. That having been said, the fetch API can be a bit rough to wrap one's brain around if you're new to it.

Either way, one option is to add an additional parameter to the AJAX calls (for instance, 'ajaxRequest') that isn't set in the normal call expecting a full page refresh. Check for that extra parameter in the processing code and you know how to return the data - either a JSON string of just the data or the entire page.

I'm a little brain-fried, so I hope that makes sense...

Just going back a bit to your question, and some short history:
 

Under the covers, the XMLHttpRequest() was a non-standard addition to the official DOM api, first added in by microsoft.  While it was an important idea, as it was not standard, and not every browser maker was eager to add the feature in, so there's still code floating around that was aimed at specific browsers (microsoft in particular, as they were the inventor of it).  With that said, it's at the core of all "ajax".  

The acronym "AJAX" is short for "Asynchronous JavaScript and XML" which in reality rarely involves XML anymore.  Most people use json as the data transport format and not xml.

$.ajax() is the grandparent of javascript libraries:  jquery. 

Just a quick aside, but Jquery was the first to popularize taking advantage of the fact that javascript allows you to name a variable '$'.  It doesn't own the use of $, being that it's just an alias for the jquery object, but regardless, there's so much code around that used demonstrated $.ajax() people still associate it with jquery, and to be fair, it was a nice improvement over hand coding all DOM manipulation code yourself.  The ajax() method is just a small part of jquery, but it's still popular with many developers for its simplicity and ease of implementation.  It was also created prior to a number of improvements to javascript itself, in particular ES6.  And it's still the best known wrapper around XMLHttpRequest, although there have been any number of other libraries around that people used to do the same thing.

In recent years, people have moved away from jquery (which is a large library) in favor of other more lightweight and problem specific libraries. 

In the ajax coding world, one popular competitor to using jquery for ajax is Axios.  

As for the fetch api, it is an entirely different animal, being that it was designed as an alternative to the use of XMLHttpRequest and was part of an initiative to provide more robust support for http request/response architecture.  In other words, it was purpose built as an alternative to using XMLHttpRequest. 

One of the main reasons you want to write code that uses fetch, is that fetch was built on top of ES6 and inherently uses Promises.

Just in case you aren't clear on this, prior to promises, people used callbacks.  The more complicated the code the more likely you were to have a mess of interwoven callbacks, leading to the phrase "callback hell".

So promises were introduced into the language as an alternative to callbacks.  The fetch api returns a Promise object, and you will often see code that uses it that way, with a chain of code like this:

 

fetch(url, options)
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
});

You might also notice, that using fetch, not unlike using the native XMLHttpRequest function is built into the browser.  You don't need a library to do it.  Looking back on it, what Axios attempted to do, was bridge the gap between the introduction of Promises and an api that allowed you to write promise based code, only under the covers it was still using XMLHttpRequest.

Unlike Axios, you don't need any library... just put your fetch code in there, and it already hides lots of complexity and works for you.

Last but not least, given the intrinsic use of Promises, anyone can also take advantage of the syntactic sugaring of Async Await when writing your fetch api code.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.