Q:

PHP Session Issue with Javascript Fetch

Keeping it simple, I have two pages namely index.php and fav.php
Here's the code for index.php 
<?php session_start();
var_dump($_SESSION);
if(!isset($_SESSION['fave'])) {
   $_SESSION['fave'] = [];
}
 ?>

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <p><?php

      echo join(", ", $_SESSION['fave']); ?>
</p>

    <div id="blog-post-101" class="blog-post">
      <h3>Blog Post 101</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      </p>
      <button class="favorite-button">Favourite</button>
    </div>

        <div id="blog-post-102" class="blog-post">
          <h3>Blog Post 102</h3>
          <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
          </p>
          <button class="favorite-button">Favourite</button>
        </div>

            <div id="blog-post-103" class="blog-post">
              <h3>Blog Post 103</h3>
              <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
              </p>
              <button class="favorite-button">Favourite</button>
            </div>

                <div id="blog-post-104" class="blog-post">
                  <h3>Blog Post 104</h3>
                  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                  </p>
                  <button class="favorite-button">Favourite</button>
                </div>

    <script type="text/javascript">
    function favourite() {

      let parent = this.parentElement;
      let json_upload = "id=" + parent.id;
      fetch('fav.php', {
        method:"POST",
        headers: {
          "Content-type":"application/x-www-form-urlencoded",
          "X-REQUESTED-WITH" : "XMLHttpRequest"
        },
        body: json_upload })
      .then(response => response.text() )
    .then(data => console.log(data));
    }
    const ajaxButton = document.querySelectorAll('.favorite-button');
    ajaxButton.forEach(e => e.addEventListener('click', favourite));
    </script>
  </body>
</html>

Here's the code for fav.php
<?php session_start();
if(!isset($_SESSION['fave'])) { $_SESSION['fave'] = []; }

        function is_ajax_request() {
        if(isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest") {
           return true;
         }
        }

        if(!is_ajax_request()) { exit(); }

        $raw_id = isset($_POST['id']) ? $_POST['id'] : '';

        if(preg_match("/blog-post-(\d+)/", $raw_id , $matches)) {
          $id = $matches[1];

          if(!in_array($id, $_SESSION['fave'])) {
            $_SESSION['fave'][] = $id;
          }
             echo join(", ", $_SESSION['fave']);
        } else {
          echo "false";
        }

 ?>

Basically the Javascript code uses Fetch to make AJAX call from index.php to fav.php where each div id is provided from index.php via Javascript this.parentElement; 
In a nutshell, the raw_id is transferred from index.php to fav.php and there I use preg to trim to required id in numeric form. That works too. But for some very odd reason, it is not putting in to session. If I console.log in javascript function this echo join(", ", $_SESSION['fave']);
then it does log the id, but then on refreshing the page no session is being displayed, as I've used join to show up session. As well as nothing in var_dump of session as well.
I've used session in other projects. It's working there. But for some reason, it is not working here. Very strange. I've been trying since last 4 hours! whew!

A:

I've had a very similar problem on my own project, I think it might be the same. The issue for me was that the new fetch API does not send nor accept cookies unless you explicitly tell it to (unlike the older XMLHttpRequest). So, when you call fetch(), make sure you pass the necessary options:
fetch('fav.php', { credentials: 'same-origin' })

More details here: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

