I have 2 SQL queries as below:
$results2 = $wpdb->get_results("SELECT * FROM `wp_posts` WHERE id IN (".implode(",", $product_ids).")");
$getprice = $wpdb->get_results("SELECT * FROM `wp_postmeta` WHERE meta_key='_regular_price' AND post_id IN (".implode(",", $product_ids).")");
I have combined them as below query:
$yeni = $wpdb->get_results("SELECT wp_posts.id, wp_posts.post_title, wp_postmeta.meta_value
FROM wp_posts
INNER JOIN wp_postmeta ON wp_posts.id = wp_postmeta.post_id
WHERE meta_key = '_regular_price'
WHERE wp_posts.id IN (".implode(",", $product_ids).")");
After combining the queries, it's giving an empty result. I can't find the issue with the updated query.
Try this sql.
I have replace this WHERE meta_key = '_regular_price'
$yeni = $wpdb->get_results("SELECT wp_posts.id, wp_posts.post_title, wp_postmeta.meta_value FROM wp_posts INNER JOIN wp_postmeta ON wp_posts.id = wp_postmeta.post_id WHERE wp_posts.id IN (".implode(",", $product_ids).") and wp_postmeta.meta_key = '_regular_price'");
I don't understand why you don't use the native Wordpress features via OOP procedure.
Your simple query, it can be translated like this:
<?php
$loop = new WP_Query(
array(
'post_type' => 'page', // post type: page, post, attachment etc..
'post__in' => $productIds, // array[]
)
);
// after that, you can use a standard wordpress loop
if($loop->have_posts()) {
while($loop->have_posts()) {
: $loop->the_post();
the_title();
print "<br>";
// access to meta key _regular_price
print get_post_meta(get_the_ID(), '_regular_price', true);
}
}
This is the right way.
Cheers
Class reference here: https://developer.wordpress.org/reference/classes/wp_query/
Related
I've been searching through the past two days to find out where exactly could the Woocommerce products thumbnails (images) texts and URL's are stored inside the database tables, but still cannot figure this out!
I'm in a situation where I must use SQL queries to move the products data into another tables, and I have to implement the process from my phpmyadmin panel.
I already searched the wp_posts and wp_postmeta tables, wp_posts contains a guide column for the url to the product which post_type like 'product%', So far I know that in general the post stores it's thumbnalis link inside one of the posts with a type of attachment , while I need the posts with a post_type of product or like so.
Hope I can find some answers here, Thanks.
You can use the Wordpress WP_Query to get the thumbnail image of product.
$args = array(
'post_type' => 'product', //post type of product
'posts_per_page' => -1
);
$query= new WP_Query( $args );
while ( $query->have_posts() ) : $query->the_post();
global $product;
//woocommerce_get_product_thumbnail is use to get the product thumbnail link
echo '<br />' . woocommerce_get_product_thumbnail().' '.get_the_title().'';
endwhile;
wp_reset_query();
Solution 2- using the custom query as you mention in query.
//Using custom query get the details from wp_postmeta and wp_posts
//_wp_attached_file - meta key for image
$querystr = "SELECT p.*, pm2.meta_value as product_image FROM wp_posts p LEFT JOIN
wp_postmeta pm ON (
pm.post_id = p.id
AND pm.meta_value IS NOT NULL
AND pm.meta_key = '_thumbnail_id'
)
LEFT JOIN wp_postmeta pm2 ON (pm.meta_value = pm2.post_id AND pm2.meta_key = '_wp_attached_file'
AND pm2.meta_value IS NOT NULL) WHERE p.post_status='publish' AND p.post_type='product'
ORDER BY p.post_date DESC";
$upload_dir = wp_upload_dir();
//get wp_upload url
$wp_upload_url = $upload_dir['baseurl'];
$pageposts = $wpdb->get_results($querystr, OBJECT);
foreach ($pageposts as $post){
echo "<br /><a href='".$post->guid."'><img src='". $wp_upload_url.'/'.$post->product_image."'>".$post->post_title."</a>";
}
I am trying to get ordering working in wp_query, but posts are still being ordered with default settings (just tag__in is working). SQL query for posts looks like this:
string(379) "SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (81) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 3"
Here is code snippet:
remove_all_filters('posts_orderby');
$tag = get_term_by('name', 'title_post', 'post_tag');
$args=array(
'order'=>'ID',
'orderby'=>'ASC',
'tag__in' => $tag,
'posts_per_page'=>3, // Number of related posts to display.
'caller_get_posts'=>1
);
$my_query = new wp_query( $args );
var_dump($my_query->request);
Thanks!
I have checked your code you have to pass wrong arguments.
Can you please check below code?
Wrong
'order'=>'ID',
'orderby'=>'ASC',
Right
'order'=>'ASC',
'orderby'=>'ID',
Ok, I switched order and orderby ...
So, correct arguments are 'orderby'=>'ID','order'=>'ASC',
In "category.php" file I need to order my posts in this strange way:
First all the posts where author is different than "admin" (in alphabetical order by title)
Than all the post by "admin" (in the same alphabetical order)
Here is the standard code I use to do my query:
<?php global
$wp_query;
query_posts(
array_merge(
array('orderby' => 'title', 'order' => 'ASC'),
$wp_query->query
)
);
?>
Any idea about how to accomplish it without nesting two queries?
Thanks in advance!
EDIT: Following is some code that was tried, as suggested by Sepster in a previous version of his answer. But at the moment this code starts showing all the posts from 'admin' (instead of the others) until the posts with author different than 'admin' come. At that point it breaks the results and jump to the next page of results.
<?php
global $wp_query;
query_posts(
array_merge(
array('orderby' => 'title', 'order' => 'ASC'),
$wp_query->query
)
);
$adminPosts = false;
for ($i=1; $i<=2; $i++) {
while ( $wp_query->have_posts() ) {
$wp_query->the_post();
$author = get_the_author();
if ($author == 'admin' && $adminPosts == false) break;
if ($author != 'admin' && $adminPosts == true) break;
// ALL MY STUFF
} // end while
rewind_posts();
$adminPosts=true;
} // end FOR
?>
Update:
I've finally come up with a somewhat workable solution for this, but it's fair to say this really is an excercise in academics; Yes, it's do-able without executing a second loop, but really, it's pretty convoluted.
The solution is, in summary
Develop a custom SQL statement that will return the rows in the order required.
This is because in SQL, the only way to get the results in the order you need is by doing a UNION of your two subsets. To my knowledge there's no way of doing that using the "normal" WP query operations.
Execute this query, and loop over its results rather than a standard "the loop".
This is because we're getting back a recordset, rather than a WP_Query object.
Set the "Blog pages show at most X posts" setting to 1.
(on /wp-admin/options-reading.php)
A common complaint is pagination breaking when using custom queries (incidentally, the query_posts() method you're using is susceptible to this issue).
There are numerous turorials on how to do this properly, eg:
https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
https://codex.wordpress.org/Pagination#Troubleshooting_Broken_Pagination
The first of those recommends the implementation of "Offset and Manual Pagination".
The closest I've found to an implementation of this in conjunction with a custom SQL statement is this https://wordpress.stackexchange.com/a/28717. I've borrowed heavily from this answer (and so I recommend you go over and give it an up-vote!).
However, this technique (among other more "standard" custom query approaches) suffers from a known behaviour where WP produces a 404 on the final page (if I understand correctly, because WP is still using its own query and associated max-page=posts-per-page/posts calculations to map between the page number in the URL and the delivered content).
Refer http://wordpress.org/support/topic/explanation-and-workaround-for-error-404-on-category-pagination?replies=14 for details about this issue, and a proposed solution (which unfortunately won't work for our custom SQL approach).
A known "work-around" for this issue is to reduce the number of posts-per-page to 1, as per eg http://wordpress.org/support/topic/custom-post-type-pagination-404-on-last-page
So, assuming you're happy with a global setting of 1 posts-per-page (remember you'd need to override this manually in your custom queries), here's the code:
functions.php:
...
function get_users_posts_last($userDisplayName = 'Admin', $categoryName = '') {
global $wpdb, $paged, $max_num_pages;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = 5;
$offset = ($paged - 1)*$post_per_page;
$sql = "
SELECT SQL_CALC_FOUND_ROWS q.* FROM
(
(
SELECT
p.*
FROM
{$wpdb->posts} p
INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
WHERE
tt.taxonomy = 'category'
AND p.post_status = 'publish'
AND p.post_type = 'post'
AND u.display_name != '{$userDisplayName}'
" . ( $categoryName != '' ? "AND t.name = '{$categoryName}'" : "" ) . "
ORDER BY
p.post_title ASC
)
UNION
(
SELECT
p.*
FROM
{$wpdb->posts} p
INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
WHERE
tt.taxonomy = 'category'
AND p.post_status = 'publish'
AND p.post_type = 'post'
AND u.display_name = '{$userDisplayName}'
" . ( $categoryName != '' ? "AND t.name = '{$categoryName}'" : "" ) . "
ORDER BY
p.post_title ASC
)
) q
LIMIT {$offset}, {$post_per_page};
";
$sql_result = $wpdb->get_results( $sql, OBJECT);
$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
$max_num_pages = ceil($sql_posts_total / $post_per_page);
return $sql_result;
}
...
category.php:
...
$postList = get_users_posts_last('admin'); // Note you can also pass a category name if necessary
if($postList) {
global $post;
foreach( $postList as $key=>$post ) {
setup_postdata($post);
// Render the post here
?>
<header class='entry-header'><h1 class='entry-title'><?php the_title(); ?></h1></header>
<div class='entry-content'><?php the_content(); ?></div>
<?php
}
// Render pagination here
?>
<div class="navigation">
<div class="previous panel"><?php previous_posts_link('« Previous page',$max_num_pages) ?></div>
<div class="next panel"><?php next_posts_link('Next page »',$max_num_pages) ?></div>
</div>
<?php
}
...
Or, just set up two separate queries ;-)
I am running a competition which is based on WP Custom Fields. I am trying to count all meta values of a meta_key='odd' for a specific user. I am using the formula below but it's not returning any result.
$meta_key = 'odd';
$post_author = 'Admin';
$odd = $wpdb->get_var( $wpdb->prepare(
"
SELECT Count(meta_value)
FROM $wpdb->postmeta
INNER JOIN $wpdb->posts ON $wpdb->postmeta->post_id = $wpdb->posts->ID
WHERE $wpdb->postmeta->meta_key = 'odd' AND $wpdb->posts->post_author = 'Admin'
",
$meta_key, $post_author
) );
echo "<p>Total odd {$odd}</p>";
Anyone can help me? Thanks in advance.
You are mixing up the $wpdb variables and the $post variables - for your JOIN, for example, you can't use $wpdb->postmeta->post_id, it would be {$wpdb->postmeta}.post_id, and would be even better to just use table aliases. Your prepare() is also not passing in your meta_key or author because you don't have %s placeholders for them
$odd = $wpdb->get_var( $wpdb->prepare(
"
SELECT count(meta_value)
FROM {$wpdb->postmeta} pm
INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
WHERE pm.meta_key = %s AND p.post_author = %s
",
$meta_key, $post_author
) );
I have a movie-database, i want to know which movies actor A and B has both been featured in.
function getmoviefromactor(){
global $wp_query;
global $wpdb;
global $post;
$loop = new WP_Query(array(
'post_type' => 'movies',
'actors' => 'A', 'B',
'posts_per_page' =>-1,
));
print_r($loop);
while ( $loop->have_posts() ) : $loop->the_post();
?>
<h2 class="entry-title"><?php the_title(); ?></h2>
<?php
the_content();
endwhile;
}
The problem with this code is that Wordpress by default is searching for Actor A or B and displaying every movie they've been featured in and not just the movie(s) they've both been featured in.
Thanks,
Marten
EDIT:
I think im almost there, im stuck in a SQL-query, it works perfect if i just search for one of the actors, the problem accors when i search for both, which results in an empty array.
When i do the manual search in the SQL query i see duplicate content with different term.slugs, is there any workaround for this?
global $wpdb;
$querystr = "
SELECT *
FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT JOIN $wpdb->terms ON($wpdb->term_taxonomy.term_id = $wpdb->terms.term_id)
WHERE $wpdb->posts.post_type = 'movies'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->term_taxonomy.taxonomy = 'actors'
AND $wpdb->terms.slug = 'A'
AND $wpdb->terms.slug = 'B'
ORDER BY $wpdb->posts.post_date DESC";
$pageposts = $wpdb->get_results($querystr, OBJECT);
print_r($pageposts);
All the best,
Marten
try this:
'actors' => array('A', 'B')
After doing some digging and experimenting, found a way to do it right. It involves posts_join and posts_where filters:
$actor1 = 'A';
$actor2 = 'B';
function join_it($join) {
$join = " INNER JOIN $wpdb->term_relationships tr1 ON($wpdb->posts.ID = tr1.object_id)
INNER JOIN $wpdb->term_taxonomy tt1 ON(tr1.term_taxonomy_id = tt1.term_taxonomy_id)
INNER JOIN $wpdb->terms t1 ON(tt1.term_id = t1.term_id)
INNER JOIN $wpdb->term_relationships tr2 ON($wpdb->posts.ID = tr2.object_id)
INNER JOIN $wpdb->term_taxonomy tt2 ON(tr2.term_taxonomy_id = tt2.term_taxonomy_id)
INNER JOIN $wpdb->terms t2 ON(tt2.term_id = t2.term_id)";
return $join;
}
function where_it($where) {
global $actor1;
global $actor2;
$where = " WHERE $wpdb->posts.post_type = 'movies'
AND tt1.taxonomy = 'actors'
AND tt2.taxonomy = 'actors'
AND t1.slug = {$actor1}
AND t2.slug = {$actor2}";
}
function getmoviefromactor(){
global $wp_query;
global $wpdb;
global $post;
add_filter('posts_join','join_it',10);
add_filter('posts_where','where_it',10);
$loop = new WP_Query();
remove_filter('posts_join','join_it',10);
remove_filter('posts_where','where_it',10);
print_r($loop);
while ( $loop->have_posts() ) : $loop->the_post();
?>
<h2 class="entry-title"><?php the_title(); ?></h2>
<?php
the_content();
endwhile;
}
The posts_where and posts_join filters adds where and join clauses respectively to the loop. I tested a similar code with my own site but if it doesn't work, please let me know.