2

I have this program where a user inputs a message and name in a form. Then the program saves this information in a json file. The entries in the json file are then output in a table.

Everything works as I want it to except for when I add a new entry in the table. When I click the submit button the table gets updated with an empty entry. If I then update the page the table gets input with the right values.

I've looked at the file the json objects are saved to and the form data is sent correctly. From my point of view it seems like the table gets updated before get program reads the new entry. However, I don't really understand why since it's the local array $tempArray that the foreach loops through and this array gets updated with the new entry when the submit is performed.

<?php
//open & read php file
$json = file_get_contents("../../../writeable/test2.json");
$tempArray = json_decode($json);

//get form values
if(isset($_POST['submit'])) {
    $name = $_POST['name'];
    $text = $_POST['text'];
    $date = date("m-d-Y h:i", time());
    //create new json object
    $new_post = array(
        'name' => $name,
        'text' => $text,
        'date' => $date,
        'ip' => $_SERVER['REMOTE_ADDR']
    );
    //add new json object to array
    $tempArray[] = $new_post;
    print_r($tempArray);
}

//encode array into json & save to file
$my_json = json_encode($tempArray);
$fh = fopen("../../../writeable/test2.json", 'wd') or die("can't open file");
fwrite($fh, $my_json);
fclose($fh);

?>

<!DOCTYPE html>
<html lang="sv-SE">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css"/>
    <title>DT161G-Laboration1</title>
</head>
<body>
  <table id="guestbook">
          <?php
                    foreach ($tempArray as $obj) { //loop through array with posts
                        echo '<tr>';
                        echo '<td>' . $obj->name . '</td>';
                        echo '<td>' . $obj->text . '</td>';
                        echo '<td>' . 'IP: ' . $obj->ip . '</br>TID: ' . $obj->date . '</td>';
                        echo '</tr>';
                    }
                ?>
  </table>
 <form action="guestbook.php" method="POST">
            <input type="text" placeholder="Write your name"
                   name="name">
            <br>
            <label for="text">Your message</label>
            <textarea id="text" name="text"
                      rows="10" cols="50"
                      placeholder="Message .."></textarea>
            <br>
            <button type="submit" name ="submit">Send</button>
    </form>
</body>
M. H
  • 339
  • 2
  • 6
  • 17
  • 1
    can you post the output of this line? `print_r($tempArray);` – Haris Feb 02 '19 at 20:51
  • @Haris Sure. From anywhere in the code or somewhere specific? – M. H Feb 02 '19 at 20:55
  • on form submission @M.H – Haris Feb 02 '19 at 20:56
  • @Haris Array ( [0] => stdClass Object ( [name] => TestName [text] => Testing message [date] => 02-02-2019 09:29 [ip] => 1.1.1.1 ) [1] => Array ( [name] => Name [text] => Message [date] => 02-02-2019 09:57 [ip] => 1.1.1.1 ) ) – M. H Feb 02 '19 at 20:59
  • (Except on production system) you should turn on full error messages and install xdebug and an IDE with debugging capabilities. This kind of debugging is easily done with the appropriate tools. – Pinke Helga Feb 02 '19 at 21:12
  • BTW.: What is your URL? I'ld like to infect your site with some crypto miner javascript malware. ;-) Whenever outputting user data to HTML clients, use `htmlspecialchars()`. Look for *XSS* in the search engine of your choice. – Pinke Helga Feb 02 '19 at 21:32

3 Answers3

3

JavaScript does not have associative arrays. Thus such PHP arrays are converted into objects. You are reading objects from the JSON file but appending an associative array.

In the loop all works fine except with the latest added array. $obj->name cannot access the array element $obj['name'].

Handle with an object by changing your code into

$new_post = (object)[
  'name' => $name,
  'text' => $text,
  'date' => $date,
  'ip'   => $_SERVER['REMOTE_ADDR'],
];
Pinke Helga
  • 6,378
  • 2
  • 22
  • 42
2

From my point of view it seems like the table gets updated before get program reads the new entry.

NO!

  1. The problem you are facing is because that when you get json-data from the file and decode it using json_decode you have array of objects and if the form is submitted you insert an array to the array of objects.

    $new_post = array( 'name' => $name, 'text' => $text, 'date' => $date, 'ip' => $_SERVER['REMOTE_ADDR'] ); //add new json object to array $tempArray[] = $new_post;

  2. Then in your loop you're accessing elements as objects e.g $obj->name;

Easiest Solution

The simplest solution is to type-cast your $new_post array into an object like:

$new_post =(object) array(
    'name' => $name,
    'text' => $text,
    'date' => $date,
    'ip' => $_SERVER['REMOTE_ADDR']
);

You can read more about casting Here

Haris
  • 764
  • 4
  • 9
  • 27
1

The thing is json_decode($json) returns PHP's standard class object which is stdClass. In the if block, you're appending the $tempArray object with the array literal. To fix it, you can simply pass in the second argument true to json_decode.

$tempArray = json_decode($json, true);

This returns an associative array, so that you can append the new array to $tempArray. You can also typecast the array to object as said in the other answers.

By the way, you're loading the JSON data even before the new data is added to the file and also you're trying to add data even if the form is not submitted. But actually, you're re-adding the existing data again when the form is not submitted. Here is the changes I made to your code.

<?php

//open & read php file
$json = file_get_contents("../../../writeable/test2.json");
$tempArray = json_decode($json, true);

//get form values
if(isset($_POST['submit'])) {
    $name = $_POST['name'];
    $text = $_POST['text'];
    $date = date("m-d-Y h:i", time());
    //create new json object
    $new_post = array(
        'name' => $name,
        'text' => $text,
        'date' => $date,
        'ip' => $_SERVER['REMOTE_ADDR']
    );
    //add new json object to array
    $tempArray[] = $new_post;
    print_r($tempArray);

    //encode array into json & save to file
    $my_json = json_encode($tempArray);
    $fh = fopen("../../../writeable/test2.json", 'wd') or die("can't open file");
    fwrite($fh, $my_json);
    fclose($fh);
}

//open & read php file
$json = file_get_contents("../../../writeable/test2.json");
$tempArray = json_decode($json);

?>
Wolverine
  • 1,712
  • 1
  • 15
  • 18