In the archive.php file of my custom theme, I want to only show posts of a certain category. It was suggested elsewhere that I add this before if( have_posts() ):
$posts = get_posts('category=1');
However, that seems to disregard all the other filtering that may be in place (such as post date, post author, etc.).
I don't want to remove any other filtering that is already in place. All I want to do is say: "AND ONLY SHOW POSTS WITH CATEGORY=1". Doable?
You could try merging your new filters into the existing filters:
global $wp_query;
$posts = get_posts(
array_merge(
array('category' => '1'),
$wp_query->query
)
);
Related
I have around 2000 products which has no tags. Now i want to update tag for those products. I want to set post_title=tag for all 2000 products.
Below code works for a product to set CUSTOM TAG to PRODUCT
wp_set_object_terms($productID, array('product_tag1','product_tag2','product_tag3'), 'product_tag');
Instead of complicating the work from front end for each product.
Can someone please guide me how to set post_title=tag using php for all my products.
You can loop through your products and assign the tags, maybe something like this:
Update:
If you want to just add a tag to posts which dont have any existing tags, you could do something like this:
<?php
add_action('init', 'add_tags_products');
function add_tags_products()
{
$args = array(
'post_type' => 'products', // your product post type
'posts_per_page' => - 1,
);
$posts = get_posts($args);
foreach ($posts as $post):
setup_postdata($post);
// get the title of the post
$title = get_the_title($post->ID);
// check to see if the post has any tags
if( ! has_term( '', 'product_tag', $post->ID ) ) :
// create the term
wp_set_object_terms($post->ID, array($title), 'product_tag');
endif;
wp_reset_postdata();
endforeach;
}
Paste the above code in your index.php file for testing and visit the site, and after all the tags are set, remove it. Also backup first in case something happens.
I have following structure
Services
-Page_1
-Page_2
--Page_3
--Page_4
I use Wp-query to get pages. This is my args:
<?php $args = array(
'post_type' => 'page',
'post_parent' => '45'
); ?>
45 is ID of Services page.
But I only get first level Page_1 and Page_2. How do I get all pages? I'm using Advanced Custom Fields plugin so using get_pages() is not a good option, is it?
As mentioned in your comments, the easiest solutions is to actually use get_pages(). You can still grab meta data of posts if you are able to get the the ID of the page (which you can with get_pages()) so you should still be able to ACF's custom fields.
Here's an example of get_pages():
$args = array(
'child_of' => 45,
'post_type' => 'page',
);
$pages = get_pages($args);
The main difference between get_pages() and WP_Query that we want to focus on here is the 'child-of'=>45 paramater vs the 'post_parent'=>45.
The child-of argument will grab ALL children throughout the hierarchy, i.e. children and children's children etc.
In contrast, the post-parent argument of WP_Query will only grab direct children of the page.
Using in conjunction with ACF
If you need to grab custom fields from ACF, you will still be able to use get_post_meta().
If your custom field includes an array of values, you will need to unserialize it first and then loop through the values like this:
$meta = get_post_meta( $post->ID, 'acf_meta_key', true ); //grab the post meta using WordPress core function
$array = unserialize( $meta ); //unserialize the field into an array
foreach ( $array as $value ) { //loop through the array
echo $value .'<br>';
}
I'm having a bad time trying to make wordpress querys excluding categories unless asked.
I mean, if not specifically asked (ex: $args= array('cat'=>'-35')) , the loop excludes this category.
what I got so far:
function exclude_categories( $wp_query ) {
$excluded_cats = array( '-35' , '-36' );
set_query_var( 'category__not_in', $excluded );
}
add_action( 'pre_get_posts', 'exclude_categories' );
This is doing ok excluding posts with this category but then if I try to ask for posts with this category it wont display any.
Any sugestions?
Can you show the whole code with when you ask for posts including this category?
Basically, you can set these parameters to inlucde or exclude categories in the query.
'category__not_in'=> array(1,2),
'category__in' => array(3,3)
However in your example you have already pre-set set_query_var( 'category__not_in', $excluded );
categories so even if you use category__in the query won't use it because of the usage of category__not_in. You need to set this parameter to empty value.
I am trying to create a series of pages that display the posts within a single category. To do this I use the following PHP code:
<?php
$args = array( 'category' => '$CATEGORY', 'numberposts' => 10000000000);
$myposts = get_posts( $args );
foreach($myposts as $post) :
setup_postdata($post);
?>
My problem is that the $CATEGORY does not seem to contain the category as a string. I have tried using both %s and $id but as I have not declared that it is the category id I am wanting it fails to work. The resulting output has been either an error or all the posts regardless of category.
What argument will convey the category string?
Below is a page illustrating the problem. This is a category page, meaning it should hold all the necessary info. If it was working it would only show the topmost post as it is the only post en site that has the "Press Release" category. Worth mentioning that I have another page just like it called "Dokument" and it displays the press release.
Page: http://www.skinwellness.se/category/pressrelease/
EDIT
I did not notice this before, but it seems that you are using the bundled theme twentythirteen. Simply delete the category.php from your child theme. If you have made changes to the parent theme directly, you should get a fresh copy of the theme, and create a child theme with all your modifications. Never make changes to a theme that you did not write. When such themes update, all you changes will be gone forever
You should then just need the pre_get_posts section in your child theme's functions.php to make everyone work
ORIGINAL ANSWER
You problem is purely your custom loop. As explained in the linked post, you should not be using custom queries in place of the main query on any type of archive page or on your home page
To solve this, revert back to the default loop. This is all you should have. No get_posts or foreach loops
if( have_posts() ) {
while( have_posts() ) {
the_post();
// Add your loop elements here like the_title() and the_content()
}
}
This should fix the problem that when you visit a category page, only the category been viewed will be viewed, no posts from other categories will be shown
Now, if you need to change anything on your category page, use pre_get_posts to do that. Make use of the is_category() conditional tag to target your category pages only. You can also target a specific category with this tag
Say for instance, you need to change the posts per page on you category page, as your case, display all posts with no pagination, you can do this in your functions.php
function so26589648_category_ppp( $query ) {
if ( !is_admin() && $query->is_category() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '-1' );
}
}
add_action( 'pre_get_posts', 'so26589648_category_ppp' );
If you need to for example change the order to ASC and need to order posts by author, you can do this
function so26589648_category_ppp( $query ) {
if ( !is_admin() && $query->is_category() && $query->is_main_query() ) {
$query->set( 'posts_per_page', '-1' );
$query->set( 'order', 'ASC' );
$query->set( 'orderby', 'author' );
}
}
add_action( 'pre_get_posts', 'so26589648_category_ppp' );
You should see WP_Query for all available parameters to use
I am using Wordpress auto suggests using this snippet of code
and currently it is searching all tags, I want it to search only post titles. Any help is appreciated.
This is sql query calling all the tags which needs to be modified for all posts.
<?php global $wpdb;
$search_tags = $wpdb->get_results("SELECT name from wp_terms WHERE name LIKE '$search%'");
foreach ($search_tags as $mytag)
{
echo $mytag->name. " ";
}
?>
These days i had to do some request in a wordpress theme.
In your case ( getting title can be done easier than getting tags, as in your example link ) the stuff can be done easier (i guess).
Firstly you have to make a php page to get posts. As you maybe know you won't be able to use wp stuff in standalone php files, so your file ( let call it get_posts.php ) will look like
<?php
// Include the file above for being able to use php stuff
// In my case this file was in a folder inside my theme ( my_theme/custom_stuff/get_posts.php ).
// According to this file position you can modify below path to achieve wp-blog-header.php from wp root folder
include( '../../../../wp-blog-header.php' );
// Get all published posts.
$list_posts = get_posts( array( 'numberposts' => -1 ) );
// Get "q" parameter from plugin
$typing = strtolower( $_GET["q"] );
//Save all titles
$list_titles = array();
foreach( $list_posts as $post ) { $list_titles[] = $post->post_title; }
// To see more about this part check search.php from example
foreach( $list_titles as $title ) {
if( strpos( strtolower( $title ), $typing ) ){
echo $title;
}
}
?>
I added some comments trying to help you better.
Now stuff get easy, you only have to call your page through jQuery plugin like
$('#yourInput').autocomplete( "path_to/get_posts.php" );
You can directly use wordpress in-build feature to get all post titles
// The Query
query_posts( 'posts_per_page=-1' );
// The Loop
while ( have_posts() ) : the_post();
echo '<li>';
the_title();
echo '</li>';
endwhile;
None of the answers here answer your real question:
How to query JUST post titles
The "raw SQL" way:
Few important things:
escape search for SQL! (also do that for the tags search!) use $GLOBALS['wpdb']->esc_like()
if you only need 1 column, you can use $GLOBALS['wpdb']->get_col()$GLOBALS['wpdb']->get_results() is if you want to fetch more columns in one row
use $GLOBALS['wpdb']->tableBaseName to make your code portable - takes care of the prefixe.g. $GLOBALS['wpdb']->posts
When querying posts you must also think about which post_type and post_status you want to query=> usually the post_status you want ispublish, but post_type may vary based on what you want
WordPress table "posts" contains ALL post types - post, page, custom, but also navigation, contact forms etc. could be there! => I strongly advice to use explicit post_type condition(s) in WHERE ! :)
...$GLOBALS is same as globalizing variabl -today performance difference is little
<?php
// to get ALL published post titles of ALL post types (posts, pages, custom post types, ...
$search_post_titles = $GLOBALS['wpdb']->get_col(
"SELECT post_title from {$GLOBALS['wpdb']->posts}
WHERE (
(post_status = 'publish')
AND
(post_title LIKE '{$GLOBALS['wpdb']->esc_like($search)}%')
)
ORDER BY post_title ASC
"); // I also added ordering by title (ascending)
// to only get post titles of Posts(Blog)
// you would add this to conditions inside the WHERE()
// AND (post_type = 'post')
// for Posts&Pages
// AND ((post_type = 'post') OR (post_type = 'page'))
// test output:
foreach ($search_post_titles as $my_title) {
echo $my_title . " ";
}
?>
The WP_Query way
This is more wordpress but has a little overhead, because although there is a fields param for new WP_Query()/get_posts(), it only has options:
'all' - all fields (also default), 'ids' - just ids, 'id=>parent' - ... if you pass anything else, you still get all, so you still need to add "all" BUT - WP however has filters for altering fields in SELECT.
I tried to make it the same as the raw SQL version, but it depends on how does WP does it's "search" - which I think is %search% for 1 word + some more logic if there are more words. You could leverage the $clauses filter used for fields to also add your custom where INSTEAD of adding the 's' into $args (remember to append to not-lose existing WHEREs $clauses['where' .= "AND ...;). Also post_type => 'any' does not produce always the same results as the raw query in cases like Navigation, Contact forms etc...
Also WP_Query sanitizes the input variables so actually don't escape $args!
<?php
$args = [
'fields' => 'all', // must give all here and filter SELECT(fields) clause later!
'posts_per_page' => -1, // -1 == get all
'post_status' => 'publish',
's' => $search,
// I also added ordering by title (ascending):
'orderby' => 'title',
'order' => 'ASC',
'post_type' => 'any', // all "normal" post types
// 'post_type' => 'post', // only "blog" Posts
// 'post_type' => ['post', 'page'], // only blog Posts & Pages
];
$onlyTitlesFilter = function($clauses, $query) {
// "fields" overrides the column list after "SELECT" in query
$clauses['fields'] = "{$GLOBALS['wpdb']->posts}.post_title";
return $clauses; // !FILTER! MUST RETURN!
};
$onlyTitlesFilterPriority = 999;
// add filter only for this query
add_filter('posts_clauses', $onlyTitlesFilter, $onlyTitlesFilterPriority, 2);
// Pro-tip: don't use variable names like $post, $posts - they conflict with WP globals!
$my_posts = (new WP_Query($args))->get_posts();
// !IMPORTANT!
// !remove the filter right after so we don't affect other queries!
remove_filter('posts_clauses', $onlyTitlesFilter, $onlyTitlesFilterPriority);
// test output:
// note that I used "my"_post NOT just $post (that's a global!)
foreach($my_posts as $my_post) {
echo $my_post->post_title . " ";
}
?>
Don't be confused - you will still get the array of WP_Posts - WP will throw some default properties&values into it, but in reality it will only query and fill-in with real values the fields you specify in the filter.
PS: I've tested these - they are working codes (at least on WP 5.4 and PHP7 :) )