WP Shortcode to display posts by ID - php

Currently, I have a shortcode that displays a specific set of posts by specifying the post ID inside the function. But I would like to change this so the user can specify the post IDs as shortcode attributes.
Currently
[fsgrid]
Desired:
[fsgrid id="1, 2, 3"]
Here is the current code
public function shortcode_handler($atts) {
$atts = shortcode_atts(
array(
'posts_per_page' => 100 ,
'orderby' => 'post__in',
'post__in' => array(1, 2, 3)
), $atts, 'fsgrid'
);
return $this->grid($atts);
}
How do I change it? Any help is much appreciated.

explode will be your best option. Firstly extract your shortcode ids attributes then explode the comma separated string to an array.
See: https://codex.wordpress.org/Function_Reference/shortcode_atts
public function shortcode_handler($atts) {
extract(shortcode_atts(array(
'id' => null
), $atts, 'fsgrid'));
$post_ids = explode(",", strval($id));
$args = array(
'posts_per_page' => 100 ,
'orderby' => 'post__in',
'post__in' => $post_ids
);
return $this->grid($args);
}
Then you call you shortcode [fsgrid id="1,2,3"]

Related

WordPress: Combine two loops with different amount of posts

I want to show a random selection of 4 new products in WooCommerce.
For that I'm using a first loop to get the 20 newest products.
Like this:
$args= array(
'post_type' => 'product',
'posts_per_page' => 20,
'orderby' => 'date',
);
Now I've a second loop to reduce the products to 4 in a random order:
$args_new = array(
'posts_per_page' => 4,
'orderby' => 'rand',
);
In the end I merge the two loops:
$final_args = array_merge( $args, $args_new );
But that doesn't work. Is there any other way to achieve it?
General knowledge
The post_type argument accept String or Array.
Argument
Description
post_type
(String/Array) – use post types. Retrieves posts by post types, default value is post. If tax_query is set for a query, the default value becomes any.
Source # https://developer.wordpress.org/reference/classes/wp_query/#post-type-parameters
Merging queries
In crude terms we want to combine 2 posts queries, retrieve each posts ID, push them to a new array and open a new query.
Keep in mind that if you want your 4 posts to be random (as you stated in the comments) they might be some duplicates of the last 20 from the first query. Don't forget to offset the second query.
<?php
// First query
$args_1 = get_posts( array(
'post_type' => 'dogs',
'post_status' => 'publish',
'post_count' => 20,
) );
// Second query
$args_2 = get_posts( array(
'post_type' => 'dogs',
'post_status' => 'publish',
'post_count' => 4,
'offset' => 20,
'orderby' => RAND,
) );
// Merge queries
$posts = array_merge( $args_1, $args_2 );
// Push posts IDs to new array
$identifiers = array();
foreach ( $posts as $post ) {
array_push( $identifiers, $post->ID );
};
// Third query
$query = new WP_Query( array(
'post_status' => 'publish',
'post_count' => 24,
'post_in' => array_unique( $identifiers ),
) );
var_dump( $query );

Find tags by custom field value - Wordpress

I'm customizing the admin of wordpress and I've created a new custom input field for the tags of a post.
It's a dropdown list with all the categories of a post. Now, I wanna find all the tags with an specific category. So, I'm using this:
$args = array(
'meta_key' => 'project',
'meta_value' => $idProject,
);
$allTags = get_tags( $args );
Is this the right way to get all the tags that I want? The problem is that the array list with the tags is coming with only one result. It should bring 2 tags with the project id that I'm passing on the variable $args.
Am I missing something?
I found a solution:
$args = array(
'hide_empty' => false, // also retrieve terms which are not used yet
'meta_query' => array(
array(
'key' => 'project',
'value' => $idProject
)
)
);
$terms = get_terms( 'post_tag', $args );

Query product title or slug based on shortcode atts name in Woocommerce

I would like to query a product by it's title or name (slug). The code below will allow me to retrieve a product with a specific tag, however when I attempt to use page or pagename instead of product_tag, no products are returned. I did not see a relevant product_page or similar available unless I have overlooked it. Appreciate insight into where I may have gone wrong.
function woo_products_by_name_shortcode( $atts, $content = null ) {
// Get attributes
extract(shortcode_atts(array( "tags" => '' ), $atts));
ob_start();
// Define Query Arguments
$args = array(
//'post_type' => array('product','product_variation'),
'post_type' => 'product',
'posts_per_page' => 5,
'product_tag' => $tags
);
// Create the new query
$loop = new WP_Query( $args );
// Get products number
$product_count = $loop->post_count;
// If results
if( $product_count > 0 ) :
Update:
For querying products by their slug use "name" argument or by their title use "title" argument:
function woo_products_by_name_shortcode( $atts, $content = null ) {
// Get attributes
extract( shortcode_atts( array(
'tags' => '',
'name' => ''
'title' => ''
), $atts ));
ob_start();
// Define Query Arguments
$loop = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 5,
'product_tag' => $tag,
'name' => $name,
'title' => $title
) );
// Get products number
$product_count = $loop->post_count;
// Test raw output
echo '<pre>'; print_r($loop->posts); echo '</pre>';
Tested and works
Official documentation: WP_query - Post and page parameters

Wordpress foreach loop doesn't finish

I have a little under 1,000 posts of type lp_lesson and I am trying to be able to loop through them all to apply text to a specific custom field.
The below code works for only a few of them. Possibility between 10-15. I wanted to know if it's because I am using wp_enqueue_scripts? I also tried applying this change on wp_login. Both of them update the exact same number of posts and the exact same posts.
I am completely new to php so if I am doing this complete wrong please let me know.
I do believe there's an issue with the loop not finishing before the system just times it out, maybe? I can confirm that all the posts are lp_lesson so the loop is not finishing. Perhaps $args cannot hold an array that big? Any tips are appreciated!
Thanks.
add_action( 'wp_enqueue_scripts', 'win_9388244_format_lp_lesson' );
function win_9388244_format_lp_lesson() {
//Get post type of lp_lesson
$args = array(
'post_type' => 'lp_lesson'
);
$posts = get_posts($args);
foreach($posts as $post) {
update_post_meta( $post->ID, 'wpk_icon_text', 'Test' );
}
}
The default args of get_posts are :
$defaults = array(
'numberposts' => 5,
'category' => 0, 'orderby' => 'date',
'order' => 'DESC', 'include' => array(),
'exclude' => array(), 'meta_key' => '',
'meta_value' =>'', 'post_type' => 'post',
'suppress_filters' => true
);
meaning that if you do not specify these values in your $args variables, wordpress will take these ones by default. If you give a value to numberposts, then wordpress will use this one, and the other default values.
You should set the numberposts. For instance :
$args = array(
'post_type' => 'lp_lesson',
'numberposts' => 99999
);
get_posts function reference

WP Loop with custom array field as argument

I'm trying to do a query with the arguments below. Somehow, WP just doesn't return any posts. I can't figure out what I'm doing wrong! Any help?
Some more info: I have a custom post type that contain featured images. I want them to be displayed in a header slider. Through Advanced Custom Fields plugin I've created a custom field in the posts: 'assigned_page'. It's an array with page ID's on which that specific slide should be displayed. '$current_page' is the ID of the current page that's to be displayed. So, $args should filter the custom post type, and the posts that have the current page ID in their 'assigned_page' array.
// Get the current page ID
global $post;
$current_page = $post->ID;
$string_page = (string)$current_page;
$current_parent_page = $mv_is_subpage->ID;
// Post selection
$args = array (
'post_type' => $post_type,
'posts_per_page' => $posts_per_page,
'orderby' => $orderby,
'order' => $order,
'no_found_rows' => 1,
'meta_query' => array(
array(
'meta_key' => 'assigned_page',
'meta_value' => $string_page,
)
),
);
Then:
$query = new WP_Query( $args );
And then the loop:
while ($query->have_posts()) : $query->the_post();
I guess it should be like this (according to docs at http://codex.wordpress.org/Class_Reference/WP_Query) :
array(
'key' => 'assigned_page',
'value' => $string_page,
)

Categories