Reputation: 15
I am currently trying to make a page of a TV series. Somehow the page only shows one row for seasons
, which are 5 in my database.
$sql = "SELECT * FROM `shows` WHERE url='".dburl($_GET["url"])."'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
// General info about the TV show here
$sql = "SELECT * FROM seasons WHERE `show`='".$row["id"]."' ORDER BY number ASC";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($seasons = $result->fetch_assoc()) {
// The seasons
$sql= "SELECT * FROM episodes WHERE `show`='".$row["id"]."' AND `season`='".$seasons["number"]."' ORDER BY number DESC";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($episodes = $result->fetch_assoc()) {
// The episodes, sorted by season
}
}
}
}
}
}
Is there any change I overlooked something? The episodes
part works just perfectly fine, it shows all the episodes that are in a season.
Upvotes: 1
Views: 1379
Reputation: 3842
I suggest you to get all the data in one mysql query, use proper variable escaping and the code will be simpler and more readable than the one you got. Then maybe you are gonna make fewer mistakes but having better coding:
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_db");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$sql = "SELECT * FROM `shows` sh
JOIN `seasons` se.show ON sh.id
JOIN `episodes` e ON e.show = se.id AND e.season = e.number
WHERE url=?
ORDER BY se.number, e.number";
/* Prepare statement */
$stmt = $conn->prepare($sql);
if($stmt === false) {
trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->errno . ' ' .$conn->error, E_USER_ERROR);
}
/* Bind parameters. Types: s = string, i = integer, d = double, b = blob */
$stmt->bind_param('s', dburl($_GET["url"]));
/* Execute statement */
$stmt->execute();
/* Fetch result to array */
$res = $stmt->get_result();
while($row = $res->fetch_array(MYSQLI_ASSOC)) {
array_push($a_data, $row);
}
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
Justification or explanation:
Never concatenate or interpolate data in SQL
Never build up a string of SQL that includes user data, either by concatenation:
$sql = "SELECT * FROM users WHERE username = '" . $username . "';";
or interpolation, which is essentially the same:
$sql = "SELECT * FROM users WHERE username = '$username';";
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc. Using prepared statements and bound parameters is a much better solution. PHP's mysqli and PDO functionality includes this feature (see below).
From OWASP: PHP Security Sheet
Upvotes: 1
Reputation: 311018
You are overwriting the $result
variable used by the outer loop. Just use a new variable:
$sql = "SELECT * FROM seasons WHERE `show`='".$row["id"]."' ORDER BY number ASC";
$seasons_result = $conn->query($sql);
if ($seasons_result->num_rows > 0) {
while($seasons = $seasons_result->fetch_assoc()) {
Upvotes: 1