Demo of PHP paging script with data from SQLite database by using PDO with dynamic navigation : A7
In Part I, we demonstrate executing a basic SQL query using PDO without parameter binding. The query retrieves data directly from the database, iterating through results using a simple foreach loop, making it an efficient method for straightforward database interactions.
@$start=$_GET['start'];// Collect data from Query string
if(strlen($start) ==0){$start=0;} // if blank then set to 0
if(strlen($start) > 0 and !is_numeric($start)){
echo "Data Error";
exit;
}
Collecting Query Parameter:`@$start=$_GET['start'];` collects the `start` parameter from the query string in the URL. The `@` symbol is used to suppress any errors in case the parameter is not set.
Setting Default Value:`if(strlen($start) == 0){$start=0;}` checks if the `start` value is empty. If so, it sets `$start` to `0` to ensure a default starting point for pagination.
Data Validation:`if(strlen($start) > 0 and !is_numeric($start))` checks if the `start` value is not numeric, displaying a "Data Error" message and stopping further execution using `exit;` to prevent invalid data from being processed.
$steps = 10; // No of records to be shown per page.
$next = $start + $steps; // Starting number of record for Next page
$back = $start - $steps; // Starting number of record for Previous page
$page_name="display-paging.php"; // Pange name for linking
Records per Page:`$steps = 10;` defines the number of records to display per page (10 in this case).
Next Page Calculation:`$next = $start + $steps;` calculates the starting record number for the next page by adding the current start value to the number of records per page.
Previous Page Calculation:`$back = $start - $steps;` calculates the starting record number for the previous page by subtracting the steps from the current start value.
Page Link Setup:`$page_name="display-paging.php";` sets the page URL used in pagination links.
SQL Query with Pagination:`$query=" SELECT * FROM student LIMIT $start, $steps ";` retrieves student records from the database, limited by the starting point (`$start`) and the number of records per page (`$steps`). This implements pagination.
Generating Table: The `foreach` loop iterates through the result set and dynamically generates an HTML table with student details like `id`, `name`, `class`, `mark`, and `gender`.
Displaying Data: Each row of the student table is displayed within the table tags, using HTML `<tr>` and `<td>` elements.
$nume = $my_conn->query("SELECT COUNT(id) FROM student")->fetchColumn();// Total number of records
// Left side navigational link
echo "<table align=center width='50%'><tr><td align='left' width='30%'>";
if($back >=0) {
print "<a href='$page_name?start=$back'>PREVIOUS</a>";
}
// Center navigational link
echo "</td><td align=center width='30%'>";
$i=0;
$l=1;
for($i=0;$i < $nume;$i=$i+$steps){
if($i <>$start){
echo " <a href='$page_name?start=$i'><font size='6'>$l</font></a> ";
}
else { /// Current page is not displayed as link and given font color red
echo "<font size='8' color=red>$l</font>";
}
$l=$l+1;
}
// Right side navigational link
echo "</td><td align='right' width='30%'>";
if($next < $nume) {
print "<a href='$page_name?start=$next'>NEXT</a>";}
echo "</td></tr></table>";
Total Record Count: `$nume = $my_conn->query("SELECT COUNT(id) FROM student")->fetchColumn();` retrieves the total number of student records to determine the number of pagination links needed.
Previous Link: If `$back` is greater than or equal to 0, the "Previous" link is displayed to navigate to the previous set of records.
Center Navigation: A loop creates numbered page links. The current page is highlighted in red without being clickable.
Next Link: If there are more records to show, the "Next" link is displayed for forward navigation.
Full code is here
$my_conn = new PDO('sqlite:my_db.db');
@$start=$_GET['start'];// Collect data from Query string
if(strlen($start) ==0){$start=0;} // if blank then set to 0
if(strlen($start) > 0 and !is_numeric($start)){
echo "Data Error";
exit;
}
$steps = 10; // No of records to be shown per page.
$next = $start + $steps; // Starting number of record for Next page
$back = $start - $steps; // Starting number of record for Previous page
$page_name="display-paging.php"; // Pange name for linking
$query=" SELECT * FROM student LIMIT $start, $steps ";
echo "<table align=center width='50%'>";
foreach ($my_conn->query($query) as $row) {
echo "<tr><td>$row[id]</td><td>$row[name]</td><td>$row[class]</td>
<td>$row[mark]</td><td>$row[gender]</td></tr>";
}
echo "</table>";
// Rows display is over
// Bottom navigation links to different pages part starts
//$nume=$my_conn->querySingle("SELECT count(*) FROM student "); // For SQlite3
$nume = $my_conn->query("SELECT COUNT(id) FROM student")->fetchColumn();// Total number of records
// Left side navigational link
echo "<table align=center width='50%'><tr><td align='left' width='30%'>";
if($back >=0) {
print "<a href='$page_name?start=$back'>PREVIOUS</a>";
}
// Center navigational link
echo "</td><td align=center width='30%'>";
$i=0;
$l=1;
for($i=0;$i < $nume;$i=$i+$steps){
if($i <>$start){
echo " <a href='$page_name?start=$i'><font size='6'>$l</font></a> ";
}
else { /// Current page is not displayed as link and given font color red
echo "<font size='8' color=red>$l</font>";
}
$l=$l+1;
}
// Right side navigational link
echo "</td><td align='right' width='30%'>";
if($next < $nume) {
print "<a href='$page_name?start=$next'>NEXT</a>";}
echo "</td></tr></table>";
$my_conn = null;
Part II : Using Parameterized Query for Data Fetching 🔝
Here we will introduce parameterized queries in SQLite using PDO to securely bind user inputs. This method protects against SQL injection, ensuring that values are treated as data, not executable code, making it ideal for dynamic and secure database operations.
By using prepared statements we have separated the SQL query from the data inputs.
Only the changes are explained but you can copy the full code below.
$query="SELECT * FROM student LIMIT :start, :steps ";//query with place holders
$stmt = $my_conn->prepare($query);
$stmt->bindParam(':start', $start,PDO::PARAM_INT);
$stmt->bindParam(':steps', $steps,PDO::PARAM_INT);
$result=$stmt->execute();
echo "<br><center><table align=center width='50%'>";
//while ($row=$result->fetchArray()) { // for sqlite3
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "<tr ><td>$row[id]</td><td>$row[name]</td>
<td>$row[class]</td><td>$row[mark]</td><td>$row[gender]</td></tr>";
}
echo "</table><br><br>";
Parameterized Query: The query `"SELECT * FROM student LIMIT :start, :steps "` uses placeholders `:start` and `:steps` to safely insert values for pagination. This prevents SQL injection.
Binding Parameters:`bindParam(':start', $start, PDO::PARAM_INT, 3)` and `bindParam(':steps', $steps, PDO::PARAM_INT, 3)` bind the actual values of `$start` and `$steps` to the placeholders, ensuring they are treated as integers.
Executing Query: The prepared statement is executed with `$stmt->execute()` and the data is fetched using `PDO::FETCH_ASSOC`, displaying each student's details inside an HTML table.
Full code using Parameterized Query
$my_conn = new PDO('sqlite:my_db.db');
@$start=$_GET['start'];// Collect data from Query string
if(strlen($start) ==0){$start=0;}
$steps = 10; // No of records to be shown per page.
$next = $start + $steps; // Starting number of record for Next page
$back = $start - $steps; // Starting number of record for Previous page
$page_name="display-paging.php"; // Pange name for linking
$query="SELECT * FROM student LIMIT :start, :steps ";//query with place holders
$stmt = $my_conn->prepare($query);
$stmt->bindParam(':start', $start,PDO::PARAM_INT);
$stmt->bindParam(':steps', $steps,PDO::PARAM_INT);
$result=$stmt->execute();
echo "<br><center><table align=center width='50%'>";
//while ($row=$result->fetchArray()) { // for sqlite3
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "<tr ><td>$row[id]</td><td>$row[name]</td>
<td>$row[class]</td><td>$row[mark]</td><td>$row[gender]</td></tr>";
}
echo "</table><br><br>";
// Total number of records
//$nume=$my_conn->querySingle("SELECT count(*) FROM student "); // For SQlite3
$nume = $my_conn->query("SELECT COUNT(id) FROM student")->fetchColumn();
// Rows display is over
// Bottom navigation links to different pages part starts
// Left side navigational link
echo "<table align=center width='50%'><tr><td align='left' width='30%'>";
if($back >=0) {
print "<a href='$page_name?start=$back'>PREVIOUS</a>";
}
// Center navigational link
echo "</td><td align=center width='30%'>";
$i=0;
$l=1;
for($i=0;$i < $nume;$i=$i+$steps){
if($i <>$start){
echo " <a href='$page_name?start=$i'><font size='6'>$l</font></a> ";
}
else { /// Current page is not displayed as link and given font color red
echo "<font size='8' color=red>$l</font>";
}
$l=$l+1;
}
// Right side navigational link
echo "</td><td align='right' width='30%'>";
if($next < $nume) {
print "<a href='$page_name?start=$next'>NEXT</a>";}
echo "</td></tr></table>";