DEV Community

Cover image for Backend Operations in PHP from 0 to Hero(Pt. 3 Heavy operations and AJAX)
Code_Jedi
Code_Jedi

Posted on

Backend Operations in PHP from 0 to Hero(Pt. 3 Heavy operations and AJAX)

In the last tutorial, we made a PHP script that performs customizable backend operations that take in user input.

In part 3, we'll be making a php script that refers another php script, which then executes a memory and time intensive background script through AJAX.

In order to understand some of the things covered in this tutorial, I strongly advice you to read Part 1 and Part 2


Just thinking about running and handling these sorts of memory and time intensive background processes in PHP brings back memories of younger me really struggling with them.

The reason is, I've spent a lot of time trying to handle and work with these types of PHP background operations. Heavy background operations in PHP are hard to:

  • Handle
  • Scale
  • Adapt for good UX

But in this tutorial, I'll be condensing my experience with such backend operations and teaching you the easiest and most efficient way to perform and handle long running backend operations in PHP!


Let's get started!

First of all, let's create an index.php file:

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Simple operations</title>
  </head>
  <body>
  <form method="post" action="results.php">
  Ticker: <input type="text" name="ticker"><br>
  <button type="submit" >Submit</button>
  </form>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

As you can see, all it does is display a form asking the user for a 'url' and 'tag' parameter.


These parameters will then be passed on to our results.php file, and this is where the magic happens...

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Complex operations</title>
  </head>
  <body>
    <h1 id="txt"></h1>
    <?php
    session_start(); 
    $ticker = $_POST["ticker"];
    $_SESSION["ticker"] = $ticker;
    ?>
    <script>
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                document.getElementById("txt").innerHTML = this.responseText;
            }
        }
        xmlhttp.open("GET", "bg.php", true);
        xmlhttp.send();
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Now I know the stuff between inside the script tag might look scary, but let me explain what's happening here:

  1. The h1 tag containing the "txt" id is defined, this will be used later by the code between the script tag.

  2. PHP then starts the user session using session_start(); function, defines the $ticker variable as the parameters received from the index.php file and finally defines the $_SESSION["ticker"] as the previously defined $ticker variable. These variables are then going to be used in bg.php to execute the background operation, but we'll get into that later.

  3. Inside the script tag is where AJAX retrieves the data displayed by bg.php inside the h1 tag created earlier.


Inside bg.php:

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Complex operations</title>
  </head>
  <body>
    <?php
    session_start(); 
    $ticker = $_SESSION["ticker"];
    $output = exec("ticker=$ticker node op1.js");
    echo("<h1>$output</h1>");
    ?>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

PHP:

  • Starts the user session using session_start();

  • Retrieves the $_SESSION["ticker"]; session variables created by the results.php file.

  • Displays the output of the op1.js file once executed with the $ticker parameter passed on as a system variable( refer to Part 2 ).
    The displayed text contents are then retrieved by AJAX and displayed on results.php


op1.js simply scrapes the stock ticker passed-on by bg.php inside the $ticker parameter ( refer to Part 2 ).
For the purpose of this tutorial, there's no need to know how this works, but if you want to find out, check out this tutorial

const puppeteer = require('puppeteer');
async function start() {
    const url = 'https://finance.yahoo.com/quote/' + process.env.ticker + '?p=' + process.env.ticker + '&.tsrc=fin-srch';
    const browser = await puppeteer.launch({
      args: ['--no-sandbox']
    });  
    const page = await browser.newPage();
    await page.waitFor(1000)
    await page.goto(url);
    var accept = ("#consent-page > div > div > div > form > div.wizard-body > div.actions.couple > button");
    await page.click(accept)
    await page.waitFor(1000)
    var element = await page.waitForXPath("/html/body/div[1]/div/div/div[1]/div/div[2]/div/div/div[5]/div/div/div/div[3]/div[1]/div[1]/span[1]")
    var price = await page.evaluate(element => element.textContent, element);
    console.log(price)
    browser.close()
}
start();

Enter fullscreen mode Exit fullscreen mode

Here's how the whole process looks like:

The process


Let's see how it works!
In action

As you can see, the stock price of the specified ticker is returned once it's scraped by the Node.js script, displayed by bg.php and retrieved by results.php, which takes about 5 seconds.

The main advantage of this is that the results.php webpage doesn't need to wait for the stock price element to be retrieved in order to load the page, this way, long running background operations that include: web scraping, data queries or machine learning don't need to take up loading time on the front-end.


Final thoughts

AJAX is a full-stack, back-end, and front-end developer's dream because it eliminates the problems of:

  • Loading time
  • Timeout errors on the front-end
  • Bad UX that requires the user to constantly be redirected, reloaded, or getting stuck on loading screens

Since AJAX is such a big topic and has so many useful implementations, comment down below if you would like another tutorial on AJAX explaining how to build more complex fullstack applications with it?

Byeeee👋

Discussion (4)

Collapse
moay profile image
moay

Just a quick thought: You are promoting serious security vulnerabilities here.

First:

$ticker = $_POST["ticker"];
Enter fullscreen mode Exit fullscreen mode

Later

$output = exec("ticker=$ticker node op1.js");
Enter fullscreen mode Exit fullscreen mode

This is known as code injection and literally the number one security risk on the OWASP list. You are basically allowing everybody to just do stuff on the server.

To the less experienced readers: Don't follow anything of whats written in this article.

To the author: Familiarize yourself with

Collapse
code_jedi profile image
Code_Jedi Author

I understand that if this code was dealing with sensitive and private information, I wouldn't do it this way either, but since the applications I had in mind for this code are just ones that deal with none-sensitive data, like data scraped from public websites, I didn't bother with all the security stuff. There's also very little things the user is able to alter within the code.

As far as I'm concerned, the only big risk with this method for non-sensitive data like public stock price data is having too many background processes running at the same time, which can be easily resolved and controlled ( I might make a blog post about that ).

Collapse
moay profile image
moay • Edited

Allow me to give a short answer here.

  • exec('Whatever is in the request') is one of the most dangerous things you can do. It's not about what's in your application, it's about what is on your server. You clearly did not understand the danger, so again: read about code injection. Something like this might help you get the point: cobalt.io/blog/a-pentesters-guide-...
  • I am not concerned about your project. It's probably going to work. I'm concerned with people that come here, see a title like "PHP Backend from Zero to Hero" and just copy paste stuff for their projects. You never know where they are going to run this, how well they protect the runtime (given they even know how to do this), and so on.

Stating that a blog post is about "PHP Backend" and implying that it contains a guide on how to do it the right way is just not what you want to do if you clearly have a huge lack in understanding what happens. Building a PHP backend is far (!) more than just misusing PHP to run a node script. Don't make people think that this is what you should do. :-)

To people reading this: If you want a better guide on what you can do with PHP and how to really use it: phptherightway.com/

Collapse
indevx profile image
Nick Dev • Edited

If you use php - use it. Need/want js - use ajax to nodejs server...