I am trying to create a PDO database results page with a previous and next for the previous 10 or next 10 records. I just can't figure out what should go in the 4 ????? areas below. I have tried several different approaches with all sorts of incorrect results. Any ideas on the missing pieces to make this work?
$results = $dbh->prepare("select
stories.SID,
stories.story_name,
stories.category,
stories.genre
FROM stories
WHERE stories.category = :cat OR stories.genre = :gen LIMIT 10");
$results->bindParam(':cat', $scategory, PDO::PARAM_STR);
$results->bindParam(':gen', $sgenre, PDO::PARAM_STR);
$results->execute();
$row = $results->fetchAll(PDO::FETCH_ASSOC);
}
if ($row) {
echo '<table>';
echo '<tr>';
foreach ($row as $all) {
echo '<tr>';
echo "<td>$all[story_name]
</td>";
echo "<td>$all[category]</td>";
echo "<td>$all[genre]</td>";
}
echo '</table>';
}
//get all results from PDO SQL query and pass to previous & next links
$id = $row;
$stmt_a = $pdo->prepare("
(SELECT * FROM stories WHERE ???? ORDER BY id DESC LIMIT 1)
UNION (SELECT * FROM stories WHERE id = (SELECT MAX(id) FROM stories)) LIMIT
1 prev_id");
$stmt_b = $pdo->prepare("
(SELECT * FROM stories WHERE ????? ORDER BY id ASC LIMIT 1)
UNION (SELECT * FROM stories WHERE id = (SELECT MIN(id) FROM stories)) LIMIT
1 next_id");
// $vars = array(':id' => $id);
$prev = $stmt_a->execute();
$next = $stmt_b->execute();
if ($prev) {
while($row = $stmt_a->fetchObject()) {
echo 'Previous';
}
} else {
echo 'no previous';
}
if ($next) {
while($row = $stmt_b->fetchObject()) {
echo 'Next';
}
} else {
echo 'no next';
}
Here is a blog that discusses many aspects of what you are doing:
http://mysql.rjweb.org/doc.php/pagination
It also shows how to do "pagination" in a scalable way.
Related
So I am working on a project where I have a database filled with questions/options. Each question has 3 options (1 of them is right).
Before a user starts a quiz he selects how many questions he wants to have. I do this with a select form. PHP then sends value from select form to the quiz page. Where it's used in SQL query:
SELECT *
FROM quiz_question
WHERE quiz_id = 1
ORDER BY RAND()
LIMIT $number
The $number stands for value of select form
I can display questions but not options for the selected question.
My code:
<div id="quiz">
<?php
$number = $_POST['number'];
$sql = "SELECT *
FROM quiz_question
WHERE quiz_id = 1
ORDER BY RAND()
LIMIT $number";
$result = mysqli_query($conn,$sql);
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
echo "<p>";
echo $row['question'];
echo "</p>";
}
}
?>
</div>
My database looks something like this:
quiz
id (PK)
quiz_name (text)
quiz_question
id (PK)
quiz_id (FK)
question (text)
quiz_question_option
id (PK)
quiz_question_id (FK)
quiz_option (text)
is_correct (enum 0, 1)
EDIT:
I tried to use INNER JOIN but when I used ORDER BY RAND() and LIMIT I couldn't get all 3 options for a single question.
Just put aside SQL injection issue (you should use prepared statement), here is how you can use a secondary query to get all the options of the quiz for rendering.
<div id="quiz">
<?php
// aggregate an array of options
$option_results = mysqli_query($conn, "SELECT qo.* FROM quiz_question_option qo
LEFT JOIN quiz_question q ON (qo.quiz_question_id = q.id)
WHERE q.quiz_id = 1");
$options = [];
while ($option = mysqli_fetch_assoc($option_results)) {
$options[$option['quiz_question_id']] = $option;
}
mysqli_free_result($option_results);
$number = $_POST['number'];
$sql = "SELECT * FROM quiz_question WHERE quiz_id = 1 ORDER BY RAND() LIMIT $number";
$result = mysqli_query($conn,$sql);
if (mysqli_num_rows($result) > 0)
{
while ($question = mysqli_fetch_assoc($result)) {
echo "<p>";
echo $question['question'];
echo "</p>";
}
if (isset($options[$question['id']])) {
echo "<ul>";
foreach ($options[$question['id']] as $option) {
echo $option['quiz_option'];
}
echo "</ul>";
}
}
?>
</div>
Now, to convert to prepared statements:
<div id="quiz">
<?php
$number = $_POST['number'] ?? 10000;
$quiz_id = 1;
// aggregate an array of all questions' options of a quiz
$option_stmts = mysqli_prepare($conn, "SELECT qo.* FROM quiz_question_option qo
LEFT JOIN quiz_question q ON (qo.quiz_question_id = q.id)
WHERE q.quiz_id = ?");
$option_stmts->bind_param('i', $quiz_id);
$option_results = $option_stmts->execute();
$options = [];
while ($option = mysqli_fetch_assoc($option_results)) {
$options[$option['quiz_question_id']] = $option;
}
mysqli_free_result($option_results);
mysqli_stmt_close($option_stmts);
// query for all the questions of a quiz
$stmt = mysqli_prepare($conn, "SELECT * FROM quiz_question WHERE quiz_id = ? ORDER BY RAND() LIMIT ?");
$stmt->bind_param('ii', $quiz_id, $number);
$result = $stmt->execute();
if (mysqli_num_rows($result) > 0)
{
while ($question = mysqli_fetch_assoc($result)) {
echo "<p>";
echo $question['question'];
echo "</p>";
}
if (isset($options[$question['id']])) {
echo "<ul>";
foreach ($options[$question['id']] as $option) {
echo $option['quiz_option'];
}
echo "</ul>";
}
}
?>
</div>
I am wanting to count the id field in my users table in my current query and output that. How can I change my query or my output, so that if there are 40 id's in my user table with the same WHERE conditions apply, that I can output it with a variable?
$member = mysqli_query($con,"SELECT * FROM users WHERE `group` IN (2, 3, 4, 5) ORDER BY id DESC LIMIT 1");
$numrows_member = mysqli_num_rows($member);
if($numrows_member > 0){
while($row_member = mysqli_fetch_assoc($member)){
$memberid = $row_member['id'];
$member_username = $row_member['username'];
}
} else {
$no_members = "No Members Found...";
}
Try this code :
Warning : also rename group column because group is reserve keyword of mysql database in example i renamed it as groupid.
<?php
$member = mysqli_query($con,"SELECT * FROM users WHERE `groupid` IN (2, 3, 4, 5) ORDER BY id DESC LIMIT 1");
$numrows_member = mysqli_num_rows($member);
if($numrows_member > 0){
$totalRecord=null;
while($row_member = mysqli_fetch_assoc($member)){
$memberid = $row_member['id'];
$member_username = $row_member['username'];
$group_id = intval($row_member['groupid']);
if($group_id > 0){
$totalRecord = getTotalRow($con,$group_id);
}
}
echo 'ID : '.$memberid.' UserName : '.$member_username. ' Total records : '.$totalRecord;
} else {
echo $no_members = "No Members Found...";
}
function getTotalRow($con,$id){
$record=0;
$result = mysqli_query($con,"SELECT count(id) as total FROM users WHERE groupid = $id ");
while($row = mysqli_fetch_row($result)){
echo $record = $row[0];
}
return $record;
}
?>
I was working on a post system..
So, I have to show posts by friends of the user and the groups in which user has participated..
Here is my code to show posts..
<?php
$sql = "SELECT * FROM posts WHERE uploader_id=:friend_id ORDER BY id DESC";
$query = $db->prepare($sql);
$query->execute(array(
":friend_id" => $friend_id
));
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$name = $row['name'];
echo "POST BY $name";
}
$sql = "SELECT * FROM group_posts WHERE id=:member_group ORDER BY id DESC";
$query = $db->prepare($sql);
$query->execute(array(
":member_group" => $group_id
));
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$name = $row['name'];
echo "POST BY $name";
}
?>
Now, I want all these posts to be shuffled in a way that all the posts of the post table and group_posts table are shown in the descending order.
UPDATE
I edited my code to this..
I figured out that first I'll have to code this before coding my post system..
<?php
$sql = "SELECT * FROM friends WHERE user_one=:me OR user_two=:me2 UNION SELECT * FROM group_members WHERE member_id=:me3";
$query = $db->prepare($sql);
$query->execute(array(
":me" => $my_id,
":me2" => $my_id,
":me3" => $my_id
));
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$user_one = $row['user_one'];
$user_two = $row['user_two'];
$group_id = $row['group_id'];
if ($user_one == $my_id) {
$friend_id = $user_two;
} else {
$friend_id = $user_one;
}
echo $friend_id . "<BR>" . $group_id;
}
?>
Now, here's the problem..
This is successfully printing the $friend_id but, it shows an undefined index 'group_id' while printing $group_id.
I have checked all the fields are correct.
Try using just one query with UNION
SELECT *
FROM (
SELECT name, id FROM posts WHERE uploader_id=:friend_id
UNION
SELECT name, id FROM group_posts WHERE id=:member_group
) p
ORDER BY p.id DESC
Note, your inner queries must return the same number of columns in the same order (and I think with the same name/alias, too).
I'm trying to order a list of items based on the amount of comments for each topic as shown below:
$page = $_GET['page'];
$query = mysql_query("SELECT * FROM topic WHERE cat_id='$page' LIMIT $start, $per_page");
if (mysql_num_rows($query)>=1)
{
while($rows = mysql_fetch_array($query))
{
$number = $rows['topic_id'];
$title = $rows['topic_title'];
$description = $rows['topic_description'];
//get topic total
$sqlcomment = mysql_query("SELECT * FROM comments WHERE topic_id='$number'");
$commentnumber = mysql_num_rows($sqlcomment);
// TRYING TO ORDER OUTPUT ECHO BY TOPIC TOTAL ASC OR DESC
echo "
<ul>
<li><h4>$number. $title</h4>
<p>$description</p>
<p>$topictime</p>
<p>$commentnumber</p>
</li>
</ul>
";
}
}
else
{
echo "<p>no records available.</p><br>";
}
What would be the best way to order each echo by $num_rows (ASC/DESC values)? NOTE: I've updated with the full code - I am trying to order the output by $commentnumber
The first query should be:
SELECT t.*, COUNT(c.topic_id) AS count
FROM topic AS t
LEFT JOIN comments AS c ON c.topic_id = t.topic_id
WHERE t.cat_id = '$page'
GROUP BY t.topic_id
ORDER BY count
LIMIT $start, $per_page
You can get $commentnumber with:
$commentnumber = $rows['count'];
You don't need the second query at all.
First of all you have error here
echo "divs in order from least to greatest "number = $num_rows"";
It should be
echo "divs in order from least to greatest number = " . $num_rows . "";
And about the most commented try with
$sql = "SELECT * FROM `table` WHERE `id` = '$id' ORDER BY column DESC/ASC";
Or if there is not count column try with
$sql = "SELECT * FROM `table` WHERE `id` = '$id' ORDER BY COUNT(column) DESC/ASC";
i've got some bad sytax in my query where i'm trying to create 'prev_id' to pull into the $row result link. any ideas on a better way of doing this?
edit: the error is "Check the manual that corresponds to your MySQL server version for the right syntax to use near 'prev_id'."
function traversePhoto($the_selected_id) {
global $pdo;
$id = $the_selected_id;
$stmt_a = $pdo->prepare("
(SELECT * FROM images WHERE id < '.intval($id).' ORDER BY id DESC LIMIT 1)
UNION (SELECT * FROM images WHERE id = (SELECT MAX(id) FROM images)) LIMIT 1 prev_id");
$stmt_b = $pdo->prepare("
(SELECT * FROM images WHERE id > '.intval($id).' ORDER BY id ASC LIMIT 1)
UNION (SELECT * FROM images WHERE id = (SELECT MIN(id) FROM images)) LIMIT 1 next_id");
// $vars = array(':id' => $id);
$prev = $stmt_a->execute();
$next = $stmt_b->execute();
if ($prev) {
while($row = $stmt_a->fetchObject()) {
echo 'Previous';
}
} else {
echo 'no previous';
}
if ($next) {
while($row = $stmt_b->fetchObject()) {
echo 'Next';
}
} else {
echo 'no next';
}
}
Try it like this
<?php function traversePhoto($the_selected_id) {
global $pdo;
$id = $the_selected_id;
$stmt_a = $pdo->prepare("
(SELECT * FROM images WHERE id < ? ORDER BY id DESC LIMIT 1)
UNION (SELECT * FROM images WHERE id = (SELECT MAX(id) FROM images)) LIMIT 1");
$stmt_b = $pdo->prepare("
(SELECT * FROM images WHERE id > ? ORDER BY id ASC LIMIT 1)
UNION (SELECT * FROM images WHERE id = (SELECT MIN(id) FROM images)) LIMIT 1");
// $vars = array(':id' => $id);
$prev = $stmt_a->execute(array( (int)$id ));
$next = $stmt_b->execute(array( (int)$id ));
if ($stmt_a->rowCount() > 0) {
while($row = $stmt_a->fetch(PDO::FETCH_ASSOC)) {
echo 'Previous';
}
} else {
echo 'no previous';
}
if ($stmt_b->rowCount() > 0) {
while($row = $stmt_b->fetch(PDO::FETCH_ASSOC)) {
echo 'Next';
}
} else {
echo 'no next';
}