I started a web application in CI 3.0, everything working smooth, I got my pagination working, but there is a problem wich I cannot figure out...
For example, I have the following URL: localhost/statistics/api_based
When navigate, $query results are displayed, links are generated, OK.
But, when I navigate to page 2 for example, the URL will become:
localhost/statistics/dll_based/index/2 and page 3 will become localhost/statistics/api_based/index/3 , so therefore I am using segments.
Now the problem is the query that is generated:
SELECT * FROM `shield_api` ORDER BY `id` ASC limit 20 offset 2
offset 2 - is the page number 2, and it should be 20, if I am correct.
I am displaying 20 results per page, so first page is correctly showing results from 1 - 20, but then page 2 will display results from 2 - 21, so you get my point, it`s not OK...
Here is my controller:
function index($offset = 0) {
// Enable SSL?
maintain_ssl ( $this->config->item ( "ssl_enabled" ) );
// Redirect unauthenticated users to signin page
if (! $this->authentication->is_signed_in ()) {
redirect ( 'account/sign_in/?continue=' . urlencode ( base_url () . 'statistics/api_based' ) );
}
if ($this->authentication->is_signed_in ()) {
$data ['account'] = $this->account_model->get_by_id ( $this->session->userdata ( 'account_id' ) );
}
$per_page = 20;
$qry = "SELECT * FROM `shield_api` ORDER BY `id` ASC";
//$offset = ($this->uri->segment ( 4 ) != '' ? $this->uri->segment ( 4 ) : 0);
$config ['total_rows'] = $this->db->query ( $qry )->num_rows ();
$config ['per_page'] = $per_page;
$config ['uri_segment'] = 4;
$config ['base_url'] = base_url () . '/statistics/api_based/index';
$config ['use_page_numbers'] = TRUE;
$config ['page_query_string'] = FALSE;
$config ['full_tag_open'] = '<ul class="pagination">';
$config ['full_tag_close'] = '</ul>';
$config ['prev_link'] = '«';
$config ['prev_tag_open'] = '<li>';
$config ['prev_tag_close'] = '</li>';
$config ['next_link'] = '»';
$config ['next_tag_open'] = '<li>';
$config ['next_tag_close'] = '</li>';
$config ['cur_tag_open'] = '<li class="active"><a href="#">';
$config ['cur_tag_close'] = '</a></li>';
$config ['num_tag_open'] = '<li>';
$config ['num_tag_close'] = '</li>';
$config ["num_links"] = round ( $config ["total_rows"] / $config ["per_page"] );
$this->pagination->initialize ( $config );
$data ['pagination_links'] = $this->pagination->create_links ();
//$data ['per_page'] = $this->uri->segment ( 4 );
$data ['offset'] = $offset;
$qry .= " limit {$per_page} offset {$offset} ";
if ($data ['pagination_links'] != '') {
$data ['pagermessage'] = 'Showing ' . ((($this->pagination->cur_page - 1) * $this->pagination->per_page) + 1) . ' to ' . ($this->pagination->cur_page * $this->pagination->per_page) . ' results, of ' . $this->pagination->total_rows;
}
$data ['result'] = $this->db->query ( $qry )->result_array ();
$this->load->view ( 'statistics/api_based', isset ( $data ) ? $data : NULL );
}
Can someone point me to my problem ? Any help is apreciated.
You may have a misunderstanding of how LIMIT works.
Limit with one value sets the maximum number to be returned.
LIMIT 10
Will retrieve at most 10 rows, starting at the beginning of the results matching your query.
Limit with two values sets the start position (offset in rows, not pages) and the maximum number of rows to be returned.
LIMIT 20, 10
Will retrieve at most 10 rows, starting at row 20.
So, you'll need to modify your logic a bit here:
$start = max(0, ( $offset -1 ) * $per_page);
$qry .= ' LIMIT {$start}, {$per_page}';
Related
I have a code that displays reviews graph of the entire website and divides them into sections according to ratings. The problem is that this code calculates the total reviews of the whole website. I would need to filter the total reviews count according to the currently chosen language. I use WPML. Any advice?
Code:
function display_all_product_review_histogram($minimum_rating, $maximum_rating){
$all_product_review_average_rating = get_all_product_review_average_rating($minimum_rating, $maximum_rating);
$total_ratings = $all_product_review_average_rating[0]["total_ratings"];
$get_all_product_review_counts_by_ratings = get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating);
if($get_all_product_review_counts_by_ratings){
$output = '';
$sum = 0;
$total = 0;
$raw_percentages_array = array();
$percentages_array = array();
//When working with rounded percentages, we must make sure the total percentages add up to 100%.
//Creating array of rating values and its percentage
foreach ($get_all_product_review_counts_by_ratings as $key => $rating) {
$percentage = round($rating["amount"] / $total_ratings, 2) * 100;
$raw_percentages_array[] = array("value" => $rating["value"], "percent_of_total" => $percentage, 'amount'=> $rating["amount"]);
}
//Counting the total of our percents
foreach($raw_percentages_array as $key => $percent) {
$total += $percent[ "percent_of_total" ];
}
//Creating an array that will have the actual percentages after the rounding has been applied to it.
//This will help to see if we have 100% or we are not aligned
foreach($raw_percentages_array as $key => $percent){
$percentages_array[$percent["value"]] = round(($percent["percent_of_total"]/$total) * 100, 0);
}
$sum = array_sum($percentages_array); //Again counting the total of our new percents to see if it adds up to 100%
if($sum != 100){ //If we do not have 100%, then we will alter the highest percentage value so that we get a total of 100%
$highest_percentage_key = array_keys($percentages_array, max($percentages_array)); //Getting key of the highest percentage value
$percentages_array[$highest_percentage_key[0]] = 100 - ($sum - max($percentages_array)); //Alterning the percentage
}
//Now we are ready to create the output that will give us 100% in total
$r_count = 0;
$output .= "<div class='product-review-histogram'>";
foreach ($percentages_array as $key => $percentage) {
$output .= "<div class='histogram-row star-rating-". $key ."'>";
$output .= "<div class='histogram-col-1'>". $key ." star</div>";
$output .= "<div class='histogram-col-2'><div class='histogram-meter-bar'><div class='histogram-bar-temperature' style='width: ". $percentage ."%'></div></div></div>";
$output .= "<div class='histogram-col-3'>". $raw_percentages_array[$r_count]['amount'] ."</div>";
$output .= "</div>";
$r_count++;
}
$output .= "</div>";
return $output;
}else{
return;
}
}
UPDATE - sharing code of get_all_product_review_average_rating function:
function get_all_product_review_average_rating($minimum_rating, $maximum_rating){
$get_all_product_review_counts_by_ratings = get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating);
if($get_all_product_review_counts_by_ratings){ //If we have reviews
$average_rating_results = array();
$total_ratings = 0;
$total_rating_value = 0;
foreach ($get_all_product_review_counts_by_ratings as $key => $rating) {
$total_ratings = $total_ratings + $rating["amount"];
$current_rating_value = $rating["amount"] * $rating["value"];
$total_rating_value = $total_rating_value + $current_rating_value;
}
$average_rating = number_format($total_rating_value / $total_ratings, 1); //Rounding value to one decimal place
$average_rating_results[] = array(
"total_ratings" => $total_ratings,
"average_rating" => $average_rating
);
return $average_rating_results;
}else{
return;
}
}
UPDATE2 - sharing more of the functions related to the graph
function get_all_product_review_ratings(){
global $wpdb;
if ( false === ( $review_ratings = get_transient( 'all_product_review_ratings' ))){ //Checking if we have previously cached query results in order to save resources and increase speed
$review_ratings = $wpdb->get_results("
SELECT meta_value
FROM {$wpdb->prefix}commentmeta as commentmeta
JOIN {$wpdb->prefix}comments as comments ON comments.comment_id = commentmeta.comment_id
WHERE commentmeta.meta_key = 'rating' AND comments.comment_approved = 1
ORDER BY commentmeta.meta_value
", ARRAY_A);
$expiration = 60 * 5; //Expiring query results after 5 minutes
set_transient( 'all_product_review_ratings', $review_ratings, $expiration ); //Temporarily storing cached data in the database by giving it a custom name and a timeframe after which it will expire and be deleted
return $review_ratings;
}else{
return $review_ratings;
}
}
WHAT DO WE NEED TO CHANGE TO GET THIS IS PROBABLY THIS PART OF THE CODE:
$review_ratings = $wpdb->get_results("
SELECT meta_value
FROM {$wpdb->prefix}commentmeta as commentmeta
JOIN {$wpdb->prefix}comments as comments ON comments.comment_id = commentmeta.comment_id
WHERE commentmeta.meta_key = 'rating' AND comments.comment_approved = 1
ORDER BY commentmeta.meta_value
", ARRAY_A);
UPDATE 3:
function get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating){
$all_product_review_ratings = get_all_product_review_ratings();
if($all_product_review_ratings){ //If we have reviews
$all_product_review_ratings_one_dimensional_array = array_map("current", $all_product_review_ratings); //Converting two dimensional array to one dimensional array
$rating_counts = array_count_values($all_product_review_ratings_one_dimensional_array); //Creating array that consists of rating counts
$ratings = array();
while($maximum_rating >= $minimum_rating){
if(array_key_exists($maximum_rating, $rating_counts)){
$star_count = $rating_counts[$maximum_rating];
}else{
$star_count = 0;
}
//Creating array that contains information about
$ratings[] = array(
"value" => $maximum_rating,
"amount" => $star_count
);
$maximum_rating--;
}
return $ratings;
}else{
return;
}
}
function get_all_product_review_ratings() {
global $wpdb;
if (false === ( $review_ratings = get_transient('all_product_review_ratings'))) { //Checking if we have previously cached query results in order to save resources and increase speed
$review_ratings = array();
$args = array(
'status' => 'approve',
'type' => 'review',
'paged' => 0,
'meta_query' => array(
array(
'key' => 'verified',
'value' => 1
)
));
// The Query for getting reviews - WPML respected
$comments_query = new WP_Comment_Query;
$comments = $comments_query->query($args);
foreach ($comments as $comment) {
$review_ratings[] = get_comment_meta($comment->comment_ID, 'rating', 1);
}
$expiration = 60 * 5; //Expiring query results after 5 minutes
set_transient('all_product_review_ratings', $review_ratings, $expiration); //Temporarily storing cached data in the database by giving it a custom name and a timeframe after which it will expire and be deleted
return $review_ratings;
} else {
return $review_ratings;
}
}
I'm wondering if there is a way to know the time each function takes to execute within my php script ?
The script contain functions like (if conditions - for loop - connections to the DB using PDO).
for example I have something like that :
<?php
$link = $_POST['url'];
$links = array();
for($i = 1; i < 9; i++){
array_push($links , $link . 'page' . $i);
}
foreach($links as $lin){
//PDO connection to the DB , It's not written right
$statement = 'SELECT * from links WHERE link = :zlink';
zlink = $lin;
$count = $statement->rowCount();
if($count > 1){
// do something
}else{
'INSERT INTO links WHERE link = :mlink';
mlink = $lin;
file_put_contents();
}
}
and more other functions , So is it possible to know how much each of these functions take? and what takes much time ?
If you want to accomplish this without using external libraries, add a function to your code like:
function splittime( $flag = NULL, $msg = ‘’, $output = TRUE ) {
$ts = microtime( TRUE );
if ( $output ) {
if ( $flag ) {
echo ( round( ( $ts - $flag ), 3 ) ) . " seconds - ";
}
echo $msg . ": " . date( 'H:i:s', $ts ) . ":" . ( round( ( $ts - intval( $ts ) ), 3 ) * 1000 ) . "<br><br>";
}
return $ts;
}
The first time you call the function in your script (or inside another function), call it like this:
$flag = splittime();
With each subsequent call, use this:
$flag = splittime( $flag );
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'm developing a plugin for WordPress. I use WP_List_Table which output rows from database nicely.
The issue I have is the pagination. If I have let's say 200 rows in the database and I set it to only display 50 rows per page, this works and I do get 1 of 4 pages.
On page 1 It displays ID 1 to ID 50. But when I click on page 2 it displays ID 2 to ID 51. So it only jumps 1 row and not 50. Where's the issue?
This will handle the data:
function prepare_items() {
global $wpdb;
/* Select project for user */
$table_name2 = $wpdb->prefix . 'project_name';
$current_user = wp_get_current_user();
$sql2 = "SELECT * FROM " . $wpdb->prefix . "project_name WHERE alloweduser = " . $current_user->ID;
$results2 = $wpdb->get_results($sql2) or die(mysql_error());
foreach( $results2 as $result2 ) {
$table_name = $wpdb->prefix . "project_name_" . $result2->projectname;
/* Define how many rows to show per page */
$per_page = 50;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
// here we configure table headers, defined in our methods
$this->_column_headers = array($columns, $hidden, $sortable);
// [OPTIONAL] process bulk action if any
$this->process_bulk_action();
// will be used in pagination settings
$total_items = $wpdb->get_var("SELECT COUNT(cid) FROM $table_name");
// prepare query params, as usual current page, order by and order direction
$paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged']) - 0) : 0;
$orderby = (isset($_REQUEST['orderby']) && in_array($_REQUEST['orderby'], array_keys($this->get_sortable_columns()))) ? $_REQUEST['orderby'] : 'cid';
$order = (isset($_REQUEST['order']) && in_array($_REQUEST['order'], array('ASC', 'DESC'))) ? $_REQUEST['order'] : 'ASC';
// Define $items array
// notice that last argument is ARRAY_A, so we will retrieve array
$this->items = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name ORDER BY $orderby $order LIMIT %d OFFSET %d", $per_page, $paged), ARRAY_A);
// configure pagination
$this->set_pagination_args(array(
'total_items' => $total_items, // total items defined above
'per_page' => $per_page, // per page constant defined at top of method
'total_pages' => ceil($total_items / $per_page) // calculate pages count
));
}
}
}
This will output the data:
function custom_table_example_submissions_page_handler() {
global $wpdb;
$table = new Custom_Table_Example_List_Table();
$table->prepare_items();
$message = '';
if ('delete' === $table->current_action()) {
$message = '<div class="updated below-h2" id="message"><p>' . sprintf(__('Deleted %d submission(s).', 'custom_table_example'), count($_REQUEST['id'])) . '</p></div>';
}
?>
<div class="wrap">
<div class="icon32 icon32-posts-post" id="icon-edit">
<br></div>
<h2><?php _e('Submissions', 'custom_table_example')?>
</h2>
<?php echo $message; ?>
<form id="submissions-table" method="GET">
<input type="hidden" name="page" value="<?php echo $_REQUEST['page']; ?>"/>
<?php //$table->display(array('contributorname', 'email')); ?>
<?php $table->display(); ?>
</form>
</div>
<?php
}
Update:
get_columns:
function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
'name' => __('Name', 'custom_table_example'),
'upload' => __('Upload', 'custom_table_example'),
'upload2' => __('Upload', 'custom_table_example'),
'upload3' => __('Upload', 'custom_table_example'),
'upload4' => __('Upload', 'custom_table_example'),
'rate' => __('Rate', 'custom_table_example'),
);
return $columns;
}
$this->items is retrieved from:
https://core.trac.wordpress.org/browser/tags/4.0.1/src//wp-admin/includes/class-wp-list-table.php#L0
It's called with:
if (!class_exists('WP_List_Table')) {
require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
}
I managed to solve it and answer my own question.
The issue was here:
$paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged']) - 0) : 0;
Since I want to output 50 rows per page I simply added -1 to $_REQUEST['paged'] and added * 50 which means that on page 1 row 1-50 is displayed and on page 2 rows 51-100 is displayed since 2*50 is 100 and so on.
Correct solutions is this:
$paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged'] -1) * 50) : 0;
I have same issue in my project so solution is here
$per_page = 5;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
$this->process_bulk_action();
$paged = isset($_REQUEST['paged']) ? max(0, intval($_REQUEST['paged'] -1) * $per_page) : 0;
I hope Now your problem will be solve
$found_data = array_slice($this->table_data(),(($current_page-1)*$per_page),$per_page);
$this->items = $found_data;
Use above mention code in your prepare_items(). It devides your list of data into the chunks.
How is that possible to show sphinx search result via PHP
i have installed sphinx and configured but i am unable to get the result via PHP
Check the Sphinx Library : Sphinx Documentation
The Below Code Is Used To Get The Full Content From Sphinx Search Result
Now Currently We Need To Give The Id In $SQL line
<?php
echo "Welcome To Sphinx Search Site </br>";
$q = "html";
$sphx = sphinx_search("html", 0, 20);
$sphx['122'];
$ids = 122;
$sql = "SELECT post_title , post_content FROM wp_posts WHERE ID = '122'";
db();
if( !($r = mysql_query($sql)))
die("[MYSQL]".mysql_error() . mysql_errno() );
$max = $sphx['total'];
$num_rows = $sphx['docs'];
echo "<b>Displaying {$num_rows} results of {$max}</b><br /><br />";
while($row = mysql_fetch_assoc($r) ) {
echo "{$row['post_title']} <br />{$row['post_content']}<br /><hr />";
}
mysql_free_result($r);
/*
* SPHINX Search
*/
/*
* Search sites by Keywords using sphinx; with an option to search sites tags only
* #param string $q te keyword
* #param int $i id of the first result to return
* #param int $max max results to return
* #param bollen $url set to true to return matches from the 'url' column only
*
* #return string $ids comma seperated list of ids
*/
function sphinx_search($q, $i, $limit, $post_type=true){
require_once 'sphinxapi.php';
$ids = '33500';
$cl = new SphinxClient();
$cl->SetServer( "192.168.0.89" , 9667);
$cl->SetMatchMode( SPH_MATCH_EXTENDED );
$cl->SetSortMode ( SPH_SORT_RELEVANCE );
$cl->SetFieldWeights(array('post_title' => 300));
$cl->SetLimits( $i , $limit);
$q = $cl->EscapeString( $q);
//search url only
$q = $post_type ? "#post_type {$q}" : $q;
$result = $cl->Query( $q, 'sites sitesDelta' );
if ( $result === false )
error_log( '[SPHINX]Query failed: ' . $cl->GetLastError() );
elseif ( $cl->GetLastWarning() )
error_log( '[SPHINX]WARNING: ' . $cl->GetLastWarning() );
if ( !empty($result["matches"]) ){
foreach ( $result["matches"] as $doc => $docinfo )
$ids .= "$doc,";
$ids = substr( $ids, 0, -1 );
}else
return false;
return array( 'ids' => $ids, 'total' => $result['total'], 'docs' => count($result["matches"]) );
}
/*
* Connect to MySQL
*/
function db(){
if( !empty($GLOBALS['db']) ) return true;
if( !$GLOBALS['db'] = mysql_connect('localhost', 'root', '' ) ) {
die("[MYSQL]".mysql_error() . mysql_errno() );
}
elseif(!mysql_select_db('sphinxiirmulti')) {
die("[MYSQL]".mysql_error() . mysql_errno() );
}
}
?>