I am trying to create Pagination using PHP, trying to show 5 records per page. Everything works just fine but when I click Pagination links to go to the next page it show an error message.
Access forbidden!
You don't have permission to access the requested object. It is either
read-protected or not readable by the server.
If you think this is a server error, please contact the webmaster.
Error 403
localhost Apache/2.4.25 (Win32) OpenSSL/1.0.2j PHP/5.6.30
Here is my code.
<?php
define("SPP", 5);
if(isset($_GET['groupname']) && isset($_GET['uniname'])) {
/* VARS */
$xpage = 0;
$content = null;
$totalProfile;
$totalPage = 0;
if(isset($_GET['xpage'])) { $xpage = $_GET['xpage']; }
$start = $xpage*SPP;
$end = $start+SPP;
include("protected/config.php");
include("protected/class.db.php");
include("protected/publicLang.php");
$newSearch = new DB();
$newSearch->query("SELECT username, university,bgroup, (SELECT COUNT(id) FROM donors) AS totalProfile FROM donors WHERE bgroup = :bgroup LIMIT " . $start . ", " . $end . " ");
$newSearch->exec(array(
":bgroup" => $_GET['groupname']
));
$data = $newSearch->fetch();
foreach($data as $row) {
$totalProfile = $row['totalProfile'];
$content .= '
<tr>
<td>' . $row['username'] . '</td>
<td>'.$row['university'].'</td>
<td>' . convertBloodIdPublic($row['bgroup']) . '</td>
<td><button class="btn btn-success">Contact</button></td>
</tr> ';
}
$totalPage = round($totalProfile/SPP); }
?>
<div class="container records">
<table>
<tr>
<th>--</th>
<th>--</th>
<th>--</th>
<th>--</th>
</tr>
<?php echo $content ?>
</table>
<ul class="pagination">
<?php
for($i=1; $i<=$totalPage; $i++) {
echo '<li>' . $i . '</li>';}
?>
</ul>
403 indicates you are no longer authorized. You probably need to pass some authentication information, this is usually done by POSTING to the URL instead of GET ting it as you are now doing via a bare hyperlink/ element.
I think if you change your code to
<a href="javascript:submit_pagination($i);" >
and add a HIDDEN input element to the encompassing form and add some javascript along the lines
function submit_pagination(i){
document.forms[0].xpage.value = i;
document.forms[0].submit();
}
I think it might work. Hope it helps!
Related
I am currently working on an invoice script which currently pulls the information from MySql and then converts that information into a PDF and emails it using PHPmailer.
The part im stuck with is how I would convert this into a PDF. I would like to be able to post the orderid to a following page which then does the conversion to PDF.
I have attached my script below for some help.
<?php
session_start();
$username = $_SESSION['username'];
$con = mysqli_connect('***', '***', '***', '***');
if (!isset($con)) {
die("Connection to Aurora System failed.");
}
$orderid = $_POST['order_id'];
?>
<!doctype html>
<html>
<body class="body page-orderview clearfix">
<div class="element"></div>
<p class="text text-1">SMKD Field Force</p>
<img class="image" src="images/smkd_logo.png">
<p class="text text-2">Welcome</p>
<p class="text text-3">Order <?php echo "$orderid"; ?>
<table>
<tr>
<th>Product Title</th>
<th>Nicotine Strength</th>
<th>Quantity</th>
<th>Price (inc. VAT)</th>
</tr>
<?php
$query = "SELECT `product`, `variant`, `quantity` FROM orders_detail WHERE order_id = '$orderid'";
$result = mysqli_query($con, $query);
$quantitytotal = 0;
$quantityline = - 0;
while ($row = mysqli_fetch_assoc($result)) {
$product = $row['product'];
$stuff = $row['quantity'];
$variant = $row['variant'];
$linequantity = $stuff;
$quantitytotal += $stuff;
$pricequery = "SELECT product_price FROM products WHERE product_name = '$product'";
$priceresult = mysqli_query($con, $pricequery);
$pricetag = 0;
$priceline = 0;
while ($rowprice = mysqli_fetch_assoc($priceresult)) {
$price = $rowprice['product_price'];
$pricetag += $price;
$priceline = $price;
}
$linetotal = $priceline * $linequantity;
echo '<tr><td>' . $product .' </td> ' . '<td>' . $variant . '</td>' . ' <td> ' . $linequantity . '</td>' . '<td> £' . $linetotal . '</td> </tr>';
}
$total = $pricetag * $quantitytotal;
?>
<tr><td>Total Ex Vat:</td><td> Total Inc Vat:</td></tr>
<tr><td><?php echo "£" . ($total / 1.2);?></td>
<td><?php echo "£" . $total; ?></td></tr>
</table>
</p><br>
<form method="post" action"pdfinvoice.php">
<input type="hidden" value="<?php echo $orderid; ?>" name="orderid">
</form>
Submit button goes here
</body>
</html>
I wouuld not object to converting the entire page to a PDF but from what I understand this isn't possible with FPDF.
Regards & Many thanks!
As long as you don't make it too complex in regard to styling and html elements, I suggest taking a look at https://github.com/dompdf/dompdf, it's a pretty powerfull HTML to PDF converter library and is supports quite a lot of HTML.
Just forms and the like aren't going to work inside of the pdf, so don't include those (they may or may not be rendered, depends on the exact html tag.)
I actually just completed the same task a couple weeks ago. My page doesn't display the pdf however. Upon completion of checkout the page displays a success message and emails the pdf to the user.
Once you download and include the the FPDF library in your php file. Its just a matter of creating the FPDF object, adding to it, and outputting it.
require "Resources/PDF/fpdf.php";
$pdf = new FPDF();
$pdf->SetAutoPageBreak(true, 0);
$pdf->SetLeftMargin(8);
$pdf->AddPage();
$pdf->SetFont('Arial','B',20);
$pdf->SetTextColor(255);
$pdf->SetFillColor(0,153,204);
$pdf->Cell(194,10,'MyCompany Inc.','LRT',0,'L', true);
$pdf->Ln();
$pdf->SetFont('Arial','I',12);
$pdf->Cell(97,10,'Invoice #: '.$id.''.$cnt.'','LB',0,'L', true);
$pdf->Cell(97,10, "Date: ".date("d-m-Y")." ",'RB',0,'R', true);
$pdf->Ln();
$pdf->SetTextColor(0,153,204);
$pdf->SetFont('Arial','B',14);
$pdf->Cell(40,10,'Ship to:',0,4);
$pdf->SetTextColor(0,0,0);
$pdf->SetFont('Arial','I',12);
$pdf->Cell(40,5, $_POST['shippingName'],0,5);
$pdf->Cell(40,5, $COMP,0,6);
$pdf->Cell(40,5, $EMAIL,0,6);
$pdf->Cell(40,5, $_POST['shippingPhoneNumber'],0,7);
$pdf->Cell(40,5, $_POST['shippingAddress'],0,8);
$pdf->Cell(40,5, $_POST['shippingPostalCode'],0,9);
$pdf->Cell(40,5, $_POST['shippingCity'],0,10);
$pdf->Cell(40,5, $_POST['shippingProvince'],0,11);
$pdf->Cell(40,5, $_POST['shippingCountry'],0,12);
$pdf->Output(); //should display the pdf to the page
Output("filepath"); can save pdf to directory where you could then email the file.
The above will create a header and list User's info passed in through $_POST variables.
The FPDF documentation can be helpful at times. http://www.fpdf.org/
I am trying to create a small instagram app in PHP only (no database) and without getting an access_token (just my client_id). So far so good, (i.e. input user_id returns photos from last 30 days, with likes-count and created_time, in a table), until I get to pagination. As expected, I want to hit a 'more' button which loads next json file and adds additional photos to the existing table, but it falls apart there... Here is what I've got, working, except for the pagination attempt.
NOTE: this is an internal app, so the sensitivity of my client_id is not an issue, if it is exposed
<?php
if (!empty($_GET['user_id'])){
$user_id = ($_GET['user_id']);
$instagram_url = 'https://api.instagram.com/v1/users/' . $user_id . '/media/recent/?client_id=MY_CLIENT_ID';
$instagram_json = file_get_contents($instagram_url);
$instagram_array = json_decode($instagram_json, true);
}
?>
...
<?php
if(!empty($instagram_array)){
$instagram_array['pagination'] as $page { // Attempt at pagination
echo '<p>' .$page['next_url'].'</p>'; // Attempt at pagination
} // Attempt at pagination
foreach($instagram_array['data'] as $image){
if ($image['created_time'] > strtotime('-30 days')) {
echo '<tr>';
echo '<td>' . date('M d, Y', $image['created_time']) . '</td>';
echo '<td>'.$image['likes']['count'].'</td>';
echo '<td><img src="'.$image['images']['standard_resolution']['url'].'" alt=""/ style="max-height:40px"></td>';
echo '</tr>';
}
}
}
?>
</body>
</html>
Note: this is cobbled together from a few other sources - I am a total noob, so please forgive me if I need a little hand-holding...:)
You may specify min_timestamp to return medias which taken later than this timestamp
https://api.instagram.com/v1/users/{user_id}/media/recent/?access_token={access_token}&min_timestamp={min_timestamp}
$instagram_array['pagination']['next_url'] should be removed, it may include your access token which is a sensible data, that must be always invisible.
list_ig.php
<?
$user_id = "...";
$access_token = "...";
//30 day ago
$min_timestamp = strtotime("-30 day",time());
//pagination feature
$next_max_id = $_GET['next_max_id'];
$instagram_url = "https://api.instagram.com/v1/users/" . $user_id . "/media/recent/?access_token=" .$access_token. "&min_timestamp=" . $min_timestamp;
if($next_max_id != "")
$instagram_url .= "&max_id=" . $next_max_id;
$instagram_json = file_get_contents($instagram_url);
$instagram_array = json_decode($instagram_json ,true);
?>
<? if( $instagram_array['pagination']['next_max_id'] != "" ): ?>
More
<? endif;?>
.... print instagram data....
Instagram AJAX Demo
http://jsfiddle.net/ajhtLgzc/
I'am trying to implement a modal that shows always different information. This depends on the name you click. At this moment he always shows the modal of the latest link.
Here I'm printing out the different information. For each line i want a specific modal
PHP
foreach ($badgesNotifications as $notifications) {
echo "<p>Congratulations! You've earned the <a href='#' data-reveal-id='myModal'>" . $notifications['challenge_badge_title'] ." badge</a></p>";
echo "<div id='myModal' class='reveal-modal' data-reveal>
<h2>" . $notifications['challenge_title'] . "</h2>
<p class='lead'>Your couch. It is mine.</p>
<p>" . $notifications['challenge_description'] . " </p>
<a class='close-reveal-modal'>×</a>
</div>";
}
?>
I tried to replace 'myModal' with $notifications['challenge_badge_title'] in the link and the id of the mail but then he isn't opening the modal.
The title is always different so I thought he would open an other window. The id don't have to be necessary "MyModal" because it's working with other words to.
I also tried to put the data in different arrays because they are overwriting each other. But also that won't fix my problem.
public function BadgeNotifications($user_id)
{
$db = new Db();
$select = "SELECT
c.challenge_id,
c.challenge_title,
c.challenge_target,
c.challenge_description,
c.challenge_badge_img,
c.challenge_badge_title,
p.challenge_id,
p.user_id,
p.challenge_progress
FROM (tblchallenges c INNER JOIN tblchallenges_progress p ON c.challenge_id = p.challenge_id) WHERE p.user_id = " . $user_id . " ";
$result = $db->conn->query($select);
$result_count = mysqli_num_rows($result);
$result_array = array();
for($i = 0; $i < $result_count; $i++)
{
$result_data = mysqli_fetch_assoc($result);
$result_array[$i]["challenge_id"] = $result_data["challenge_id"];
$result_array[$i]["challenge_title"] = $result_data["challenge_title"];
$result_array[$i]["challenge_description"] = $result_data["challenge_description"];
$result_array[$i]["challenge_badge_title"] = $result_data["challenge_badge_title"];
}
return $result_array;
}
It looks like there's an error here with your code:
echo "<div id='myModal' class='reveal-modal' data-reveal>";
You should perhaps give each modal a unique ID. Properly written Javascript applications fall over when ID's are used more than once as the CSS/JS specification says that you may only use an ID once.
My solution below introduces an iterator $i which you can use to make each echoed element unique.
You will notice that the modal ID now has a number at the end of it, (myModal0, myModal1, etc.).
foreach ($badgesNotifications as $i => $notifications)
{
echo "<p>Congratulations! You've earned the <a href='#' data-reveal-id='myModa" . $i . "l'>" . $notifications['challenge_badge_title'] ." badge</a></p>";
echo "<div id='myModal" . $i . "' class='reveal-modal' data-reveal>
<h2>" . $notifications['challenge_title'] . "</h2>
<p class='lead'>Your couch. It is mine.</p>
<p>" . $notifications['challenge_description'] . " </p>
<a class='close-reveal-modal'>×</a>
</div>";
}
?>
So I'm working on my very first ever attempt at pagination (using simple Previous and Next buttons) on a for-fun project that I've undertaken. Below is all of the relevant code for my pagination system - I have left out the before and after, but I assure you that the table structure is valid.
Here is the jQuery I'm using with the elements I'm using to call the script:
<ul class="pager">
<li class="previous">< Previous</li>
<li class="next">Next ></li>
</ul>
<script>
$(document).ready(function() {
var page = 1;
$(".pagination-page").hide();
$(".pagination-page tbody[id=page" + page + "]").show();
$('#pagination-prev').click(function() {
page = page - 1;
$(".pagination-page").hide();
$(".pagination-page tbody[id=page" + page + "]").show();
});
$('#pagination-next').click(function() {
page = page + 1;
$(".pagination-page").hide();
$(".pagination-page tbody[id=page" + page + "]").show();
});
});
</script>
When I viewed the page without the jQuery active, I saw 8 <tbody> elements filled with dummy data that had been properly classed and id'd by the PHP script. My issue is that when I view the page with the script active, it doesn't seem to be working out for me. It hides all .pagination-page elements as I want, but my output has nothing toggled to show. Below is the PHP that is generating the content that I am flipping through.
<?php
try {
$listed = $dbc->query("SELECT data1,data2,data3,data4 FROM `table` ORDER BY data3 DESC")->fetchAll(PDO::FETCH_BOTH);
$annPP = 15;
$totalRows = count($listed);
$lastPCount = $totalRows % $annPP;
$totalPages = ceil($totalRows/$annPP);
$place = 0;
for ($i=1;$i<=$totalPages;$i++) {
echo "<tbody class='pagination-page' id='page{$i}'>";
if ($i == $totalPages) {
// Only do the remaining rows
$pageMax = $place + $lastPCount;
} else {
// Do 15 rows
$pageMax = $i * 15;
}
for ($j=$place;$j<$pageMax;$j=$place) {
$row = $listed[$j];
echo "<tr>
<td style='width: 25%'>";
if ($isAdmin) {
echo '<label class="control-label"><input type="checkbox" name="delete[]" value="' . $row['0'] . '"> ';
}
echo "<a href='view.php?id={$row[0]}'>{$row[1]}</a>";
if ($isAdmin) {
echo '</label>';
}
echo "</td>
<td style='width: 60%'>{$row[2]}</td>
<td class='text-center' style='width: 15%'>";
$created = new DateTime($row[3]);
echo $created->format('Y/m/d') . "</td>
</tr>";
$place++;
}
echo "</tbody>";
}
}
?>
What did I miss? What's going on? Thanks!
Removing the .pagination-page to make my jQuery read as follows:
$("tbody[id='page" + page + "']").show;
Fixed the problem. Not quite sure I understand why this is, though.
I am having trouble with modifying a php application to have pagination. My error seems to be with my logic, and I am not clear exactly what I am doing incorrectly. I have had before, but am not currently getting errors that mysql_num_rows() not valid result resource
and that invalid arguments were supplied to foreach. I think there is a problem in my logic which is stopping the results from mysql from being returned.
All my "test" echos are output except testing while loop. A page is generated with the name of the query and the word auctions, and first and previous links, but not the next and last links. I would be grateful if a more efficient way of generating links for the rows in my table could be pointed out, instead of making a link per cell. Is it possible to have a continuous link for several items?
<?php
if (isset($_GET["cmd"]))
$cmd = $_GET["cmd"]; else
die("You should have a 'cmd' parameter in your URL");
$query ='';
if (isset($_GET["query"])) {
$query = $_GET["query"];
}
if (isset($_GET["pg"]))
{
$pg = $_GET["pg"];
}
else $pg = 1;
$con = mysql_connect("localhost","user","password");
echo "test connection<p>";
if(!$con) {
die('Connection failed because of' .mysql_error());
}
mysql_query('SET NAMES utf8');
mysql_select_db("database",$con);
if($cmd=="GetRecordSet"){
echo "test in loop<p>";
$table = 'SaleS';
$page_rows = 10;
$max = 'limit ' .($pg - 1) * $page_rows .',' .$page_rows;
$rows = getRowsByProductSearch($query, $table, $max);
echo "test after query<p>";
$numRows = mysql_num_rows($rows);
$last = ceil($rows/$page_rows);
if ($pg < 1) {
$pg = 1;
} elseif ($pg > $last) {
$pg = $last;
}
echo 'html stuff <p>';
foreach ($rows as $row) {
echo "test foreach <p>";
$pk = $row['Product_NO'];
echo '<tr>' . "\n";
echo '<td>'.$row['USERNAME'].'</td>' . "\n";
echo '<td>'.$row['shortDate'].'</td>' . "\n";
echo '<td>'.$row['Product_NAME'].'</td>' . "\n";
echo '</tr>' . "\n";
}
if ($pg == 1) {
} else {
echo " <a href='{$_SERVER['PHP_SELF']}?pg=1'> <<-First</a> ";
echo " ";
$previous = $pg-1;
echo " <a href='{$_SERVER['PHP_SELF']}?pg=$previous'> <-Previous</a> ";
}
echo "---------------------------";
if ($pg == $last) {
} else {
$next = $pg+1;
echo " <a href='{$_SERVER['PHP_SELF']}?pg=$next'>Next -></a> ";
echo " ";
echo " <a href='{$_SERVER['PHP_SELF']}?pg=$last'>Last ->></a> ";
}
echo "</table>\n";
}
echo "</div>";
function getRowsByProductSearch($searchString, $table, $max) {
$searchString = mysql_real_escape_string($searchString);
$result = mysql_query("SELECT Product_NO, USERNAME, ACCESSSTARTS, Product_NAME, date_format(mycolumn, '%d %m %Y') as shortDate FROM {$table} WHERE upper(Product_NAME) LIKE '%" . $searchString . "%'" . $max);
if($result === false) {
echo mysql_error();
}
$rows = array();
while($row = mysql_fetch_assoc($result)) {
echo "test while <p>";
$rows[] = $row;
}
return $rows;
mysql_free_result($result);
}
edit: I have printed out the mysql error of which there was none. However 8 "test whiles" are printed out, from a database with over 100 records. The foreach loop is never entereded, and I am unsure why.
The problem (or at least one of them) is in the code that reads:
$rows = getRowsByProductSearch($query, $table, $max);
$numRows = mysql_num_rows($rows);
The $numRows variable is not a MySQL resultset, it is just a normal array returned by getRowsByProductSearch.
Change the code to read:
$rows = getRowsByProductSearch($query, $table, $max);
$numRows = count($rows);
Then it should at least find some results for you.
Good luck, James
Hi there,
The next problem is with the line that reads:
$last = ceil($rows/$page_rows);
It should be changed to read:
$last = ceil($numRows / $page_rows);
Would recommend adding the following lines to the start of you script at least while debugging:
ini_set('error_reporting', E_ALL | E_STRICT);
ini_set('display_errors', 'On');
As that would have thrown up a fatal error and saved you a whole lot of time.
if (!(isset($pg))) {
$pg = 1;
}
How is $pg going to get set? You don't appear to be reading it from $_GET. If you're relying on register_globals: don't do that! Try to read it from $_GET and parse it to a positive integer, falling back to '1' if that fails.
<a href='{$_SERVER['PHP_SELF']}?pg=$next'>Next -></a>
You appear to be losing the other parameters your page needs, 'query' and 'cmd'.
In general I'm finding it very difficult to read your code, especially the indentation-free use of echo(). Also you have untold HTML/script-injection vulnerabilities every time you "...$template..." or .concatenate a string into HTML without htmlspecialchars()ing it.
PHP is a templating language: use it, don't fight it! For example:
<?php
// Define this to allow us to output HTML-escaped strings painlessly
//
function h($s) {
echo(htmlspecialchars($s), ENT_QUOTES);
}
// Get path to self with parameters other than page number
//
$myurl= $_SERVER['PHP_SELF'].'?cmd='.urlencode($cmd).'&query='.urlencode($query);
?>
<div id="tableheader" class="tableheader">
<h1><?php h($query) ?> Sales</h1>
</div>
<div id="tablecontent" class="tablecontent">
<table border="0" width="100%"> <!-- width, border, cell width maybe better done in CSS -->
<tr>
<td width="15%">Seller ID</td>
<td width="10%">Start Date</td>
<td width="75%">Description</td>
</tr>
<?php foreach ($rows as $row) { ?>
<tr id="row-<?php h($row['Product_NO']) ?>" onclick="updateByPk('Layer2', this.id.split('-')[1]);">
<td><?php h($row['USERNAME']); ?></td>
<td><?php h($row['shortDate']); ?></td>
<td><?php h($row['Product_NAME']); ?></td>
</tr>
<?php } ?>
</table>
</div>
<div class="pagercontrols">
<?php if ($pg>1) ?>
<<- First
<?php } ?>
<?php if ($pg>2) ?>
<-- Previous
<?php } ?>
<?php if ($pg<$last-1) ?>
Next -->
<?php } ?>
<?php if ($pg<$last) ?>
Last ->>
<?php } ?>
</div>
Is it possible to have a continuous link for several items?
Across cells, no. But you're not really using a link anyway - those '#' anchors don't go anywhere. The example above puts the onclick on the table row instead. What exactly is more appropriate for accessibility depends on what exactly your application is trying to do.
(Above also assumes that the PK is actually numeric, as other characters may not be valid to put in an 'id'. You might also want to consider remove the inline "onclick" and moving the code to a script below - see "unobtrusive scripting".)
This is wrong:
if($cmd=="GetRecordSet")
echo "test in loop\n"; {
It should be:
if($cmd=="GetRecordSet") {
echo "test in loop\n";
In your getRowsByProductSearch function, you return the result of mysql_error if it occurs. In order to debug the code, maybe you can print it instead, so you can easily see what the problem is.