-1

I'd like to read MySQL in Amazon server and send the result to my Unity program. The PHP source in PHP5 worked in another server and I copied the source onto Amazon server in PHP7.

However, everytime I run this program, I get this error saying 'PHP Parse error: syntax error, unexpected end of file in ... line no. 51'. Line no 51 is the end of source.

I am new to PHP. I've been googling for days and tried to find out what the problem is. But I couldn't find any.

Can anyone help me out? Any advice will be appreciated. My source is here...

<?php
$servername = 'localhost';
$username = 'root';
$password = '********';
$dbname = 'mysqldb';

$connect = mysqli_connect($servername, $username, $password, $dbname);
if ($connect == 0) {
    echo "SORRY SCORE SERVER CONNECTION ERROR";
} else {}

mysqli_select_db($connect, $dbname);

$User_Id2 = $_POST["User_Id"];
$User_Id = $User_Id2 + 0;

$sql = "select * from Users where User_Id = '".$User_Id."'";
$result = mysqli_query($connect, $sql);

$rows = array();
$return = array();
while($row = mysqli_fetch_array($result)) {
    $rows['User_Id'] = $row['User_Id'];
    $rows['Dia_Qty'] = $row['Dia_Qty'];
    $rows['Fighter_Info'] = $row['Fighter_Info'];
    $rows['InvBonus'] = $row['InvBonus'];

    array_push($return, $rows);
}

header("Content-type:application/json");
echo json_encode($return);

mysqli_close($connect);
?>
VERONICA
  • 11
  • 1
  • 1

2 Answers2

0

Your code runs fine on my server using PHP 7.0.22, so i think it has to be a PHP configuration error on your AWS Server, have you tried to run a simple script like phpinfo()?

Also for security reasons its better to do not add the php ending tag more info here:

Why would one omit the close tag?

Chico3001
  • 1,853
  • 1
  • 22
  • 43
  • I've run phpinfo() and it worked. How can I check my PHP configuration? – VERONICA Feb 08 '18 at 05:21
  • If phpinfo is working then your configuration is fine, so the other only problem i can think of is the file encoding, if you are using windows it usually encodes in ANSI and Linix encodes in UTF8, check that your script uses the same encoding as your server (usually UTF8) – Chico3001 Feb 08 '18 at 05:55
  • I am using Mac. So it's supposed to be UFT-8. I see. I will check it. Should I mention UTF-8 in my PHP program? – VERONICA Feb 08 '18 at 06:20
  • No its not necessary, have you run @Alive to Die code on your AWS server? if his code runs the only thing i can think of is an encoding problem, and maybe is an ilegal character or an invisible character, try to delete the last lines and retype them – Chico3001 Feb 08 '18 at 06:35
  • Have you read this thread? https://stackoverflow.com/questions/18050071/php-parse-syntax-errors-and-how-to-solve-them – Chico3001 Feb 08 '18 at 06:40
  • Now, no syntax errors. I still don't get the right results yet. But thanks for your help.^^ – VERONICA Feb 08 '18 at 06:52
0

It seems that your ajax (I suppose there is one because of $_POST variables) is pretty picky regarding errors :-)

Please note that I don't know if and how you make the ajax request. So I will refer myself to an ajax request inside a script tag in a html page.

First problem:

If you are outputing with json_encode, e.g. supposedly send data to an ajax request callback ("succes", "error", etc), then you must provide an exit(); statement right after json_encode, in order to stop the execution of further statements. That was probably the cause of your initial error: the lack of an exit statement before mysqli_close($connect);. Which you don't need, actually, because php closes each connection after it finishes a script processing (like getUsers.php). Also, you don't need the ?> tag, as @Chico3001 correctly said.

Second problem:

Your code still throws a notice, because of the if ($connect == 0) statement:

Notice: Object of class mysqli could not be converted to int in /getUsers.php on line 9

For proper error handling (including db connection failure) see this and this. Below I give an example too.

Third problem (depends on the 2nd one :):

A warning is raised, right after the notice.

Warning: Cannot modify header information - headers already sent by (output started at /getUsers.php:9) in /getUsers.php on line 32

This is thrown because the previous notice was printed on screen - at least in my tests.

You could have seen these errors if you would have made something like this in your ajax request code:

$.ajax({
    //...
    error: function (jqXHR, textStatus, errorThrown) {
        $('#messages').html(jqXHR.responseText);
    }
});

So:

Solution 1 (recommended): Remove the if ($connect == 0) statement and proceed with the links that I provided (regarding correct error/exception handling in PHP). See example below.

Solution 2: Replace

if ($connect == 0) {
    echo "SORRY SCORE SERVER CONNECTION ERROR";
} else {}

with

if (!$connect) {
    echo json_encode("SORRY SCORE SERVER CONNECTION ERROR");
    exit();
}

Also, I don't think the header(...) is necessary in your case. I am not sure because I don't know Unity.


Suggestions and code:

Please note that in my example all system-caused errors/exceptions (like db connection failure, failure in preparing/execution of the sql statements, etc) will be visible only in the log files. To be seen only by the developers, not by the users of the website. As it should be. The users should never see errors like "Sorry, connection failed". The errors which are supposed to be shown to the users (like "Please provide a user id", "No user found for the provided user id", etc) should be directly echo-ed, or thrown & handled in "specific" try-catch blocks (like I did in getUsers.php).

Now, because I throw and catch exceptions (as I did in getUsers.php twice, e.g. with two try-catch blocks), the echo'ed messages will be automatically sent to the "error" function of the jquery.ajax(), not to the "success" function. You could achieve exactly the same functionality if you would use header 401 and echo - instead of the first try-catch block, for example - like this:

if (!isset($_POST['userId']) || empty($_POST['userId'])) {
    header('HTTP/1.1 401 Unauthorized');
    echo 'Please provide the user ID.';
    exit();
}

Or, instead of the 2nd try-catch block:

if (!$users) {
    header('HTTP/1.1 404 No Content');
    echo 'No users found for the provided user id.';
    exit();
}

Same thing: the message would be sent to the "error" function of jquery.ajax(). The point is: any response header (see this and this) which is sent from the server to the client (e.g. browser) with a status code other than 2xx makes the ajax request to call the "error" callback - not the "success" one. In the code above the header sends a 401, or 404 code, e.g. different from 2xx (200, etc).

So, you can choose either to use try-catch blocks (like I did in getUsers.php below), or header-echo pairs as above (also in getUsers.php, but commented).

I tested on Apache web server + PHP 7 + MySQL 5.7 + jQuery 3.2.1 + HTML 5.

Good luck.

A code example:

index.php

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo</title>

        <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>

        <script type="text/javascript">
            $(document).ready(function () {
                $('#submit').click(function (event) {
                    $('#messages').empty();
                    $('#results').empty();

                    $.ajax({
                        method: 'post',
                        dataType: 'json',
                        url: 'getUsers.php',
                        data: {
                            'userId': $('#userId').val()
                        },
                        success: function (response, textStatus, jqXHR) {
                            $.each(response, function (key, user) {
                                var result = 'User_Id: ' + user.User_Id + ', ';
                                result += 'Dia_Qty: ' + user.Dia_Qty + ', ';
                                result += 'Fighter_Info: ' + user.Fighter_Info + ', ';
                                result += 'InvBonus: ' + user.InvBonus;

                                $('#results').append(result);
                            });
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            $('#messages').html(jqXHR.responseText);
                        },
                        complete: function (jqXHR, textStatus) {
                            //...
                        }
                    });
                });
            });
        </script>

        <style type="text/css">
            body {
                padding: 30px;
            }

            button {
                padding: 5px 10px;
                background-color: #8daf15;
                color: #fff;
                border: none;
            }

            #messages {
                color: #c00;
                margin-bottom: 15px;
            }

            #results {
                margin-top: 20px;
            }
        </style>
    </head>
    <body>

        <div id="messages">
            Here come the success, or error messages...
        </div>

        <div class="form-container">
            <label for="userId">User ID</label>
            <input type="text" id="userId" name="userId" value="2">

            <button type="button" id="submit" name="submit" value="submit">
                Submit
            </button>
        </div>

        <div id="results">
            Here comes the fetched data...
        </div>

    </body>
</html>

getUsers.php:

<?php

include 'handlers.php';
include 'db.php';

// Validate the posted values.

// Like this:
try { // If an exception is thrown, then it will be handled by the "error" callback of jquery.ajax().
    if (!isset($_POST['userId']) || empty($_POST['userId'])) {
        throw new InvalidArgumentException('Please provide the user ID.');
    }

    // Here other validations...
} catch (InvalidArgumentException $exc) {
    /*
     * If you want you can use a header to specify a certain status code (here 401), which can be 
     * read in the ajax call for further customizations. I think the second parameter ("textStatus") 
     * of the "error" callback of jquery.ajax() is the one displaying it.
     * 
     * Notice that no json_encode() is needed. The same applies to the error/exception handlers in 
     * "handlers.php". So, no json_encode() in their echo's, as well. Why? Because in the "error"
     * callback the "responseText" property is used to display the error, not the "responseJSON".
     */
    // header('HTTP/1.1 401 Unauthorized');
    echo $exc->getMessage();
    exit();
}

//**********************************************************
// ... or like this instead:
//if (!isset($_POST['userId']) || empty($_POST['userId'])) {
//    header('HTTP/1.1 401 Unauthorized');
//    echo 'Please provide the user ID.';
//    exit();
//}
//**********************************************************

$userId = $_POST['userId'];

/*
 * The SQL statement to be prepared. Notice the so-called markers, 
 * e.g. the "?" signs. They will be replaced later with the 
 * corresponding values when using mysqli_stmt::bind_param.
 * 
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$sql = 'SELECT * 
        FROM Users 
        WHERE User_Id = ?';

/*
 * Prepare the SQL statement for execution - ONLY ONCE.
 * 
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$statement = $connection->prepare($sql);

/*
 * Bind variables for the parameter markers (?) in the 
 * SQL statement that was passed to prepare(). The first 
 * argument of bind_param() is a string that contains one 
 * or more characters which specify the types for the 
 * corresponding bind variables.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.bind-param.php
 */
$statement->bind_param('i', $userId);

/*
 * Execute the prepared SQL statement.
 * When executed any parameter markers which exist will 
 * automatically be replaced with the appropriate data.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.execute.php
 */
$statement->execute();

/*
 * Get the result set from the prepared statement.
 * 
 * NOTA BENE:
 * Available only with mysqlnd ("MySQL Native Driver")! If this 
 * is not installed, then uncomment "extension=php_mysqli_mysqlnd.dll" in 
 * PHP config file (php.ini) and restart web server (I assume Apache) and 
 * mysql service. Or use the following functions instead:
 * mysqli_stmt::store_result + mysqli_stmt::bind_result + mysqli_stmt::fetch.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.get-result.php
 * @link https://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result
 */
$result = $statement->get_result();

/*
 * Fetch data and save it into $fetchedData array.
 * 
 * @link http://php.net/manual/en/mysqli-result.fetch-all.php
 */
// Fetch all rows at once...
$users = $result->fetch_all(MYSQLI_ASSOC);

// ... OR fetch one row at a time.
// $users = [];
// while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
//     $users[] = $row;
// }

/*
 * Free the memory associated with the result. You should 
 * always free your result when it is not needed anymore.
 * 
 * @link http://php.net/manual/en/mysqli-result.free.php
 */
$result->close();

/*
 * Close the prepared statement. It also deallocates the statement handle.
 * If the statement has pending or unread results, it cancels them 
 * so that the next query can be executed.
 * 
 * @link http://php.net/manual/en/mysqli-stmt.close.php
 */
$statement->close();

/*
 * Close the previously opened database connection.
 * 
 * @link http://php.net/manual/en/mysqli.close.php
 */
$connection->close();

// If no users found (e.g. $users is empty) display a message.

// Like this:
try {
    if (!$users) {
        throw new UnexpectedValueException('No users found for the provided user id.');
    }
} catch (UnexpectedValueException $exc) {
    echo $exc->getMessage();
    exit();
}

//****************************************************
// ... or like this instead:
//if (!$users) {
//    header('HTTP/1.1 404 No Content');
//    echo 'No users found for the provided user id.';
//    exit();
//}
//****************************************************

echo json_encode($users);
exit();

db.php:

<?php

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'root');
define('PASSWORD', 'root');

/*
 * Enable internal report functions. This enables the exception handling, 
 * e.g. mysqli will not throw PHP warnings anymore, but mysqli exceptions 
 * (mysqli_sql_exception).
 * 
 * MYSQLI_REPORT_ERROR: Report errors from mysqli function calls.
 * MYSQLI_REPORT_STRICT: Throw a mysqli_sql_exception for errors instead of warnings. 
 * 
 * @link http://php.net/manual/en/class.mysqli-driver.php
 * @link http://php.net/manual/en/mysqli-driver.report-mode.php
 * @link http://php.net/manual/en/mysqli.constants.php
 */
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

/*
 * Create a new db connection.
 * 
 * @see http://php.net/manual/en/mysqli.construct.php
 */
$connection = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);

handlers.php:

<?php

/**
 * Error handler.
 * 
 * @link http://php.net/manual/en/function.set-error-handler.php set_error_handler.
 * @param int $errno
 * @param string $errstr
 * @param string $errfile
 * @param int $errline
 */
function errorHandler($errno, $errstr, $errfile, $errline) {
    // Print a user-friendly message or show a custom error page.
    echo 'An error occurred during your request. Please try again or contact us.';

    // Log the error.
    error_log('Error ' . $errno . ' - ' . $errstr . ' in file ' . $errfile . ' on line ' . $errline);

    exit();
}

/**
 * Exception handler.
 * 
 * @link http://php.net/manual/en/function.set-exception-handler.php set_exception_handler.
 * @param Exception $exception
 */
function exceptionHandler($exception) {
    // Print a user-friendly message or show a custom error page.
    echo 'An error occurred during your request. Please try again or contact us.';

    // Log the exception.
    error_log('Exception ' . $exception->getCode() . ' - ' . $exception->getMessage() . ' in file ' . $exception->getFile() . ' on line ' . $exception->getLine());

    exit();
}

// Set the handlers.
set_error_handler('errorHandler');
set_exception_handler('exceptionHandler');
  • Thanks for your detailed explanations. As a beginner, it seems a little beyond my abilities for now. I will try your codes fitting my case. :) – VERONICA Feb 08 '18 at 07:09
  • @VERONICA You are welcome. Don't worry, it is not so hard. Copy/paste my `db.php` content into a php page of your own and include it in all the php pages that need a db connection. Like me. Then copy/paste my `handlers.php` content into a php page of your own and include it in all your php pages. In that moment you will not need to handle any errors yourself anymore. You will just need to look into the php log file for reading the errors, because those two functions in your `handlers.php` handled them already. E.g. they displayed a general user-friendly message to the user and ... –  Feb 08 '18 at 07:32
  • @VERONICA ... wrote the real error messages into the php log. The only hard task remaining is the `getUsers.php`. Actually, it has just a [prepared statements part](https://phpdelusions.net/mysqli) (which you should start applying anyway, as soon as possible, and is good commented by me, I hope :) and the validation of the submitted user id, e.g. of `$_POST['userId']`. That is easy too, if you read [this](https://code.tutsplus.com/tutorials/php-exceptions--net-22274), for example. –  Feb 08 '18 at 07:38
  • @VERONICA And notice that I applied the *object oriented mysqli*, not your *procedural styled mysqli*. In the official php docs they both are presented. You should try to use the object oriented form from now on... And, of course, to read and try to understand what I have done, in general, in my example... Have a nice day. P.S: Oh, and don't worry about so many code lines: most of them are just my comments. Delete them and you'll remain with only 10 lines :-)) –  Feb 08 '18 at 07:46