-3

I have a PHP script that is supposed to save movie IDs to a MySQL database table called "seen_movies". However, the data is not being saved to the table even though the script runs without errors. I've checked that the table has the correct columns and data types, and also checked that the SQL statement is correct. I'm not sure what else to try.

Here's my PHP code:

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Origin: http://localhost:3001');
header('Access-Control-Allow-Origin: http://localhost:3000');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

$servername = "*********";
$username = "******";
$password = "************";
$dbname = "my_movies";

// create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// get selected movie IDs
if (isset($_POST['selectedMovies'])) {
    $selectedMovies = $_POST['selectedMovies'];

    // prepare and bind SQL statement
    $stmt = $conn->prepare("INSERT INTO seen_movies (id) VALUES (?)");
    $stmt->bind_param("i", $movieId);

    // loop through selected movie IDs and execute SQL statement
    foreach ($selectedMovies as $movieId) {
        $stmt->execute();
    }

    // close statement
    $stmt->close();
}

echo json_encode(array('status' => 'success'));

$conn->close();
?>

Response in console in browser:

Saving movies: (2) [315162, 700391]     PopularMovies.js:28
API response: {status: 'success'}       PopularMovies.js:40 

Here is the table layout in mysql

    mysql> DESCRIBE seen_movies
       -> ;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int unsigned | NO   | PRI | NULL    | auto_increment |
| title | varchar(255) | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

I have checked the table data on phpmyadmin and in mysql and the table is empty.

Ive been trying to figure it out for hours, thanks!

Edit :

I looked at the network tab in developer tools to see if the code was interacting with the APi, i can see it listed however the response shows 'failed to load data: no content available for preflight request'

jamesc160
  • 31
  • 4
  • 3
    the table is wrong, it must be `movie_id, user_id`, the title exists already in the database, this table only saves who has seen it – nbk Apr 30 '23 at 10:50
  • Additionally $stmt->bind_param("i... would need to be in the foreach loop just below, I would assume . Otherwise the $movieId variable won't be defined. And yeah you need to put the user ID in there too, otherwise you don't know who has seen it. Title would be redundant in here as that should be already in the movies table – ADyson Apr 30 '23 at 10:51
  • @ADyson binding doesn't need to be in loop. It is bound to the variable name. – user3783243 Apr 30 '23 at 10:53
  • @user3783243 can it really bind to a var which isn't defined yet? Happy to be proved wrong – ADyson Apr 30 '23 at 10:53
  • @ADyson Yes, it binds to the association. `bind_value` would fail (or whatever the mysqli equivalent is). See first example https://www.php.net/manual/en/mysqli-stmt.bind-param.php or for an example like this first user contribution. `param` stays with the variable name, `value` takes the variable value. – user3783243 Apr 30 '23 at 10:55
  • @user3783243 ah because it passes by reference. Makes sense, thanks – ADyson Apr 30 '23 at 10:57
  • @OP in terms of it not showing errors... read https://phpdelusions.net/mysqli/error_reporting and ensure you've got php and mysqli configured to show (or log) all errors – ADyson Apr 30 '23 at 10:57
  • 1
    Put an `else` on `if (isset($_POST['selectedMovies'])) {`, perhaps that POST value isn't coming in. – user3783243 Apr 30 '23 at 10:57
  • Tried all of the above, thanks for the comments but still getting same issue. – jamesc160 Apr 30 '23 at 11:09
  • You'll have to provide some more detailed debugging info then, so we can pinpoint the issue without needing to speculate. Have you started tracing the code behaviour line by line, either with a debugger or some simple logging? Have you checked that the payload being sent in the request from the browser contains what you expect? – ADyson Apr 30 '23 at 11:12
  • P.s if you've really tried all the above, please [edit] your question to show how you're incorporating the suggested changes, then we've got the latest version – ADyson Apr 30 '23 at 11:16

2 Answers2

2

The title field is non-null, meaning you cannot insert a row without including a title:

+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| title | varchar(255) | NO   |     | NULL    |                |

But your SQL is trying to do exactly that:

$stmt = $conn->prepare("INSERT INTO seen_movies (id) VALUES (?)");

There is no error handling in the code so you're not seeing the errors, but the statements are failing.

Don't Panic
  • 13,965
  • 5
  • 32
  • 51
  • thank you for this comment, this seems to be whats causing the issue, would you have a suggestion for a fix? – jamesc160 Apr 30 '23 at 11:58
  • 2
    The fix depends on exactly what you are trying to do, but it looks like you might need to rethink your database design. I guess you have a page which lists your movies, maybe with checkboxes which select the ones you've seen. And I guess the IDs of those checked is what you are POSTing and saving in `seen_movies`. If that is true, why is `title` in this table? You already have movie titles stored in another table (probably `movies`), I guess? – Don't Panic Apr 30 '23 at 12:30
  • 2
    If you remove `title` from this table your code will work. But then you have to ask what is the point of a table storing only a list of IDs from another table? Why not just put a `seen` column in your main `movies` table? How you solve it is up to you and depends on what you are really trying to do. – Don't Panic Apr 30 '23 at 12:30
  • 1
    @jamesc160 you need to enable error logging so that you actually see these errors. And you could fix it trivially by making title nullable in the DB, but actually that's just a sticking plaster. you really ought to address the design flaw mentioned in the main comments. – ADyson Apr 30 '23 at 12:37
  • @Don'tPanic "I guess you have a page which lists your movies, maybe with checkboxes which select the ones you've seen" - This is exactly what im trying to do, a list of movies comes through from TMDB API and i have a tickbox i can select, and finally a save button to save those movies, honestly I am not 100% sure which column i need in mySql, am still learning. I just want to save the movie names or titles so i can call them later to populate a saved movies page. thanks for all your help, I have removed title from the table but it still wont actually save to the table, weird. – jamesc160 Apr 30 '23 at 13:47
  • @ADyson thanks for all your suggestions, im trying to figure out error logging at the moment. – jamesc160 Apr 30 '23 at 13:48
  • @jamesc160 so the list of movies comes from another API, and the movie names are not stored in your database until the user clicks "save" on the form, and triggers the PHP script you've shown us...is that correct? – ADyson Apr 30 '23 at 20:26
  • @ADyson almost, the movies come from tmdb api and each has a tickbox, after the movies have been selected there is a save button intending to save using the php script. its basically an app that saves movies and sadly im still having trouble with it. – jamesc160 Apr 30 '23 at 21:41
  • Ok. Well, to get it to work as it is now you would need to have a way to submit the name of the movie as well as just the ID from your form. If you show us the HTML form it would be easier to advise on that. And I think it would make sense also to store the ID of the user who saved them...otherwise the records for different users will get confused - this is, of course, assuming that your site expects multiple users, and can identify when they have logged in? – ADyson Apr 30 '23 at 22:28
-2

An answer more or less similar to your question was posted here.

But to be short, the binding is executed only once, with the value that is in your variable $movieID at that time. As the variable is not initialized, $stmt becomes a "insert nothing" query, which is totally valid (hence the success), but nothing is inserted into your DB (and this query is executed multiple times.).

Try and modify your code in this way:

    //loop through selected movie IDs and execute SQL statement
    foreach ($selectedMovies as $movieId) {
        $stmt->bind_param("i", $movieId);
        $stmt->execute();
    }

Hope this helps !

Romain46
  • 20
  • 2