How to ajax-update a view rendered by PHP

Discussion in 'App Development' started by deanstreet, Sep 8, 2021.

  1. I learn from books, blogs, and trying codes out, and never seen how experienced coders organize their Ajax codes. I am not sure my way of organizing files and using ajax is appropriate and how should I improve them. Please comment/advise.

    In a typical PHP + MySQL setting, say I have a `fruits.php` to retrieve data and load them into `fruits.html` for display; there is an accompanying `fruits.js` attached, when a user edits his fruits data on `fruits.html`, `fruits.js` sends the edited data to `fruits_ajax.php` to update the database and user can see new data on page without a page reload.

    Files structure
    Is the following organization (which I use) appropriate? I can merge fruits_ajax.php into fruits.php and use if (isset($_REQUEST("fruits"))) ... exit() to do the same thing, but I prefer keeping main logic and ajax request codes separate.
    Code:
    fruits.php
    $fruits = []; //array storing his user's liked fruits
    $age;
    $name;
    $fruitsString = "";
    foreach ($fruits as $fruit) {
      $fruitsString .= "$fruit ";
    }
    //load the data into and render fruits.html
    
    Code:
    fruits.html
    <div> {{name}} is {{age}} years old.</div>
    <div> He likes <span id="fruits">{{fruitsString}} </span>.</div>
    
    <!--some form to edit the fruits data-->
    <script src="fruits.js"></script>
    
    Code:
    fruits.js
    $("#editBtn").click(function(){ //edit form btn clicked
      let newData = new Object();
      //read edited fruits from the form into newFruits array variable
      newData.fruits = newFruits;
      $.post("fruits_ajax.php", newData); //no callback
    });
    
    Code:
    fruits_ajax.php
    $data = $_REQUEST["fruits"]; //array of fruits data
    //send the data to database for update
    
    On reflecting the new data
    The new fruits data are sent to database. But I want them to show without a page reload. Hence, I use a callback in `$.post` to update the DOM. Is it how it should be done? How else can it be done?
    Code:
    fruits.js
    .....//as above
      newData.fruits = newFruits;
      //now with callback to update view
      $.post("fruits_ajax.php", newData, function(){
        let fruitsString = "";
        newData.fruits.forEach(function(fruit){fruitsString += fruit});
        $("#fruits").text(fruitsString);
      });
    ...
    
    On JS (ajax callback) and PHP duplicated codes
    PHP renders the page using some logic, but to ajax-update the view, I have to use the callback, which will involve the same logic mirroring PHP? Hence, if PHP retrieves data and uses loop/if/blah blah to check/transform the data before rendering them to view, wouldn't those same operations be required inside ajax callback? But obviously PHP and JS codes are separate and so must result in duplicated codes. Am I mistaken somewhere and how should it be done?

    Say if instead of rendering fruits one by one in all cases, PHP outputs some text depending on the fruits array. Wouldn't the callback in `$.post()` also need to mirror the PHP? It seems something's wrong and too error-prone but I can't figure out how else to do it. Like when you edit a post in Reddit, it is ajax-sent to server and view is updated without a reload. When the view on that edited data is conditional, how can it update the view in frontend without duplicating those conditional codes?
    Code:
    fruits.php
    ...//as above
    $numberOfFruits = count($fruits); //number of elements in array
    if ($numberOfFruits == 0) {
      $fruitsString = "no fruits at all, so an unhealthy bastard.";
    } elseif ($numberOfFruits > 5) {
      $fruitsString = "many fruits, so a healthy good boy.";
    } else {
      foreach ($fruits as $fruit) {
        $fruitsString .= "$fruit ";
      }
    }
    
    Code:
    fruits.js
    ...//as above
    $.post("fruits_ajax.php", newData, function(){
      let fruitsString = "";
      numberOfFruits = newData.fruits.length; //number of elements in array
      if (numberOfFruits == 0) {
        fruitsString = "no fruits at all, so an unhealthy bastard.";
      } else if (numberOfFruits > 5) {
        fruitsString = "many fruits, so a healthy good boy.";
      } else {
        newData.fruits.forEach(function(fruit){fruitsString += fruit});
      }
      $("#fruits").text(fruitsString);
    });