how to eliminate a particular category from query - php

I have been presented with this code. The code displays the title headings of the latest 10 WordPress posts from the database. What I need to do is to eliminate a particular category from this. Can anyone help?
<?php require_once 'news/wp-config.php';
$howMany = 0;
$query ="SELECT `ID`, `post_title`,'post_category', `guid`,SUBSTRING_INDEX(`post_content`, ' ', 100) AS `post_excerpt` FROM $wpdb->posts WHERE `post_status`= \"publish\" AND `post_type` = \"post\" ";
$posts = $wpdb->get_results($query);
$posts = array_reverse($posts);
foreach($posts as $post)
{
if($howmany<10)
{
$link = $post->guid;
echo "<li><a target='_blank' href='$link'>$post->post_title</a></li>";
$howmany++;
}
}
?>

Or, you could use a second loop, something like this :
<div>
<h3>Fresh Posts</h3>
<ul>
<?php
$my_query = new WP_Query("cat=-3&order=DESC&posts_per_page=10");
echo "<pre>"; print_r($my_query->query_vars); echo "</pre>"; // shows the variables used to parse the query
echo "<code style='width: 175px;'>"; print_r($my_query->request); echo "</code>"; // shows the parsed query
while ($my_query->have_posts()) : $my_query->the_post(); //standard loop stuff
$do_not_duplicate[] = $post->ID;?>
<li id="post-<?php the_ID(); ?>"><?php the_title(); ?></li>
<?php endwhile; ?>
</ul>
</div>
once again WP 2.8.x. Lots of good info here : WordPress loop documentation

Determine the category you don't need and add an extra AND to your WHERE clause:
AND post_category != 3

You can do it either of 2 places. The most efficient is to do it in the query:
$query ="SELECT ID, post_title, post_category, guid, SUBSTRING_INDEX(post_content, ' ', 100) AS `post_excerpt`
FROM $wpdb->posts
WHERE post_status= 'publish'
AND post_type = 'post'
AND post_category!= 'unwanted string' ";
The other place to do it, if for some reason you need all the results, but you want to use the unwanted category somewhere else, is when you retrieve the results:
if($howmany<10 && post['post_category']!='unwanted string') {

'Noticeboard' is the name of the category i want to eliminate. but if i write that, it dispalys a parse error.
Because you must insert the category ID in the query, not the category name.
To get that, just watch in the database wp_categories table.
Some links about wordpress database:
http://blog.kapish.co.in/2008/01/18/wordpress-database-schema/
http://wpbits.wordpress.com/2007/08/08/a-look-inside-the-wordpress-database/
Anyway, I think it's more hard than this. Look at post2cat table.
So, you have to do a subquery.

I am not sure which WP version you are using, so this 'answer' has a few caveats.
Caveat 1 : This is not a complete answer, more like a pointer
Caveat 2 : The query below works with WP 2.8.x so YMMV
The query below shows how to link posts back to their categories. You can use the NOT IN mySQL operator to exclude the category you do not want by its ID
SELECT
wp_posts.*
FROM
wp_posts
INNER JOIN
wp_term_relationships
ON
(wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN
wp_term_taxonomy
ON
(wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id)
WHERE
wp_term_taxonomy.taxonomy = 'category'
AND
wp_term_taxonomy.term_id NOT IN ('3')
AND
wp_posts.post_type = 'post'
AND
(wp_posts.post_status = 'publish' OR wp_posts.post_status = 'future')
GROUP BY
wp_posts.ID
ORDER BY
wp_posts.post_date
DESC
The line breaks and indenting are idiosyncratic, but (hopefully) make it easier for you to see what is going on with this query.
I hope this helps.

Related

WordPress: Exclude a parent page with get_pages()

I have the following code:
<?php $pages = get_pages('exclude=10'); ?>
<?php foreach ( $pages as $page ) : ?>
<?php echo $page->post_title; ?>
<?php endforeach; ?>
I would like to exclude page id 10, but I would still like to include its subpages.
However if I try to include them with the include parameter, they still don’t show up.
There are several default ways wp query to get child pages of current page. but I will prefer this. You can use WordPress get_results() function and write an SQL query like this
global $wpdb;
$child_pages = $wpdb->get_results("
SELECT * FROM {$wpdb->posts} AS p
WHERE p.post_type LIKE 'page'
AND p.post_parent LIKE 0
AND p.id NOT IN (
SELECT post_parent
FROM {$wpdb->posts} AS p
WHERE p.post_type = 'page'
AND p.post_parent != '0'
GROUP BY post_parent
)
");

SQL Fetching Woocommerce Product Thumbnail From DB

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>";
}

How to combine multiple SQL queries into 1 and output it as PHP array

I am building something that is essentially a simple blog platform in PHP and MySQL.
Like almost every blog, the index page will basically pull all the posts from the database and loop them onto the page. I have that figured out.
Each post will have an unknown number of tags associated with it. I want to be able to echo out those tag names along with each post.
What I am doing now is running another query for each post that uses the post's id to find all the tags for that post. I'm including this query in the original loop that gets each post. So essentially, if there are 100 posts returned, I would be running an additional query for EACH of those 100 posts... which is a lot for one page obviously. I know there has to be a better way to handle this.
But how do I get an unkown number of posts, and an unknown number of tags for each of those posts, in one query. And how then do I loop through them in PHP once I have them. My guess is to return them in some sort of nested array???
Here's what I'm currently doing:
function get_all_posts() {
global $pdo;
$query = $pdo->prepare('SELECT content, id FROM posts ORDER BY id DESC');
$query->execute();
$posts = $query->fetchAll(PDO::FETCH_ASSOC);
return $posts;
}
And then I echo those results like such:
<?php $posts = get_all_posts(); foreach ($posts as $post): ?>
<div class="post-box">
<p><?php echo $post['content']; ?></p>
<ul>
<?php $tags = get_all_tags_per_post($post['id']); foreach ($tags as $tag): ?>
<li><?php echo $tag['name']; ?></li>
<?php endforeach; ?>
</ul>
</div><!-- /.post-box -->
<?php endforeach; ?>
As you can see in that, inside of each returned post, I'm running another query to get the tags:
function get_all_tags_per_post($pid) {
global $pdo;
$query = $pdo->prepare('SELECT t.name AS name, t.id AS tid FROM tags AS t JOIN posts_tags AS pt ON pt.tag_id = t.id WHERE pt.post_id = :pid ORDER BY tid ASC');
$query->bindValue(':pid', $pid);
$query->execute();
$tags = $query->fetchAll(PDO::FETCH_ASSOC);
return $tags;
}
I want to combine those two queries, essentially, and then be able to print the output onto my page in PHP.
Why not join Posts with the other tables?
SELECT t.name AS name,
t.id AS tid,
p.id as pid,
p.content
FROM tags AS t
INNER JOIN posts_tags AS pt
ON pt.tag_id = t.id
INNER JOIN posts AS p
ON p.id = pt.post_id
WHERE pt.post_id = :pid
ORDER BY p.id DESC, t.id ASC

Wordpress - Order by author if different than "admin"

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 ;-)

Very very slow query. How can I improve it?

the following query is used in my Wordpress blog, it gets the categories that a user has posted in. When he has a post in the category, the name of the category is shown.
It is a very very slow query because it is a big database and I have problems with the hosting company.
I have 3 categories, with id 3 called News, 4 called Articles and 5 called Others. My code is:
<?php
$author = get_query_var('author');
$categories = $wpdb->get_results("
SELECT DISTINCT(terms.term_id) as ID, terms.name, terms.slug, tax.description
FROM $wpdb->posts as posts
LEFT JOIN $wpdb->term_relationships as relationships ON posts.ID = relationships.object_ID
LEFT JOIN $wpdb->term_taxonomy as tax ON relationships.term_taxonomy_id = tax.term_taxonomy_id
LEFT JOIN $wpdb->terms as terms ON tax.term_id = terms.term_id
WHERE 1=1 AND (
posts.post_status = 'publish' AND
posts.post_author = '{$post->post_author}' AND
tax.taxonomy = 'category' )
ORDER BY terms.term_id ASC
");
?>
<ul>
<?php foreach($categories as $category) : ?>
<?php if ( ($category->ID == '3') || ($category->ID == '4') || ($category->ID == '5')) { ?>
<li>
<a href="<?php echo get_category_link( $category->ID ); ?>/?author_name=<?php echo $curuser->user_login; ?>" title="<?php echo $category->name ?>">
<?php echo $category->name; ?>
</a>
</li>
<?php } ?>
<?php endforeach; ?>
</ul>
Thank you all!
Judging by the looks of the wordpress database I have lying around, I'm guessing there is no index on the columns you are using in your WHERE clause for the wp_posts table.
Try adding an index like this:
ALTER TABLE wp_posts ADD INDEX (post_author,post_status).
I bet you see a speed up from that.
The best thing to do however is to run that query manually with an EXPLAIN in front of the SELECT, and analyze the output.
Have you indexes on posts.ID, relationships.object_ID, relationships.term_taxonomy_id, tax.term_taxonomy_id, tax.term_id, terms.term_id, posts.post_status, posts.post_author and tax.taxonomy ?

Categories