Jump to content
Larry Ullman's Book Forums

Filter Paginated Results With Checkboxes - Where To Start


Recommended Posts

Hi everyone,

 

I have seen a number of ecommerce and travel websites that include a filtering option, to narrow down the results displayed. For example, a page might display furniture (sofas). On that page will be a number of checkboxes whereby a user can select one or more checkboxes (colour, fabric, style, price etc) and the results will be updated accordingly.

 

Is this very complicated to code? My page would include pagination.

 

Could someone please advise me as to how to proceed with this project?

 

Thank you in advance.

Link to comment
Share on other sites

In essence, each checkbox is just another AND condition in the WHERE clause of your SQL query.

 

For example, let's say we have the following base query to display all sofas:

SELECT * FROM furniture WHERE type = 'sofa';

That query would return all sofas in the database, from which you could then display them all on the screen.

From there, let's say that a user chooses a color of brown to filter the results. In that case, your query would change to the following:

SELECT * FROM furniture WHERE type = 'sofa' AND color = 'brown';

As you can see, it's pretty straightforward to filter results based on user-checked check boxes (or whatever input device you want to use).

Does that all make sense?

  • Upvote 1
Link to comment
Share on other sites

  • 1 month later...

Hi there HartleySan,

 

I'm hoping you could please help me. I did get the checkboxes to work with the pagination script from chapter 10, but there does seem to be a problem. When a checkbox is "checked" the filtered results will load but there are still numbered pagination links to other pages when there shouldn't be any. Perhaps the filter query is being mixed up with the original query (that displays all of the results)?

 

This is from one of my posts a few days ago:

 

 

 

Posted 29 October 2013 - 1:13 PM

Hi Larry,

 

I do need some help after all. I've reached my 'PHP limit' so to speak.

 

What I'm now attempting is to use check boxes to filter the paginated results. The code does work, albeit not completely. When a check box has been checked, the page will load with the desired results but I still have links to subsequent pages when there shouldn't be any. I again added a variable (the filter variable) to the end of the URLs in case there is more than one page. Do you know what the problem could be?

 

Thank you very much.

// Number of records to show per page:
$display =3;

// Determine how many pages there are...
if (isset($_GET['p']) && is_numeric($_GET['p'])) { // Already been determined.
	$pages = $_GET['p'];
	
} else { // Need to determine.
 	// Count the number of records:
	$q = "SELECT COUNT(user_id), other columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age'";
	$r = @mysqli_query ($dbc, $q);
	$row = @mysqli_fetch_array ($r, MYSQLI_NUM);
	$records = $row[0];
	// Calculate the number of pages...
	if ($records > $display) { // More than 1 page.
		$pages = ceil ($records/$display);
	} else {
		$pages = 1;
	}
} // End of p IF.

// Determine where in the database to start returning results...
if (isset($_GET['s']) && is_numeric($_GET['s'])) {
	$start = $_GET['s'];
} else {
	$start = 0;
}



// if a check box has been checked, it is then assigned to the $string variable

if (isset($_POST['city'])) {
$start = 0; // added this here to start filtering from page1	
$string = "name = '{$_POST['city']}'";
}

// if the check box 'all' has been checked, all the records are returned

if (isset($_POST['all'])) { 
$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' LIMIT $start, $display";
}

// if the $string variable is set, then the query will be used with the $string variable, otherwise all the records are returned

if (isset($string)) {

{
$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' && '.$string.' LIMIT $start, $display";
}

else {
$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' LIMIT $start, $display";
}
}
 
      
$r = @mysqli_query($dbc, $q);	
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
 Print '<p>loop content here</p>';
 }
 
// Make the links to other pages, if necessary.
if ($pages > 1) {
	
	echo '<br /><p>';
	$current_page = ($start/$display) + 1;
	
	// If it's not the first page, make a Previous button:
	if ($current_page != 1 && isset($string))  {
		echo '<a href="view_users.php?s=' . ($start - $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'&'.$string.'">Previous</a> ';
	} else {
	echo '<a href="view_users.php?s=' . ($start - $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'">Previous</a> ';	
		
	}
	
		
	// Make all the numbered pages:
	for ($i = 1; $i <= $pages; $i++) {
		if ($i != $current_page && isset($string)) {
			echo '<a  href="view_users.php?s=' . (($display * ($i - 1))) . '&p=' . $pages . '&name='.$name.'&age='.$age.'&'.$string.'">' . $i . '</a> ';
		}
		elseif ($i != $current_page) {
		echo '<a  href="view_users.php?s=' . (($display * ($i - 1))) . '&p=' . $pages . '&name='.$name.'&age='.$age.'">' . $i . '</a> ';
		}
		
		
		else {
			echo $i . ' ';
		}
	} // End of FOR loop.
	
	
	
	// If it's not the last page, make a Next button:
	if ($current_page != $pages && isset($string)) {
		echo '<a  href="view_users.php?s=' . ($start + $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'&'.$string.'">Next</a>';
	} else
	{
		echo '<a  href="view_users.php?s=' . ($start + $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'">Next</a>';
	}
	
	
	
	
	
	echo '</p>'; // Close the paragraph.
	
} // End of links section.
	

I'm really stuck with this and could use some help.

 

 

Thank you for your time!

Link to comment
Share on other sites

Well, you're using a LIMIT clause, which is what you want, but if you're getting more results than you expect, then either the values for the $start and $display variables are not right or your SQL query is wrong.

 

I'd start by echoing out the values of the $start and $display variables to make sure they're what you expect, and if those are okay, then try running static queries on the DB without any variables to ensure that you are indeed getting back what you expect.

 

Please let us know what you find.

Thanks.

  • Upvote 1
Link to comment
Share on other sites

Hi HartleySan,

 

thank you for getting back to me.

 

I've spent hours trying to get the code to work, and its still not working. Once I have checked one of the checkboxes, the page will load with the filtered results, but there are still numbered pagination links when there shouldn't be any. At the moment the original 'unfiltered' query will fetch 10 results (rows). I have set $display =3, which will show 3 results per page for the first 3 pages, and 1 result on the fourth page.  Even if only 2 filtered results are returned on the first page after selecting a checkbox, there will still be links to 3 other pages, with each link having a p=4 at the end of the URL.

 

It appears that selecting a checkbox will display the filtered records on the first page with the records from the original query being shown over the following pages. So there must be some kind of mix up. Perhaps I need to recalculate the number of pages for the filtered results? I don't know – I'm running out of ideas.

 

I think that the start and display variables are okay.

 

 

Thanks again for taking the time to help me.

Link to comment
Share on other sites

I apologize, as I don't have a lot of time to look at your code now, but just taking a brief look, I would guess that the $pages variable is not being properly set.

I would recommend echoing the value of $pages at various points throughout your script, and seeing if you can find out what's going on.

 

Thanks.

Link to comment
Share on other sites

Hi HartleySan,

 


I have added the following code to the code I use if a check box has been checked:

if (isset($string)) {

{
$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' && '.$string.' LIMIT $start, $display";
}
$r = @mysqli_query ($dbc, $q);

	$row = @mysqli_fetch_array ($r, MYSQLI_NUM);


	$records = $row[0];
	
	echo '<p>'.$records.'records</p>';
	echo '</br>';
	echo '<p>display='.$display.'</p>';
	echo '</br>';
	// Calculate the number of pages...
	if ($records > $display) { // More than 1 page.
		$pages = ceil ($records/$display);
		
		echo '<p>'.$pages.'pages</p>';
		echo '</br>';
	} else {
		$pages = 1;
		echo '<p style="color:red">'.$pages.'pages</p>';
	}

echo $q;

}}

I have echoed out the $records, $display and $pages variables to see what is going on. These variables are all correct, but now only 1 record is displayed on the first page, even though $display might be 2 or 3. I added print_r($r); before my while loop begins and what it is telling me is that only 1 row is being returned: [num_rows] => 1. The correct number of rows are returned when using the original 'unfiltered' query.

 

I can understand that you are busy so thank you for your help so far!

 

Larry, if you have a moment, could use please offer some insight?

 

 

 

Thank you.

 

 

 

 

 

 

 

 

 

Link to comment
Share on other sites

Hi HartleySan,

 

the query I posted was for counting the total number of records in order to determine the number of pages. A while loop wasn't necessary, but your advice did remind me that I hadn't actually used a query after determining the number of pages. Now the code returns the correct number of results on the first page, after a check box has been checked. But clicking to the next page loads the wrong results. I have echoed out my queries so I can see that the query on the first page includes the  necessary WHERE...name=$_POST['city'] from the $string variable. However, this condition is missing from the query on the second page.

 

Does the value from the check box “($_POST['city'])” carry over to the other pages? If it doesn't then the $string variable won't be created and the query won't have the extra condition in the WHERE clause. Or maybe there is some other reason....

 

Thank you for your help.

 

 

 

The updated code with the second query:

if (isset($string)) {

{
$q = "SELECT COUNT(user_id), other columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' && '.$string.' LIMIT $start, $display";
}
$r = @mysqli_query ($dbc, $q);

        $row = @mysqli_fetch_array ($r, MYSQLI_NUM);


        $records = $row[0];
        
        echo '<p>'.$records.'records</p>';
        echo '</br>';
        echo '<p>display='.$display.'</p>';
        echo '</br>';
        // Calculate the number of pages...
        if ($records > $display) { // More than 1 page.
                $pages = ceil ($records/$display);
                
                echo '<p>'.$pages.'pages</p>';
                echo '</br>';
        } else {
                $pages = 1;
                echo '<p style="color:red">'.$pages.'pages</p>';
        }


$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' && '.$string.' LIMIT $start, $display";


echo $q;

}}

Link to comment
Share on other sites

No, POST values are not carried over to anchor links by default. That is likely the root of your problem.

Be sure to add an extra parameter with the city data to your anchor URLs so that you can grab that information with the $_GET superglobal. With that, you should be good to go.

Link to comment
Share on other sites

Hello again HartleySan,

 

hope you are well.

 

I have followed your advice, and the correct results are now loading on the second page, which is great. But now the all of the pagination links (previous, next etc) are gone on the second page. So I can't go back to the previous page or forward to the next pages.

 

I'm sure getting sick of this but hopefully there'll be a breakthrough soon, and then other forum members can make use of pagination with check boxes. 

 

 

Sorry for taking up all of your time on this.

 

 

The updated code:

// Number of records to show per page:
$display =3;

// Determine how many pages there are...
if (isset($_GET['p']) && is_numeric($_GET['p'])) { // Already been determined.
        $pages = $_GET['p'];
        
} else { // Need to determine.
        // Count the number of records:
        $q = "SELECT COUNT(user_id), other columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age'";
        $r = @mysqli_query ($dbc, $q);
        $row = @mysqli_fetch_array ($r, MYSQLI_NUM);
        $records = $row[0];
        // Calculate the number of pages...
        if ($records > $display) { // More than 1 page.
                $pages = ceil ($records/$display);
        } else {
                $pages = 1;
        }
} // End of p IF.

// Determine where in the database to start returning results...
if (isset($_GET['s']) && is_numeric($_GET['s'])) {
        $start = $_GET['s'];
} else {
        $start = 0;
}


// if a checkbox has been checked assign its value to the $cityname variable otherwise...
if (isset($_POST['city'])) {
$cityname = $_POST['city'];}
else {
$cityname = filter_input(INPUT_GET, 'cityname', FILTER_SANITIZE_STRING);}



// if the check box 'all' has been checked, all the records are returned

if (isset($_POST['all'])) { 
$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' LIMIT $start, $display";
}



// if the $cityname variable has been set...
 if (isset($cityname)) {

{
$q = "SELECT COUNT(user_id), other columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' && city = '$cityname' LIMIT $start, $display";
}
$r = @mysqli_query ($dbc, $q);

        $row = @mysqli_fetch_array ($r, MYSQLI_NUM);


        $records = $row[0];
        
        echo '<p>'.$records.'records</p>';
        echo '</br>';
        echo '<p>display='.$display.'</p>';
        echo '</br>';
        // Calculate the number of pages...
        if ($records > $display) { // More than 1 page.
                $pages = ceil ($records/$display);
                
                echo '<p>'.$pages.'pages</p>';
                echo '</br>';
        } else {
                $pages = 1;
                echo '<p style="color:red">'.$pages.'pages</p>';
        }


$q = "SELECT columns FROM
table A INNER JOIN table B JOIN_CLAUSE WHERE
name = '$name' && age = '$age' && city = '$cityname' LIMIT $start, $display";


echo $q;

}}






 
      
$r = @mysqli_query($dbc, $q);   
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
 Print '<p>loop content here</p>';
 }
 
// Make the links to other pages, if necessary.
if ($pages > 1) {
        
        echo '<br /><p>';
        $current_page = ($start/$display) + 1;
        
        // If it's not the first page, make a Previous button:
        if ($current_page != 1 && isset($cityname))  {
                echo '<a href="view_users.php?s=' . ($start - $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'&cityname='.$cityname.'">Previous</a> ';
        } else {
        echo '<a href="view_users.php?s=' . ($start - $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'">Previous</a> ';       
                
        }
        
                
        // Make all the numbered pages:
        for ($i = 1; $i <= $pages; $i++) {
                if ($i != $current_page && isset($cityname)) {
                        echo '<a  href="view_users.php?s=' . (($display * ($i - 1))) . '&p=' . $pages . '&name='.$name.'&age='.$age.'&cityname='.$cityname.'">' . $i . '</a> ';
                }
                elseif ($i != $current_page) {
                echo '<a  href="view_users.php?s=' . (($display * ($i - 1))) . '&p=' . $pages . '&name='.$name.'&age='.$age.'">' . $i . '</a> ';
                }
                
                
                else {
                        echo $i . ' ';
                }
        } // End of FOR loop.
        
        
        
        // If it's not the last page, make a Next button:
        if ($current_page != $pages && isset($cityname)) {
                echo '<a  href="view_users.php?s=' . ($start + $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'&cityname='.$cityname.'">Next</a>';
        } else
        {
                echo '<a  href="view_users.php?s=' . ($start + $display) . '&p=' . $pages . '&name='.$name.'&age='.$age.'">Next</a>';
        }
        
        
        
        
        
        echo '</p>'; // Close the paragraph.
        
} // End of links section.

Link to comment
Share on other sites

  • 3 weeks later...

Hi HartleySan,

 

how are you doing?

 

I'm sorry to bother you with this, but I hope you could assist me please.

 

I'm using Javascript/Ajax to send the values of  “checked” checkboxes to a PHP script which uses the pagination script (10.4) from chapter10. The Ajax is correctly updating the query on the first page but there's a problem with the subsequent pages.

 

The query that fetches data from the database ends with variable called “$string”. This variable contains all of the column name – value statements. Depending on the selected checkboxes, the  echoed out $string variable might be hobby = 'fishing' && income = 'average'. The problem arises when I click a numbered pagination link to go to the next page. The page will load the records from the original query and not those that have been filtered via the checkboxes. I'm thinking that I need to transfer the $string variable to the other pages, so I tried appending it to the URL: &string=$string. Then I could retrieve it and assign it's contents to the original $string variable in the query.

 

I tried something like the following:

$newString = filter_input(INPUT_GET, 'string', FILTER_SANITIZE_STRING);
$string = $newString;

I have spent hours on this and am getting nowhere. If you have any idea what I could then please let me know.

 

Thank you very much.

<form method="post" action="" id="checkform">
<input type="checkbox" name="hobby[]"  value="fishing">fishing
<input type="checkbox" name="hobby[]" value="bowling"> bowling
<input type="checkbox" name="income[]" value="average">average
<input type="checkbox" name="income[]" value="high">high
<input type="submit" value="select">
</form> 



$arguments ='';
if (isset($_POST['hobby'])){
foreach ($_POST['hobby'] as $k) {
	      $arguments[] .= "hobby='$k'";
	}
        }
if (isset($_POST['income'])){        
foreach ($_POST['income'] as $a) {
	      $arguments[] .= "income='$a'";
	}        
}
if(!empty($arguments)) {
  $string = implode(' && ',$arguments);
}



// Make all the numbered pages:
	for ($i = 1; $i <= $pages2; $i++) {
		if ($i != $current_page2 && isset($string)) {
echo '<a  href="mypage.php?s2=' . (($display2 * ($i - 1))) . '&p2=' . $pages2 . '&string=$string">' . $i . '</a> ';
		}
		else {
			echo $i . ' ';
		}
	} // End of FOR loop.

<script type="text/javascript">
       $('#checkform').on('click', 'input', function(){
        var checkedBoxes = $(this).val();

        $.ajax({
          type: "POST",
          url: // some url
          cache: false,
          data: 'hobby[]=' + checkedBoxes,
          success: function(response){
            $('#someid').html(response);
          }
        });
      })
</script>


Link to comment
Share on other sites

Hi everyone,

 

could someone please tell me how I can identify form inputs with jQuery code?

 

My form has checkboxes with different name inputs. Presently I'm able to receive the value of the currently selected checkbox with this code:

var checkedBoxes = $(this).val();

This I then use in the Ajax data setting:

data: 'hobby[]=' + checkedBoxes,

But I need to process the checkboxes with the other names as well.

 

 

Thank you very much in advance!

 

 

 

 

Herewith the code:

 

The form:

<form method="post" action="" id="checkform">
<input type="checkbox" name="hobby[]"  value="fishing">fishing
<input type="checkbox" name="hobby[]" value="bowling"> bowling
<input type="checkbox" name="income[]" value="average">average
<input type="checkbox" name="income[]" value="high">high
<input type="submit" value="select">
</form> 

The JavaScript:

<script type="text/javascript">
       $('#checkform').on('click', 'input', function(){
        var checkedBoxes = $(this).val();

        $.ajax({
          type: "POST",
          url: // some url
          cache: false,
          data: 'hobby[]=' + checkedBoxes,
          success: function(response){
            $('#someid').html(response);
          }
        });
      })
</script>

The PHP:

$arguments ='';
if (isset($_POST['hobby'])){
foreach ($_POST['hobby'] as $k) {
	      $arguments[] .= "hobby='$k'";
	}
        }
if (isset($_POST['income'])){        
foreach ($_POST['income'] as $a) {
	      $arguments[] .= "income='$a'";
	}        
}
if(!empty($arguments)) {
  $string = implode(' && ',$arguments);
}
Link to comment
Share on other sites

Hi everyone,

 

I am unfortunately still stuck with combining pagination with checkboxes.

 

After clicking a checkbox, the page will load with the results. Depending on the number of records there might be one or more pagination links. Now if I click on, say, the 3rd pagination link, page 3 will load. So far so good. Now I click another checkbox -  the page will load but the current pagination number will still be 3. In other words, the pagination number continues from the previous results instead of starting from page 1.

 

 

If I'm not mistaken, the problem lies with the $start variable. When a checkbox has been selected for the second time, $_GET['s'] will already be set and so $start will begin with that number. I need some code that says if $_GET['s'] has a value, and this is followed by setting a checkbox value, then $start = 0;. Or whatever else might work.

 

 

Could someone please help me?

 

 

Thank you.

 

 

$string contains the value from the checkboxes, together with a column name (e.g., name='amy').

if (isset($string)) {




// Determine where in the database to start returning results...
if (isset($_GET['s']) && is_numeric($_GET['s'])) {
	$start = $_GET['s'];
} else {
	$start = 0;
}
Link to comment
Share on other sites

Hi HartleySan,

 

I have tried that before and it did work - now it doesn't. I have posted the code below. If you have a moment could you please look it over?

 

 

Thank you very much!

if (isset($string)) {
    
// Number of records to show per page:
$display2 =1;
// Determine how many pages there are...
if (isset($_GET['p2']) && is_numeric($_GET['p2'])) { // Already been determined.
	$pages2 = $_GET['p2'];	}
	
else {    
$q = "SELECT COUNT(user_id), ... WHERE $string ";

	$r = @mysqli_query ($dbc, $q);
	$row = @mysqli_fetch_array ($r, MYSQLI_NUM);
	$records2 = $row[0];
    
	// Calculate the number of pages...
	if ($records2 > $display2) { // More than 1 page.
		$pages2 = ceil ($records2/$display2);
		} else {
		$pages2 = 1;
			}
}

// Determine where in the database to start returning results...
if (isset($_GET['s2']) && is_numeric($_GET['s2'])) {
	$start2 = $_GET['s2'];
} else {
	$start2 = 0;
}


$q = "SELECT * FROM... WHERE... $string LIMIT $start2, $display2";
$r = @mysqli_query($dbc, $q);
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
Print'     loop content here      ';
}

// Make the links to other pages, if necessary.
if (isset ($pages2, $start2, $display2)) {
  
if ($pages2 > 1) {
	
	echo '<br /><p id="pagination">';
	$current_page2 = ($start2/$display2) + 1;
	
	// If it's not the first page, make a Previous button:
	if ($current_page2 != 1)  {
		echo '<a href="test.php?s2=' . ($start2 - $display2) . '&p2=' . $pages2 . '&'.$string.'">Previous</a> ';
	} 

	
	// Make all the numbered pages:
	for ($i = 1; $i <= $pages2; $i++) {
		if ($i != $current_page2) {
			
			echo '<a  href="test.php?s2=' . (($display2 * ($i - 1))) . '&p2=' . $pages2 . '&'.$string.'">' . $i . '</a> ';
		}
		else {
			echo $i . ' ';
		}
	} // End of FOR loop.
	
	// If it's not the last page, make a Next button:
	if ($current_page2 != $pages2) {
		
		echo '<a  href="test.php?s2=' . ($start2 + $display2) . '&p2=' . $pages2 . '&'.$string.'">Next</a>';
	} 	
	
	echo '</p>'; // Close the paragraph.
	
} // End of links section.
}	



}
else {
// normal pagination code here

Link to comment
Share on other sites

Where is $string comming from? You can't treat a variable like $string equal to $_GET['string'] og $_POST['string']. It won't exist unless you actively initiate it above your if statements.

$string = "someting"

if ( isset($string) ) { echo "Awesome"; } // Yeah!

By the looks of it, your code will immediately go to the else statement and execute from there. Make sure your indention is correct, though, because it's really hard to scan your code without proper indentation. 

 

My first thought is to add echo statements to your code an see what's running and what's left out. Deploy that tactic, and you'll get a better sense of what's really happening. I'm also betting on that Jon will post a better response soon. Seems like he's been following the thread more closely than me.

 

Good luck. :)

Link to comment
Share on other sites

Hi Antonio,

 

thanks for helping. I did post the origins of the $string variable in an earlier post. The contents of the $string variable are created when one or more checkboxes are selected.

 

 

I have tried various things but to no avail. It must have something to do with how $start2 is set.

$arguments ='';
if (isset($_POST['hobby'])){
foreach ($_POST['hobby'] as $k) {
	      $arguments[] .= "hobby='$k'";
	}
        }
if (isset($_POST['income'])){        
foreach ($_POST['income'] as $a) {
	      $arguments[] .= "income='$a'";
	}        
}
if(!empty($arguments)) {
  $string = implode(' && ',$arguments);
}
Link to comment
Share on other sites

 Share

×
×
  • Create New...