How to POST JSON with JS Fetch with a PHP API backend

Viewed 19

I have been trying to connect to my server to send and receive data, but for some reason I can only GET data back, but not POST data. I am using the JS Fetch API, but have also tried using the XMLHttpRequest with similar results. I don't receive any error logs except for the catch error that I create, so any help would be fantastic!

JS GET Users - Works

function getUsers() {
    fetch("../backend/api/user/read.php", {
        method: "GET",
        mode: "cors",
        headers: {
           "Content-Type": "application/json"
        }
    })
    .then((response) => response.json())
    .then((data) => {
          let html = "";

          data.forEach(function(val) {
              let keys = Object.keys(val);

              html += "<div class = 'cat'>";
                  keys.forEach(function(key) {
                  html += "<strong>" + key + "</strong>: " + val[key] + "<br>";
                  });
              html += "</div><br>";
          });

          document.getElementsByClassName("message")[0].innerHTML=html;
      })
    .catch(error => console.log("ERROR: Failed to get users..."));
}

JS POST Users - Does not Work

function setUsers() {
    const data = new FormData(apiform);
    const value = Object.fromEntries(data.entries());
    console.log(value);

    fetch("../backend/api/user/create.php", {
        method: "POST",
        body: JSON.stringify(value),
        mode: "cors",
        credentials: "same-origin",
        headers: {
           "Content-Type": "application/json"
        }
    })
    .then((response) => {
        if (response.ok) {
            response.json();
        } else {
            throw new Error("Bad Server Response! Response: " + response.status);
        }
    })
    .then((data) => {
        console.log(data);
    })
    .catch((error) => {
        console.error("ERROR: Failed to set users...");
    });

    return false;
}

JS POST Users with XHR - Does not work either, but not using this function and I wanted to show what I tried.

function setUsersWithXHR() {
    const data = new FormData(apiform);
    let xhr = new XMLHttpRequest();

    xhr.open('POST', '../backend/api/user/create.php');
    xhr.send(data);

    xhr.onload = function() {
        if (xhr.status != 200) {
            alert(`Error ${xhr.status}: ${xhr.statusText}`);
        } else {
            alert(`Done, got ${xhr.response.length} bytes`);
            console.log(xhr.response);
        }
    };

    xhr.onprogress = function(event) {
        if (event.lengthComputable) {
            alert(`Received ${event.loaded} of ${event.total} bytes`);
        } else {
            alert(`Received ${event.loaded} bytes`);
        }
    };

    xhr.onerror = function(error) {
        alert("Request failed: " + xhr.readyState);
        console.log("Error: " + error);
    };
}

PHP User class

<?php
    class User {
        private $conn;
        private $table = 'users';
        public $id;
        public $username;
        public $password;
        public $email;

        public function __construct($db) {
            $this->conn = $db;
        }

        public function getAllUsers() {
            $query = 'SELECT * FROM ' . $this->table . ' ORDER BY username ASC;';
            $stmt = $this->conn->prepare($query);
            $stmt->execute();

            return $stmt;
        }

        public function createUser() {
            $query = 'INSERT INTO ' . $this->table . ' SET username = :username, 
                                                           password = :password, 
                                                           email = :email';
            $stmt = $this->conn->prepare($query);

            $this->username = htmlspecialchars(strip_tags($this->username));
            $this->password = htmlspecialchars(strip_tags($this->password));
            $this->email = htmlspecialchars(strip_tags($this->email));

            $stmt->bindParam(':username', $this->username);
            $stmt->bindParam(':password', $this->password);
            $stmt->bindParam(':email', $this->email);

            if ($stmt->execute()) {
                return true;
            } else {
                printf("ERROR: %s.\n", $stmt->error);
                return false;
            }
        }
?>

PHP Create User (AKA create.php. This is what I am calling from the JS side.)

<?php
  header('Access-Control-Allow-Origin: *');
  header('Content-Type: application/json');
  header('Access-Control-Allow-Methods: POST');
  header("Access-Control-Allow-Credentials: true");
  header('Access-Control-Allow-Headers: Access-Control-Allow-Headers,
                                        Access-Control-Allow-Credentials,
                                        Content-Type,
                                        Access-Control-Allow-Methods,
                                        Authorization,
                                        X-Requested-With');

  include_once '../../config/Database.php';
  include_once '../../models/User.php';

  $database = new Database();
  $db = $database->connect();

  $user = new User($db);

  $data = json_decode(file_get_contents("php://input"));

  $user->username = $data->username;
  $user->password = $data->password;
  $user->email = $data->email;

  if($user->createUser()) {
    echo json_encode(
      array('message' => 'User Created')
    );
  } else {
    echo json_encode(
      array('message' => 'User Not Created')
    );
  }
?>
1 Answers

Try to add Content-Type: application/json for header

<?php
$data = array("a" => "Apple", "b" => "Ball", "c" => "Cat");
header("Content-Type: application/json");
echo json_encode($data);

Result will be in JSON as you need :

Related