I have a database containing 40 pictures. These pictures are displayed using a pager.
I have a URL query: http://www.test.com/photo.php?id=15. This sets the current picture ID to 15. This picture is the 5th one on page 2.
How can I get the page a picture is on given only the ID?
SQL
select * from photo limit 40
PHP
$i=1;
while($r){
if($r[id]=$id) $cur_picRank = $i;
$i++;
}
$curPage = ceil( $cur_picRank / $pagesize);
Is this correct?
Easy-peasy.
You just have to count pictures shown before.
if them ordered by id, just SELECT count(*) where id < $id
So, you will get a position and now can divide it by page size.
For the different ordering you have to get field value first (e.g. to order by name get a name by id and then use it in condition)
As for your approach, it is NOT correct.
Selecting whole table to get just ONE row is always BAD idea.
Though this code would not work anyway. There is no loop exit condition and a counter doesn't count
Related
I am making pagination in core PHP (actually first time). As user will press the pagination button for example user pressed second pagination button. then this query generates:
SELECT * FROM product LIMIT 12, 12
It is executing perfectly as I expected. but the main problem is that if user wants to do filtration on that specific page for suppose user wants all items which are present in page 2 and category_id must be 3 then this query generates:
SELECT * FROM products WHERE category_id IN (3) LIMIT 12, 12
But I am getting the empty resultset... What I am doing wrong?
The pages are based on the number of lines your query returns. You cannot apply a filter on a single page on the DB side as any additional Wheres would change the elements in the pages of the previous query.
In your case, adding WHERE category_id IN (3) results in no lines, making your new page empty.
You could implement filters in your frontend, or backend AFTER the query returns the result, and your filter would remove items from the DB result.
Ideally, every time your users interact with the UI, it would result in a new call to the DB with the filters being applied on the query. then show the result to your user.
If I understood correctly you want to change the WHERE clause in any way between pages and you not want any previous records be repeated.
If you have a unique id in your table and that id increases with each page you can use for a bookmark. I have a simple procedure to make that column. Then you can create a column specifically for this app.
You create a bookmark column and add it to the WHERE clause.
This column will give you a bookmark to save the user's position.
You save this column's value from the last record.
Then in your query you can add this position your query in the WHERE clause
WHERE `bookmark` > $position AND ...
Then you can make any change between any pages at any time you want to the WHERE clause and you will never repeat a previous record.
Making this new column is very simple and does not require much storage.
Use the same ORDER BY from your page query and make your WHERE 1.
$sql = SELECT `product_id` FROM `products` WHERE 1 ORDER BY `category`, `description`";
$results = mysqli_query($conn,$sql);
while(list($product_id) = mysqli_fetch_array($results, MYSQLI_NUM)){
$bookmark[] = $product_id;
}
foreach($bookmark as $position => $product_id){
$sql = "UPDATE `products` SET `bookmark` = $position WHERE `product_id`=$product_id";
}
I have searched everywhere but could not get anything. The scenario is that when I run a select statement from MySQL/PHP, I want to use Next & Previous buttons to navigate backwards and forward through the results.
Does anyone know how I can accomplish this?
Here's how I run the query: select everything from members where hair = black;
This returns 8 results, and I have a page like so details.php?id=3 which takes id and display the details.
I want to be able to keep clicking the next button and move to another id from the result.
How do I accomplish this?
Thank you for your assistance.
If you mean to display 1 product details per page with Next buttons, then
1) Get the total rows from table
2) Find total number of pages like
$totalPages = $totalRows; //since 1 record per page
3) Loop thru $totalPages value to generate next links
4) Get the id of product from page url $_GET
5) Query sql using te product id obtained frm GET
Well thats the basics, hope your get it
Assuming you have all ids in the $allIds var, try something like this:
<?php
$id = (int) $_GET['id'];
$key = array_search($id, $allIds);
$nextId = $allIds[$key+1];
?>
Well, you have 2 different scopes here to address, first, when you query you are in PHP/Server side mode. PHP gets some data, processes it, shows some of it to the knowledge i have of your problem and then sends it to the browser.
Next, you have the client scope, where the client has the HTML rendered to his screen and has the possibility to click NEXT and PREVIOUS. When he does that, he issues a request to the server to get the NEXT or PREVIOUS record based on the current one.
You have 2 scenarios to work this problem out:
1) Load the whole data into memory and scan it to find your current position, see if there is a NEXT and PREVIOUS element and respond to the request of the user. If the user asked for the NEXT, easy, just move one more record. If the user asked for PREVIOUS item, then when scanning using a WHILE or FOR/FOREACH, always keep in memory the "lastitem" you saw, you can use this "lastitem" as your PREVIOUS item.
2) In the event you have many (i mean like more than 1000) items, you need to use a little subquery magic and work this out using SQL.
select everything from members where hair = black AND id = XYZ ORDER BY id LIMIT 2;
This will return you the CURRENT AND NEXT elements. Then call the same query again but this time, order it DESC so that your 2 items are the CURRENT AND PREVIOUS.
select everything from members where hair = black AND id = XYZ ORDER BY id DESC LIMIT 2;
Note that you can order this the way you want, the goal is to get a static result, something that always gets out the same way so that you can reverse it and get the items around the selected one.
I hope this helps you
I am trying to make a photo gallery in php + mysql.
The URL viewphoto.php?id=143 shows photo 143.
In the navigation menu, I want to display the previous two photos in that album, and the next two.
I thought of using:
$temp_id = $id - 2;
mysql_query("SELECT id, photo FROM photos WHERE album = {$album} AND id >= {$temp_id} LIMIT 5");
But that didn't work, because photo's from different albums could have the ids preceding and succeeding the one of the viewed photo.
Does anyone know how I could do this?
Thanks.
Using the id to sort your pictures is a bad idea. Imagine you delete one picture. Your chain of pictures will be broken. In order to fix it, you would need to change the id column, which is an even worse idea.
Either use a seperate index column for the sorting within one album. This index could be rebuilt easily in the case of a picture getting deleted.
Or you define a "previous" and "next" column in your table. This would then contain the id of the last and next picture. If a picture gets deleted, you only need to change these columns for the previous and the next picture.
With both methods, you could for example use a nested self join to access your previous and next 2 pictures. Comment on this post if you need help on that.
I've been dealing with this issue myself and I never found an elegant solution to the problem, I ended up doing it in two queries:
// next
mysql_query("SELECT id, photo FROM photos WHERE album = {$album} AND id > {$id} ORDER BY id ASC LIMIT 2");
// prev
mysql_query("SELECT id, photo FROM photos WHERE album = {$album} AND id <= {$id} ORDER BY id DESC LIMIT 3");
Now the first item in "prev" once fetched would be the current photo.
This solution does has to be amended with a check that the first item in "prev" is in fact the requested id, because it doesn't make sure it's the proper id, in case of gaps in the series.
So I have set up a mysql database that holds an image (more specifically a path to an image) and the images rank (starting at 0). I then created a web page that displays two images at random at a time. [Up till here everything works fine] I want my users to be able to click on one of the images that they like better and for that images rank to increase by +1 in the database.
How would I set that up? Please be as detailed as possible in your explanation. I am new to php and mysql.
You need something like this.
A Table
Images:
ID,Name,Path,ranking
Have One up vote button ( update images set ranking = ranking + 1 where id = $id; )
Have One down vote button ( update images set ranking = ranking - 1 where id = $id and ranking > 0; )
Hopefully that solves the problem.
onclick execute UPDATE image_ranks SET rank = rank+1 WHERE image_id = {$image_id}
implement onclick event for image ( or voting icon ) what will execute AJAX request to script which will update rank value in database, as result will return a new updated value what can be used to update <div> content with acctual ranking
I've set up a simple gallery system in PHP that is built to display one image per page. My URL parameter simply uses a gallery variable and a page variable and does not use the image iD in any way to pull the image. This is because I'm setting my htaccess settings to make a friendly URL:
http://mysite.com/images/1/
^ Would pull the first image in my MySQL query
or
http//mysite.com/images/12/
^ Would pull the 12th image in my MySQL query
The PHP page would then look like:
images.php?gallery=images&page=1
and
images.php?gallery=images&page=12
The queries (simplified) would then look like this for each of the above:
For the first image:
SELECT id, img_src
FROM pictures
WHERE gallery = images
ORDER BY date_added DESC
LIMIT 0, 1
and for the 12th image:
SELECT id, img_src
FROM pictures
WHERE gallery = images
ORDER BY date_added DESC
LIMIT 11, 1
It's been working great but I ran into a problem now that I want to add a feature. I was hoping to display thumbnails of the ten most recently added images to the database no matter which gallery they belong to… i.e. this query:
SELECT id, gallery, img_src
FROM pictures
ORDER BY date_added DESC
LIMIT 10
Is there any way I can know which 'position' or 'page' each image would be for the specific gallery so that I can create the link correctly?
For example, say the ten most recent thumbnails return 4 pictures from the gallery 'images', then 2 pictures from the gallery 'weddings', then 3 pictures from the gallery 'portraits' and then one more image from the gallery 'images', so my links should then be:
http://mysite.com/images/1/
http://mysite.com/images/2/
http://mysite.com/images/3/
http://mysite.com/images/4/
http://mysite.com/weddings/1/
http://mysite.com/weddings/2/
http://mysite.com/portraits/1/
http://mysite.com/portraits/2/
http://mysite.com/portraits/3/
http://mysite.com/images/5/
Thanks for any help. I'm sure I'm overlooking something stupid easy here but I'm hoping to do it most efficiently as far as programming goes. So far my thoughts are that when I'm looping through the output I have to somehow retain each gallery's 'image count' and add one to this count each time an image of that gallery is added.
If you're still building the site I would change the URL's to show the actual image ID's and not a pseudo ID based on pagination.
This is good for several reasons:
SEO. You're pages stay the same. Google indexes them and when a visitor comes to the site at example.com/wedding/4234 he will actually find what he's looking for and not what Google indexed last time your site was scanned
Simplicity. You're already facing a problem that would be very easilly resolved if you were using real image ID's on the first place.
Analytics. You'll know what content is driving people to your site. There is no guessing here. URL's will remain the same always (no matter if new content comes in or not).
Quick and dirty:
$sql = "SELECT id, gallery, img_src
FROM pictures
ORDER BY date_added DESC
LIMIT 10";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
if(!$$row['gallery']) $$row['gallery'] = array();
array_push($$row['gallery'], $row['id']);
$pagenumber = count($$row['gallery']);
echo "<a href=\"http://mysite.com/{$row['gallery']}/$pagenumber/\">
<img src=\"{$row['img_src']}\" alt=\"\"></a><br>";
// alt attribute for w3 validation (http://validator.w3.org/)
}
Edit:
Fixed code error. Now will dynamically create the array if it doesn't already exist.
(Originally, it illegally used the [ ] operator.)
I'm going to add to Frankie's answer, because I also believe the OP's current method is going to bite him the butt again one day. The OP may not find this useful, but it could help someone else.
You can use http://site.com/images/20, but the 20 represents an image ID instead of a page number. Of course the query to get the image is simple:
SELECT id, img_src
FROM pictures
WHERE gallery = images
AND id = 20
LIMIT 1
As a benefit this query is more efficient than using an offset with the LIMIT clause. But the OP said in a comment that he likes his current system because it doesn't require additional database queries to help build pagination links. Well, that's not a problem here.
Lets say you're on the page http://site.com/images/20. Your page links would be the following:
Prev - http://site.com/images/prev/20
Next - http://site.com/images/next/20
Obviously it didn't take any additional queries to build those links. They're just a slightly different URL showing the same image ID. But how do they work to move to the next or prev image? Simple. Instead of the above query, you would use one of these:
If the prev link was clicked, you use this query:
SELECT id, img_src
FROM pictures
WHERE gallery = 'images'
AND id < 20
ORDER BY id DESC
LIMIT 1;
If the next link was clicked, you use this query:
SELECT id, img_src
FROM pictures
WHERE gallery = 'images'
AND id > 20
ORDER BY id ASC
LIMIT 1;
The first query gives the image that came before the current one, and the second query gives the image that comes after the current one.