I have an image gallery, at the moment I limit the results to 10.
What I'm trying to do, through jQuery, is on click of the 'Load more Results' button,
Load the next 10 rows(images) in the database.
at the moment I use a class query.php to make my query call, then in my index.php display the data in a foreach loop.
I was thinking perhaps using the query string to change the limit to rows 10-20 on click but finding difficulty in this.
Any help will be appreciated.
class query.php
public function Query($db_table, $limit) {
$this->db_query = mysql_query("SELECT * FROM $db_table ORDER BY time DESC limit $limit");
while($row = mysql_fetch_array($this->db_query)) {
$rows[] = $row;
}
return $rows;
}
index.php
$lim = $_GET['limit'];
$Results = $Database->Query('info', $lim);
if(is_array($Results)) {?>
foreach ($Results as $Result) {
//echo results
jquery
$("#my_container").load("../lib/class.database.php?limit=10,20" );
Kind regards,
Adam
It's very simple:
1.) You make an AJAX call to your PHP script
$.ajax(
{
url: "get-ajax-images.php",
data: "mode=ajax&start=10&end=20",
success: function() { /* ... */ },
error: function() { /* ... */ }
});
2.) PHP: Load the data from the database based upon start and end
<?php
header("Content-type: application/json");
// Please use intval() to avoid SQL injections!!
$start = isset($_GET['start']) ? intval($_GET['start']) : exit('{"error": true}');
$end = isset($_GET['end']) ? intval($_GET['end']) : exit('{"error": true}');
/* valid start and end? */
if ( $start < 0 || $end < 0 )
exit('{"error": true}');
if ( ($end - $start) <= 0 ||
($end - $start) > 15 )
exit('{"error": true}');
/* All right! */
$sql = "SELECT id, imagepath FROM images LIMIT $start, $end";
$result = mysql_query($sql) or exit('{"error": true}');
$data = array();
while ( $row = mysql_fetch_assoc($result) )
{
$data[] = $row;
}
echo json_encode($data);
Here's the jquery part for you question
http://jsfiddle.net/manuel/e5kXc/
it holds the total amount of loaded results and you could use the var's limit and total for quering the correct results
Related
I need to update a table with more then 12000 row using php Codeigniter and a txt file.. reading the file and the foreach loop are fine but when updating line by line it takes like 30 mins, I guess the problem is I'm searching by name because I have no id in the txt file...
Here is my code:
controller:
$fn = fopen($this->upload->data('full_path'),"r");
$update = true;
while(! feof($fn) && $update) {
$pieces = explode("|", fgets($fn));
if(sizeof($pieces) == 9 && is_numeric(trim($pieces[1]))) {
$update = $this->model_products->update3s($pieces);
}
}
fclose($fn);
Model:
public function update3s($product) {
if ($product) {
$product[2] = trim(str_replace("'","''",$product[2]));
$product[1] = trim($product[1]);
$product[6] = trim($product[6]);
$product[3] = trim($product[3]);
$sql = "UPDATE products set qty = $product[3], price_vente = $product[6] where (name = '$product[2]')";
echo $sql.'<br>';
$update = $query = $this->db->query($sql);
return $update;
}
return false;
}
You can use transaction and add index for column name in database table.
$fn = fopen($this->upload->data('full_path'),"r");
$update = true;
$updatedCount = 0;
while(! feof($fn) && $update) {
$pieces = explode("|", fgets($fn));
if(sizeof($pieces) == 9 && is_numeric(trim($pieces[1]))) {
if ($updatedCount == 0) {
$databaseInstance->beginTransaction();
}
$update = $this->model_products->update3s($pieces);
++$updatedCount;
if ($updatedCount > 500) { //in one transaction update 500 rows
$databaseInstance->commit();
$updatedCount = 0;
}
}
}
if ($updatedCount > 0) { // if we have not commited transaction
$databaseInstance->commit();
}
fclose($fn);
Some tips
Add index to field name
Use prepared statements
Disable the MySQL forgeign key check Read more
writing sql function can do that even in much lesser time .
using feature like :
REPLACE()
cursors
SPLIT_STRING(custom)
in a mysql user defined function
CREATE FUNCTION update3s(hole_file_content LONGTEXT) RETURNS Boolean
BEGIN
-----Your implementation(same logic in sql ) ------
END
then coll it just by if it is CI 3
$this->db->call_function('update3s', file_get_contents($this->upload->data('full_path')));
else
$this->db->query("select update3s(".file_get_contents($this->upload->data('full_path')).")");
Below is my PHP code. I'm tying to retrieve values from a database and round them to the nearest 10 (upwards only). All the values in the database in this column are integers.
<?PHP
#$Teach_ID = $_POST['txtteachID'];
#$Class_ID = $_POST['txtclass'];
#$BookingDate = $_POST['txtbookingdate'];
#$BookingPeriod = $_POST['txtperiod'];
require_once('../BookingSystem/DBconnect.php');
$capacity = 'SELECT ClassSize FROM classes WHERE ClassID = 1';
$result = $dbh->query($capacity);
$result = (int)$result;
function ceiling($number, $significance = 1)
{
return ( is_numeric($number) && is_numeric($significance) ) ? (ceil($number/$significance)*$significance) : false;
}
}
if ($result->num_rows > 0) {
echo ceiling($result, 10);
}
?>
Error Description
Am I missing something obvious?
You need to loop through your $result variable, which is a mysqli_result object, to get its different entries.
Use mysqli_fetch_assoc to get the values, which will end in something like this :
$capacity = 'SELECT ClassSize FROM classes WHERE ClassID = 1';
$result = $dbh->query($capacity);
function ceiling($number, $significance = 1)
{
return ( is_numeric($number) && is_numeric($significance) ) ? (ceil($number/$significance)*$significance) : false;
}
}
while ($row = $result->fetch_assoc()) {
// if ($result->num_rows > 0) { /* I think this condition is not needed anymore */
$value = intval($row['ClassSize'], 10); // will convert the string from database to an int in base 10
echo ceiling($value, 10); /* I suppose you wanted to use the ClassSize key since it's the one you query */
// }
}
You can't do this $result = (int)$result;. You have to irritate over each row and then extract the data.
I'm working on a simple vlog site project and I'm trying to show only 20 video thumbnail per page and I've wrote this code in the index to divide the videos to multiple pages and then pagination them ... the problem is that it shows the same first video's thumbnail 20 times per page for infinity pages.
I really need help with this code
<?php
require_once ('db.php') ;
require_once ('VideosApi.php') ;
$count = mysql_query('SELECT COUNT(id) AS numb FROM videos ORDER BY id');
$array = mysql_fetch_assoc($count);
$number = $array['numb'];
mysql_free_result($count);
$PerPage = 20;
$nbPage = ceil(abs($number/$PerPage));
if(isset($_GET['page']) && $_GET['page'] > 0 && $_GET['page'] <= $nbPage && preg_match('#^[0-9]+$#',$_GET['page'])){ $cPage = $_GET['page']; }
else{ $cPage = 1; }
$Query = mysql_query('SELECT * FROM Videos ORDER BY id LIMIT '.(($cPage-1) * $PerPage).','.$PerPage);
$videos = Videos_Get() ;
if ($videos == Null)
die ('problem');
$vcount = #count ($videos) ;
if ($vcount == 0)
die('no videos') ;
For ($i = 0; $i < $vcount; $i++)
{
$video = $videos [$i];
if ($video->time > 3600)
$duration = gmdate("H:i:s",$video->time);
else
$duration = gmdate("i:s",$video->time);
while($Rows = mysql_fetch_assoc($Query)){
echo ( "<div class=\"video\">
<img src=\"$video->img\"><span class=\"class-video-name\">$video->name</span>
<div class=\"class-video-footer\">
<span class=\"class-video-duration\">$duration</span>
</div>
</div>") ; }
} ?>
A few tips before we get to the answer proper:
Don't use mysql_*. That family of functions is now deprecated and support will be dropped in future versions of PHP. For code longevity, consider using MySQLi or PDO.
Use is_numeric() to check if a string has a numeric value. Using preg_match() is very load heavy for such a simple task.
Try to avoid using SELECT * inside of MySQL queries. Very rarely do you need everything from the table so fetching all fields for rows is very inefficient (especially if you're not using indexes optimally).
That having been said, I've taken some time to rewrite your code following the practices I've preached above. Below is the modified code, and underneath that an explanation of what was wrong:
Update db.php as follows:
<?php
$db = new PDO( 'mysql:dbname=DATABASE_NAME;host=127.0.0.1', 'DATABASE_USER', 'DATABASE_PASSWORD' );
?>
Now for your main file:
<?php
require_once 'db.php';
require_once 'VideosApi.php';
$count = $db->query( 'SELECT COUNT(id) AS total FROM videos' )->fetchObject();
$number = $count->total;
$perPage = 20;
$pages = ceil( $number / $perPage );
$page = ( isset($_GET['page']) ) ? $_GET['page'] : 1;
$page = ( $page < 1 || $page > $pages || !is_numeric($page) ) ? 1 : $page;
$offset = ($page - 1) * $perPage;
$query = $db->query( 'SELECT id, img, name, time FROM videos ORDER BY id LIMIT '.$offset.','.$perPage );
if( $query->rowCount() < 1 )
{
die( 'No videos' );
}
$html = '';
while( $video = $query->fetchObject() )
{
$duration = ($video->time > 3600) ? gmdate('H:i:s', $video->time) : gmdate('i:s', $video->time);
$html.= '<div class="video">';
$html.= "\n\t".'<a href=\"video.php?id='.$video->id.'">';
$html.= "\n\t\t".'<img src="'.$video->img.'" />';
$html.= "\n\t".'</a>';
$html.= "\n\t".'<span class="class-video-name">'.$video->name.'</span>';
$html.= "\n\t".'<div class="class-video-footer">';
$html.= "\n\t\t".'<span class="class-video-duration">'.$duration.'</span>';
$html.= "\n\t".'</div>';
$html.= "\n".'</div>';
}
echo $html;
?>
The problem with your original code is a little hard to determine since you do not provide the contents of VideosApi.php, which is where I assume you define Videos_Get(). Anyway, what I suspect is happening, is that Videos_Get() is actually ignoring all of your pagination, but as I say, it's difficult to diagnose because we can't see all of your code!
I have codes that should be getting value from mysql database, I can get only one value but I have while loop so it can get value and output data separated with comma. But I only get one value and cannot get multiple value. the result should be like this, // End main PHP block. Data looks like this: [ [123456789, 20.9],[1234654321, 22.1] ] here is the code:
<?php
// connect to MySQL
mysql_connect('localhost','','') or die("Can't connect that way!");
#mysql_select_db('temperature1') or die("Unable to select a database called 'temperature'");
if(ISSET($_GET['t']) && (is_numeric($_GET['t'])) ){
// message from the Arduino
$temp = $_GET['t'];
$qry = "INSERT INTO tempArray(timing,temp) VALUES(".time().",'$temp')";
echo $qry;
mysql_query($qry);
mysql_close();
exit('200');
}
// no temp reading has been passed, lets show the chart.
$daysec = 60*60*24; //86,400
$daynow = time();
if(!$_GET['d'] || !is_numeric($_GET['d'])){
$dayoffset = 1;
} else {
$dayoffset = $_GET['d'];
}
$dlimit = $daynow-($daysec*$dayoffset);
$qryd = "SELECT id, timing, temp FROM tempArray WHERE timing>='$dlimit' ORDER BY id ASC LIMIT 1008";
// 1008 is a weeks worth of data,
// assuming 10 min intervals
$r = mysql_query($qryd);
$count = mysql_num_rows($r);
$i=0;
$r = mysql_query($qryd);
$count = mysql_num_rows($r);
while($row=mysql_fetch_array($r, MYSQL_ASSOC)) {
$tid=$row['id'];
$dt = ($row['timing']+36000)*1000;
$te = $row['temp'];
if($te>$maxtemp) $maxtemp=$te; // so the graph doesnt run along the top
if($te<$mintemp) $mintemp=$te; // or bottom of the axis
$return="[$dt, $te]";
echo $return; //here I get all values [1385435831000, 21][1385435862000, 23][1385435892000, 22][1385435923000, 25][1385435923000, 22]
$i++;
if($i<$count) $return= ","; echo $return; // if there is more data, add a ',' however, it return me ,,,[1385435923000, 22]
$latest = "$dt|$te"; // this will get filled up with each one
}
mysql_close();
// convert $latest to actual date - easier to do it here than in javascript (which I loathe)
$latest = explode('|',$latest);
$latest[0] = date('g:ia, j.m.Y',(($latest[0])/1000)-36000);
?>
You're just assigning $return to the values from the last row your while loop grabbed instead of concatenating it. Try this
$return = "[";
while($row=mysql_fetch_array($r, MYSQL_ASSOC)) {
$tid=$row['id'];
$dt = ($row['timing']+36000)*1000;
$te = $row['temp'];
if($te>$maxtemp) $maxtemp=$te; // so the graph doesnt run along the top
if($te<$mintemp) $mintemp=$te; // or bottom of the axis
$return.="[$dt, $te]";
$i++;
if($i<$count) $return .= ", ";// if there is more data, add a ','
$latest = "$dt|$te"; // this will get filled up with each one
}
$return .= "]";
Let's first get to an important note about my situation:
I have 1 table in my MySQL database with approx 10 thousand entries
Currently, when collecting information from table #1. I collect a total of 20 - 24 rows per page.
Example being:
Q1 : SELECT * FROM table WHERE cat = 1 LIMIT 0,25
R1: id: 1, name: something, info: 12
The PHP file that does these queries, is called by the jquery ajax function, and creates an XML file that that jquery function reads and shows to the user.
My question here is. How do i improve the speed & stability of this process. I can have up to 10 thousand visitors picking up information at the same time, which makes my server go extremely sluggish and in some cases even crash.
I'm pretty much out of idea's, so i'm asking for help here. Here's an actual presentation of my current data collection (:
public function collectItems($type, $genre, $page = 0, $search = 0)
{
// Call Core (Necessary for Database Interaction
global $plusTG;
// If Search
if($search)
{
$searchString = ' AND (name LIKE "%'.$search.'%")';
}
else
{
$searchString = '';
}
// Validate Query
$search = $plusTG->validateQuery($search);
$type = $plusTG->validateQuery($type);
$genre = $plusTG->validateQuery($genre);
// Check Numeric
if((!is_numeric($genre)))
{
return false;
}
else
{
if(!is_numeric($type))
{
if($type != 0)
{
$typeSelect = '';
$split = explode(',',$type);
foreach($split as $oneType)
{
if($typeSelect == '')
{
$typeSelect .= 'type = '.$oneType.' ';
}
else
{
$typeSelect .= 'OR type = '.$oneType.' ';
}
}
}
}
else
{
$typeSelect = 'type = ' . $type . ' ';
}
//echo $typeSelect;
$limit = ($page - 1) * 20;
if(($type != 0) && ($genre != 0))
{
$items = $plusTG->db->query('SELECT * FROM dream_items WHERE active = 1 AND genre = '.$genre.' AND ('.$typeSelect.')'.$searchString.' ORDER BY name LIMIT '.$limit.',20');
$total = $plusTG->db->query('SELECT COUNT(*) as items FROM dream_items WHERE active = 1 AND genre = '.$genre.' AND ('.$typeSelect.')'.$searchString);
}
elseif(($type == 0) && ($genre != 0))
{
$items = $plusTG->db->query('SELECT * FROM dream_items WHERE active = 1 AND genre = '.$genre.$searchString.' ORDER BY name LIMIT '.$limit.',20');
$total = $plusTG->db->query('SELECT COUNT(*) as items FROM dream_items WHERE active = 1 AND genre = '.$genre.$searchString);
}
elseif(($type != 0) && ($genre == 0))
{
$items = $plusTG->db->query('SELECT * FROM dream_items WHERE active = 1 AND ('.$typeSelect.')'.$searchString.'ORDER BY name LIMIT '.$limit.',20');
$total = $plusTG->db->query('SELECT COUNT(*) as items FROM dream_items WHERE active = 1 AND ('.$typeSelect.')'.$searchString);
}
elseif(($type == 0) && ($genre == 0))
{
$items = $plusTG->db->query('SELECT * FROM dream_items WHERE active = 1'.$searchString.' ORDER BY name LIMIT '.$limit.',20');
$total = $plusTG->db->query('SELECT COUNT(*) as items FROM dream_items WHERE active = 1'.$searchString);
}
$this->buildInfo($items->num_rows, $total->fetch_assoc());
while($singleItem = $items->fetch_assoc())
{
$this->addItem($singleItem);
}
}
return true;
}
The build info call & add item call are adding the items to the DOMXML.
This is my javascript (domain and filename filtered):
function itemRequest(type,genre,page, search)
{
if(ajaxReady != 0)
{
ajaxReady = 0;
$('#item_container').text('');
var searchUrl = '';
var searchLink;
var ajaxURL;
if(search != 0)
{
searchUrl = '&search=' + search;
searchLink = search;
ajaxURL = "/////file.php";
}
else
{
searchLink = 0;
ajaxURL = "////file.php";
}
$.ajax({
type: "GET",
url: ajaxURL,
data: "spec=1&type="+type+"&genre="+genre+"&page="+page+searchUrl,
success: function(itemListing){
$(itemListing).find('info').each(function()
{
var total = $(this).find('total').text();
updatePaging(total, page, type, genre, searchLink);
});
var items = $(itemListing).find('items');
$(items).find('item').each(function()
{
var itemId = $(this).find('id').text();
var itemType = $(this).find('type').text();
var itemGenre = $(this).find('genre').text();
var itemTmId = $(this).find('tm').text();
var itemName = $(this).find('name').text();
buildItem(itemId, itemType, itemGenre, itemTmId, itemName);
});
$('.item_one img[title]').tooltip();
},
complete: function(){
ajaxReady = 1;
}
});
}
Build item calls this:
function buildItem(itemId, itemType, itemGenre, itemTmId, itemName)
{
// Pick up Misc. Data
var typeName = nameOfType(itemType);
// Create Core Object
var anItem = $('<div/>', {
'class':'item_one'
});
// Create Item Image
$('<img/>', {
'src':'///'+typeName+'_'+itemTmId+'_abc.png',
'alt':itemName,
'title':itemName,
click:function(){
eval(typeName + 'Type = ' + itemTmId);
$('.equipped_item[name='+typeName+']').attr('src','//'+typeName+'_'+itemTmId+'_abc.png');
$('.equipped_item[name='+typeName+']').attr('alt',itemName);
$('.equipped_item[name='+typeName+']').attr('title',itemName);
$('.equipped_item[title]').tooltip();
recentEquipped(typeName, itemTmId, itemName);
updateSelfy();
}
}).appendTo(anItem);
// Favs
var arrayHack = false;
$(favEquips).each(function(){
if(arrayHack == false)
{
if(in_array(itemTmId, this))
{
arrayHack = true;
}
}
});
var itemFaved = '';
if(arrayHack == true)
{
itemFaved = 'activated';
}
$('<div/>',{
'class':'fav',
'id':itemFaved,
click:function(){
if($(this).attr('id') != 'activated')
{
$(this).attr('id','activated');
}
else
{
$(this).removeAttr('id');
}
itemFav(itemTmId, typeName, itemName);
}
}).appendTo(anItem);
$(anItem).appendTo('#item_container');
}
If anyone could help me improve this code, it'd be very much appreciated.
add an index to your table for cat column
figure out what the bottleneck is, if it is your XML then try json,
if it is your network, try enabling gzip compression
I agree with Zepplock, it is important to find out where the bottleneck is - if not, you're only guessing. Zepplock's list is good but I would also add caching:
Find out where the bottleneck is.
Use indexes in your db table.
Cache your query results
Find the Bottleneck.
There are number opinions and ways to do this... Basically when your site is under load, get the time it takes to complete each step in the process: The DB queries, the server-side processes, the client side processes.
Use Indexes.
If your DB is slow chances are you can get a lot of improvement by optimizing your queries. A table index may be in order... Use 'EXPLAIN' to help identify where indexes should be placed to optimize your queries:
EXPLAIN SELECT * FROM dream_items WHERE active = 1 AND (name LIKE "%foo%") ORDER BY name LIMIT 0,20;
(I bet an index on active and name would do the trick)
ALTER TABLE `dream_items` ADD INDEX `active_name` (`active` , `name`);
Also try to avoid using the wildcard '*'. Instead only ask for the columns you need. Something like:
SELECT `id`, `type`, `genre`, `tm`, `name` FROM `dream_items` WHERE...
Cache Your Results.
If the records in the DB have not changed then there is no reason to try an re-query the results. Use some sort of caching to reduce the load on your DB (memcached, flat file, etc..). Depending on the database class / utilities you're using it may already be capable of caching results.