I want to have Wordpress post title in array.
I have my post titles in my custom post type as names of people with their surnames. I want to display my posts based alphabetically on their surnames and store it in an array. How do I do this in the loop?
You can retrieve the posts for your custom post type using WP_Query, and then run through each of them to get the titles.
// just get IDs rather than whole post object - more efficient
// as you only require the title
$post_ids = new WP_Query(array(
'post_type' => 'custom_post_type_name', // replace with CPT name
'fields' => 'ids',
'orderby' => 'meta_value',
'meta_key' => 'surname_field_name' // replace with custom field name
));
$post_titles = array();
// go through each of the retrieved ids and get the title
if ($post_ids->have_posts()):
foreach( $post_ids->posts as $id ):
// get the post title, and apply any filters which plugins may have added
// (get_the_title returns unfiltered value)
$post_titles[] = apply_filters('the_title', get_the_title($id));
endforeach;
endif;
Using WP_Query has the benefit that it does not alter the main loop on your page, and you can get the posts in the order that your require by using orderby along with the name of the custom field which contains the surname.
You can create an array outside the loop, then get the array filled up with the names, than sort the array.
<?php
// the array for the names
$name_array = array();
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
$name_array[] = $post->title;
//
// Post Content here
//
} // end while
if ( sizeof( $name_array ) > 0 ) {
sort( $name_array );
} // end if for sizeof()
} // end if
?>
If you cannot create the array outside The Loop, than you may move it under if ( have_posts() ) {.
Important note: this solution only contains the names in your current loop, so if your query does not hold all the posts, or is offset / paged, etc. then the array will not get all the names you have in your custom post type. If you would like to have all the names in the array and your loop query does not hold all the posts, then you have to query again - just for the titles (names).
Related
I have a pretty complicated query that I have not been able to get to work the way I need it to.
I have a Wordpress install using the plugins WP Courseware and ACF. I need to display a page of courses associated with the current user. I want the links to lead the user to the course "home" pages that the user should hit prior to starting the course. I have created course "home" pages, but the problem is WP Courseware has no way to associate a page with a course. So I had to use an ACF options repeater that associates the course ID with whatever course pages are necessary. The only way I know that one of those associated pages is the course "home" page is by the template I use for course home pages.
So the loops within loops need to first determine what courses the current user has access to, get those course IDs, loop the ACF options repeater to find the pages associated with those course IDs, then of those pages loop to find out which one (there is only one per course) uses the course home page template. This last loop I discovered needs to be a WP_Query loop as that's the only way to query for a Wordpress template.
I am lost in loops and I'm having the hardest time. I thought it might be simpler and most direct to use the WP_Query to query an array meta_queries of both the Wordpress template and the ACF repeater (to determine is the ACF repeater course ID matches the course ID the user has access to) but my attempts at querying ACF repeater sub fields is not working.
Here's my code:
$user = wp_get_current_user();
$user_id = $user->ID;
$user_course_list = WPCW_users_getUserCourseList($user_id);
$course_association_arr = get_field('course_association', 'option');
// Loop through user's courses
foreach ( $user_course_list as $user_course ) :
$course_id = $user_course->course_id;
$course_title = $user_course->course_title;
// Loop through the ACF course ID/page associations
foreach ( $course_association_arr as $course_association ) :
$assoc_course_id = $course_association['wp_courseware_id'];
if ( $course_id == $assoc_course_id ) :
// Loop through the ACF associated pages
foreach ( $course_association['associated_pages'] as $associated_page ) :
$page_id = $associated_page->ID;
$page_url = $associated_page->guid;
echo '<li>'. $course_title . '</li>';
endforeach;
endif;
endforeach;
endforeach;
This displays all pages associated with a user's courses, not just the ones using the course home template. I somehow have to incorporate a WP_Query with these args in there and nothing I have done has worked:
$args = array(
'post_type' => 'page',
'meta_query' => array(
array(
'key' => '_wp_page_template',
'value' => 'page-course-home.php',
),
)
);
If I could somehow turn the WP query into an if statement (if template = page-course-home.php) I could have that inside the associated pages query to only show course home pages. Or there maybe another more brilliant way to do what I need to do. I appreciate all feedback.
Ok I got something to work! I think spending so much time framing the question here helped me see one way I could do it:
$user = wp_get_current_user();
$user_id = $user->ID;
$user_course_list = WPCW_users_getUserCourseList($user_id);
$course_association_arr = get_field('course_association', 'option');
// Loop through user's courses
foreach ( $user_course_list as $user_course ) :
$course_id = $user_course->course_id;
$course_title = $user_course->course_title;
// Loop through the ACF course ID/page associations
foreach ( $course_association_arr as $course_association ) :
$assoc_course_id = $course_association['wp_courseware_id'];
if ( $course_id == $assoc_course_id ) :
// Loop through the ACF associated pages
foreach ( $course_association['associated_pages'] as $associated_page ) :
$page_id = $associated_page->ID;
$page_url = $associated_page->guid;
$args = array(
'post_type' => 'page',
'page_id' => $page_id,
'meta_query' => array(
array(
'key' => '_wp_page_template',
'value' => 'page-course-home.php',
),
)
);
$course_assoc_pages = new WP_Query( $args );
if( $course_assoc_pages->have_posts() ) :
while ( $course_assoc_pages->have_posts() ) : $course_assoc_pages->the_post();
echo '<li>'. $course_title . '</li>';
endwhile;
endif;
wp_reset_query();
endforeach;
endif;
endforeach;
endforeach;
This seems a bit cumbersome, but it works. I'm not sure if it would be better but it seems more elegant to incorporate the ACF subfield query into the meta query, so could eliminate two of the loops. If anyone has any thoughts on this I would love to hear them.
I have two different custom post types, portfolio and project.
On the single-project.php page, I want to display content where get_field('housetype') in project matches with the taxonomy of the portfolio. The content comes from the project custom post type.
So far I've managed to get all relevant information but I cant find a way to only display the result where there's a match between the housetype and the taxonomy.
I thinking that pushing the item in an array when it's a match and then using a foreach loop to display the content in a table. I just don't know how to do this..
Here's my code so far:
$args = array(
'post_type' => array( 'portfolio', 'project' ));
$my_query = new WP_Query( $args );
if( $my_query->have_posts()) {
while ($my_query->have_posts()) : $my_query->the_post();
//Returns All Term Items for "my_taxonomy"
$term_list_portfolio = wp_get_post_terms($post->ID, 'portfolio_category', array("fields" => "all"));
// Just get the category
$category = $term_list[0]->name;
// Get the house type
$houseType = get_field('hustyp');
$result = array($term_list[0]->name, get_field('hustyp'));
endwhile;
}
You would have to check with an if statement somewhere.
Something similar to this:
// Get the house type
$houseType = get_field('hustyp');
if($houseType == $term_list[0]->name){
//Here you could save your post object
//(that you declare before your while loop) to an array
//or render what you want directly
$posts[] = $post;
}
$result = array($term_list[0]->name, get_field('hustyp'));
I am trying to create a list of posts from a specific category inside a Wordpress page template by the function query_posts.
If I type in the category_name value directly in the query_posts' array value (for example 'category_name' => 'france-category') it IS working correctly.
But I would like to be able to define the category through a custom field in the page editor.
The get_field("custom-field") function retrieves the value I set in my custom field.
So I tried to put the value of my custom field into a variable and then retrieve the variable inside the array' value:
<?php
$category = get_field("france-category");
// The Query
query_posts( array ( 'category_name' => 'echo $category' ) );
// The Loop
while ( have_posts() ) : the_post();
the_title();
endwhile;
// Reset Query
wp_reset_query();
?>
But for some reason this isn't working. Is it not possible to use a variable within an array? Or Can anyone tell me whats else I am doing wrong?
In your code, try replacing 'echo $category' with just $category. Because you don't need to use the echo! Since the $category field would be having the value that you might have already fetched. So you could just pass that variable.
So, instead of this line:
query_posts( array ( 'category_name' => 'echo $category' ) );
try this:
query_posts( array ( 'category_name' => $category ) );
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 :) )
I have an array of post IDs contained in $postarray. I would like to print the posts corresponding to these IDs in Wordpress.
The code I am using is as follows:
query_posts(array('post__in' => $postarray));
if (have_posts()) :
while (have_posts()) : the_post();
the_title();
the_excerpt();
endwhile;
endif;
Despite this, the loop prints the most recent posts and not the posts contained in the array. How can I have wordpress utilize the post IDs I supply in the array and print those posts in order?
You may have to break out of the standard WP Loop for this...
Try and use the get_post() function which takes the ID of a post and returns an object containing a the details of the post in the usual OBJECT or Associate or Numeric Array format.
See full-explanation of get_post().
You can come up with a custom routine to parse each item in the array. Here's a brief example:
function get_posts_by_ids( $postarray = null ) {
if( is_array( $postarray ) )
foreach( $postarray as $post ) {
$post_details = get_post( $post[0] );
// Title
echo $post_details->post_title;
//Body
echo $post_details->post_content ;
}
}
Hope this helps :)