Wordpress query to find posts with exactly sentence from search input - php

I am a beginner front-end developer, and these are my first steps with Wordpress.
How can I show posts which have the search term from the search input in their title or in their content? I don't want to use plugins or the built-in Wordpress searching with its reload page.
This is my code:
HTML
<form class="search__form" action="" method="POST">
<div class="search__input-container">
<input type="text" name="search" class="search__input search__input-js" placeholder="Search">
</div>
</form>
JavaScript
$('.search__input-js').on('change', function(){
var search = $('.search__input').val();
search = search.toLowerCase();
$.ajax({
type: 'POST',
url: ajax_options.admin_ajax_url,
data:{
search: search,
action: 'ajax_func'
},
success: function(result) {
$('.return-msg').html('');
$('.return-msg').html(result);
},
error: function(e) {
console.log(e);
}
});
});
Functions.php
function ajax_func() {
wp_reset_postdata();
$search_term = '';
$result = '';
if(isset($_POST['search'])){
$search_term .= $_POST['search'];
}else{
$search_term = '';
}
$args= array(
'post_type' => array('post', 'case-study'),
'HERE'
);
$the_query_posts = new WP_Query( $args );
if ( $the_query_posts->have_posts() ) {
while ( $the_query_posts->have_posts() ) {
$the_query_posts->the_post();
$result .='
<div class="col-lg-4">';
$result .='
<a class="post__link" href="'.get_the_permalink().'">
<div class="post__container">';
if (has_post_thumbnail()) {
$result .= '
'.get_the_post_thumbnail(get_the_ID(), 'post-thumbnail', ['class' => 'post__img', 'alt' => get_the_title()]).'
';
} else {
$result .= '
<img class="img-responsive responsive--full post__img" src="" />
';
}
$result .='
<div class="post__background">
<p class="post__category">'.get_the_category(get_the_ID())[0]->name .'</p>';
$result .='<p class="post__name">'.get_the_title().'</p>';
$result .='<div class="post__desc">'.get_field('post_short_desc').'</div>';
$result .='
</div>
</div>
</a>
</div>';
}
wp_reset_postdata();
} else {
$result .= '<div class="col-12">0 posts</div>';
wp_reset_postdata();
}
echo $result;
die();
}
remove_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
add_action('wp_ajax_nopriv_ajax_func', 'ajax_func');
add_action('wp_ajax_ajax_func', 'ajax_func');
Ajax works correctly, and I know that I should write some function and set up a special WP query to find my posts where I write 'HERE', but I don't know how. Could anybody give me a hint?

WP_Query has a search parameter you can pass into it. It's also built in should you not want to use AJAX ( example.com/?s=query+here ). Altogether it would look like this:
$args= array(
'post_type' => array( 'post', 'case-study' ),
's' => $search_term
);

It's an old topic, I know, but if you are looking for a solution, in doc, in WP_Query class you can see the s parameter, but there's sentence parameter also, even though it doesn't appear in the doc.
$args = array(
'post_type' => array( 'post', 'case-study' ),
'sentence' => true,
's' => $search_term
);

Related

Adding multiple values to a query variable in WordPress

I stumbled upon an issue, where I have registered a custom query variable in Wordpress. However, I would like to pass several values with same custom query and return this in an array, but it redirects/only takes into account the last query value.
I have done like so:
function custom_query_vars( $qvars ) {
$qvars[] = 'filter_fabric';
return $qvars;
}
add_filter( 'query_vars', 'custom_query_vars' );
However, if I pass the url like:
example.com/category/page/2?filter_fabric=cotton&filter_fabric=polyester
I can see in the $query that only the last parameter, in this case 'polyester' is passed, which results in an error with pagination (when I click on a pagination link with the address example.com/category/page/2?filter_fabric=cotton&filter_fabric=polyester it redirects me to example.com/category/page/2?filter_fabric=polyester
Does anyone know how to solve this issue?
Would be of great help!
I have tried adding with this code as well, but it did not work:
function custom_query_vars( $qvars ) {
$qvars[] .= 'filter_fabric';
return $qvars;
}
add_filter( 'query_vars', 'custom_query_vars' );
I would assume it has something to do with a foreach loop, which pushes into into $qvars[] as array, but I am not sure how to do that.
EDIT #1
Here is my code for doing the filter with ajax.
In functions.php
function rg_product_filter() {
//unserialize query string in PHP
//parse_str($_POST['value'], $data); We change this to our custom proper_parse_str function in order to get multiple parameters with same name e.g. "/?filter_tygmaterial=sammet&filter_tygmaterial=bomull"
$data = proper_parse_str($_POST['value']);
$product_color = $data['filter_color'];
$product_material = $data['filter_material'];
$product_fabric = $data['filter_fabric'];
$wpquery_vars = $_POST['query_vars'];
//Get current product category id
$product_category = $wpquery_vars['queried_object'];
$product_cat_id = $product_category['term_id'];
//Get current order + orderby if exists, part 2
$args_orderby = $data['filter_orderby'];
//#TODO: Right now it does not work with pagination.
$per_page = $_POST['per_page'];
$current = $_POST['current'];
$args = array(
'post_type' => 'product',
'posts_per_page' => $per_page,
'paged' => $current,
);
if ($args_orderby) {
if ($args_orderby === 'price') {
$args['orderby'] = 'meta_value_num';
$args['order'] = 'asc';
$args['meta_key'] = '_price';
} elseif ($args_orderby === 'price-desc') {
$args['orderby'] = 'meta_value_num';
$args['order'] = 'desc';
$args['meta_key'] = '_price';
} else {
$args['orderby'] = $args_orderby;
}
}
if ($product_category) {
$args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $product_cat_id,
);
}
if ($product_color) {
$args['tax_query'][] = array(
'taxonomy' => 'pa_color',
'field' => 'slug',
'terms' => $product_color,
);
}
if ($product_material) {
$args['tax_query'][] = array(
'taxonomy' => 'pa_material',
'field' => 'slug',
'terms' => $product_material,
);
}
if ($product_fabric) {
$args['tax_query'][] = array(
'taxonomy' => 'pa_tygmaterial',
'field' => 'slug',
'terms' => $product_fabric,
);
}
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
} else {
do_action( 'woocommerce_no_products_found' );
}
wp_reset_postdata();
wp_die();
}
add_action('wp_ajax_rg_product_filter', 'rg_product_filter');
add_action('wp_ajax_nopriv_rg_product_filter', 'rg_product_filter');
In customjs.js
//WooCommerce Filters using AJAX
window.addEventListener("load", (event) => {
$filterForm = $('#filter-form') ? $('#filter-form') : '';
$filterForm.on('submit', function (e) {
e.preventDefault();
var values = $(this).serialize();
var product_container = $('.woocommerce ul.products');
// console.log('values', values);
//append browser URL with filters
let url = window.location.href;
let filterParams = values.replace(/[^&]+=&/g, '').replace(/&[^&]+=$/g, '') //remove empty values from URL
let baseUrl = url.includes('?') ? url.split('?')[0] : '',
paramsInUrl = url.includes('?') ? url.split(('?'))[1] : '',
paramsInUrlWithoutFilter = paramsInUrl.startsWith('filter') ? '' : paramsInUrl.split('&filter')[0]; //Get all params that are before "filter" if exists any
if (filterParams.endsWith('=') && paramsInUrlWithoutFilter) { //Removing from URL when exists other parameters than filter
filterParams = '';
url_with_filters = '?' + paramsInUrlWithoutFilter;
window.history.pushState(null, null, url_with_filters);
} else if (filterParams.endsWith('=') && !paramsInUrlWithoutFilter) { //Removing from URL when no other parameteres except filter exists
filterParams = '';
url_with_filters = location.pathname;
window.history.pushState(null, null, url_with_filters);
} else if (paramsInUrlWithoutFilter) { //Appending to browser URL when exists other parameters than filter
filterParams = filterParams;
url_with_filters = '?' + paramsInUrlWithoutFilter + '&' + filterParams;
window.history.pushState(null, null, url_with_filters);
} else { //Appending to browser URL when no other parameters except filter exists
filterParams = filterParams;
url_with_filters = '?' + filterParams;
window.history.pushState(null, null, url_with_filters);
}
//Update product results text
var resultCountElement = $('.title-wrapper .woocommerce-result-count.rg_woocommerce-total-count');
// Add loader
product_container.block({
message: null,
overlayCSS: {
cursor: 'none',
backgroundColor: '#fff',
},
});
$.ajax({
url: wp_ajax.ajax_url,
method: 'POST',
data: {
value: values,
action: 'rg_product_filter',
per_page: wp_ajax.per_page,
current: wp_ajax.current,
query_vars: wp_ajax.wp_query_vars,
},
success: (res) => {
// console.log(res);
$('.woocommerce ul.products').html(res);
product_container.unblock();
//Update product results text
resultCount = $('ul.products li.product').length;
resultCountElement.html(resultCount + ' produkter');
},
error: (res) => {
console.log(res);
}
});
});
//Select forms (not e.g. input groups)
$('select.form-control').each( function () {
$(this).on('change', $(this), (e) => {
if (e.handled !== true) { //Adding this if statement, because otherwise code $filterForm.submit(); is fired several times
e.handled = true;
$('.wc-filter .sorting__submit').css('display', 'block');
return;
}
});
});
//Input groups
$('.input-group').each( function () {
$(this).on('change', ':checkbox', (e) => {
$('.wc-filter .sorting__submit').css('display', 'block');
});
});
// Orderby
$( '.input-group' ).on( 'change', 'input[type="radio"]', function() {
$('.wc-filter .sorting__submit').css('display', 'block');
});
$('.wc-filter').on('click', '.sorting__submit', function () {
$filterForm.submit();
var filterOverlay = document.getElementsByClassName('product-filters-bg-overlay')[0] ? document.getElementsByClassName('product-filters-bg-overlay')[0] : '';
var filterContainer = document.getElementsByClassName('wc-filter')[0] ? document.getElementsByClassName('wc-filter')[0] : '';
filterOverlay.classList.toggle('toggled');
filterContainer.classList.toggle('toggled');
$('body.woocommerce').css('overflow', '');
});
and lastly, i have filters.php:
Ps: Please note that I have changed the name of the input group of fabrics from name=filter_fabric to name=filter_fabric[] as per recommendations
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$color_terms = get_terms('pa_color');
$material_terms = get_terms('pa_material');
$fabric_terms = get_terms(
array(
'taxonomy' => 'pa_tygmaterial',
));
?>
<div class="product-filters__panelbody">
<form id="filter-form" method="get" action="rg_product_filter">
<div class="product-filters-wrapper">
<?php /* Order By */ ?>
<div class="product-filters-item catalog-ordering">
<div class="product-filters-item-heading collapse-button"
data-toggle="collapse"
data-target="#tab_filter-sorting"
aria-expanded="false"
aria-controls="#tab_filter-sorting"
>Sortering
<svg viewBox="0 0 24 24" class="icon__product-filters-item">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</div>
<div class="collapse-body collapse-element collapse"
id="tab_filter-sorting"
>
<div class="product-filters-item-content">
<?php echo woocommerce_catalog_ordering(); ?>
</div>
</div>
</div>
<?php /* Color */ ?>
<div class="product-filters-item">
<div class="product-filters-item-heading collapse-button"
data-toggle="collapse"
data-target="#tab_filter-color"
aria-expanded="false"
aria-controls="#tab_filter-color"
>Color
<svg viewBox="0 0 24 24" class="icon__product-filters-item">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</div>
<div class="collapse-body collapse-element collapse"
id="tab_filter-color"
>
<div class="product-filters-item-content">
<select name="filter_color" id="filter_color" class="form-control">
<option value="" class="">Color</option>
<?php foreach ($color_terms as $color_term) {
$selected = $color_term->slug === $_GET['filter_color'] ? 'selected' : '';
echo '<option ' . $selected . ' value="' . $color_term->slug . '">' . $color_term->name . '</option>';
}?>
</select>
</div>
</div>
</div>
<?php /* Material */ ?>
<div class="product-filters-item">
<div class="product-filters-item-heading collapse-button"
data-toggle="collapse"
data-target="#tab_filter-material"
aria-expanded="false"
aria-controls="#tab_filter-material"
>Material
<svg viewBox="0 0 24 24" class="icon__product-filters-item">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</div>
<div class="collapse-body collapse-element collapse"
id="tab_filter-material">
<div class="product-filters-item-content">
<select name="filter_material" id="filter_material" class="form-control">
<option value="" class="">Material</option>
<?php foreach ($material_terms as $material_term) {
$selected = $material_term->slug === $_GET['filter_material'] ? 'selected' : '';
echo '<option ' . $selected . ' value="' . $material_term->slug . '">' . $material_term->name . '</option>';
}?>
</select>
</div>
</div>
</div>
<?php /* Fabrics */ ?>
<div class="product-filters-item">
<div class="product-filters-item-heading collapse-button"
data-toggle="collapse"
data-target="#tab_filter-fabrics"
aria-expanded="false"
aria-controls="#tab_filter-fabrics"
>Fabrics
<svg viewBox="0 0 24 24" class="icon__product-filters-item">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</div>
<div class="collapse-body collapse-element collapse"
id="tab_filter-fabrics">
<div class="product-filters-item-content">
<?php foreach ($fabric_terms as $fabric_term) {
//Get parameters from URL
$url_parameters = $_SERVER['QUERY_STRING'];
$data = proper_parse_str($url_parameters);
$product_fabrics = $data['filter_fabric'];
//Check if filter input is in array of parameters from URL, and mark the input as "checked"
if (isset($product_fabrics)) {
if (is_array($product_fabrics)) { //If more than one parameter is checked, $product_tygmaterial becomes array
$checked = in_array($fabric_term->slug, $product_fabrics) ? 'checked' : '';
} else { //If only one parameter is checked, $product_tygmaterial becomes string
$checked = $fabric_term->slug === $product_fabrics ? 'checked' : '';
}
} else {
$checked = '';
}
?>
<div class="input-group">
<input type="checkbox" id="<?php echo $fabric_term->slug; ?>" name="filter_fabric[]" value="<?php echo $fabric_term->slug ?>" <?php echo $checked; ?>>
<label for="<?php echo $fabric_term->slug; ?>"><?php echo $fabric_term->name; ?></label>
</div>
<?php }
?>
</div>
</div>
</div>
</div>
</form>
</div>
<?php /* Submit Button for Product Sorting */?>
<div class="submit__button-wrapper">
<button style="display: none;" class="sorting__submit">Show products</button>
</div>
<?php
Please let me know if this makes sense, I realize it is a lot of code in filters.php but the important part is the part noted with "Fabrics" as that is the input group that I am having trouble with.
Edit #2
I realized there might be an important function in my functions.php file that needs to be mentioned.
This works fine if the parameters are in the "clean/beautiful" state in the URL (i.e. example.com/category/page/2?filter_fabric=cotton&filter_fabric=polyester), but when I am on the paginated link, it automatically redirects to example.com/category/page/2?filter_fabric=polyester. It does this before the page is loaded, as I can see in my dev tools that a 301 request is sent to the second url with only the last parameter. I would assume this is some Wordpress automatic function that does that - is there any way to disable this?
function _url_parameters_query( $query ) {
//Check if query is for archive pages (otherwise this breaks e.g. nav header WP_Query)
if ($query->query_vars['wc_query'] !== 'product_query' || is_admin() ) {
return;
}
$url_parameters = $_SERVER['QUERY_STRING'];
$data = proper_parse_str($url_parameters);
$product_fabric = $data['filter_fabric'] ? $data['filter_fabric'] : null;
//Check if filter input is in array of parameters from URL, and mark the input as "checked"
if (isset($product_fabric)) {
// you can't use the query->set here for tax_query as tax query has already been made so you need to need add the data to any existing tax query
$tax_query = array(
'taxonomy' => 'pa_tygmaterial',
'field' => 'slug',
'terms' => $product_fabric,
'relation' => 'AND',
);
$query->tax_query->queries[] = $tax_query;
$query->query_vars['tax_query'] = $query->tax_query->queries;
if (array_key_exists('filter_fabric', $query->query)) {
// echo 'hello there Renjo!';
$query->query['filter_fabric'] = $product_fabric;
}
}
}
add_action( 'pre_get_posts', '_url_parameters_query' );
I think I resolved this issue by adding the following function in functions.php. I realized it was the redirect that was making problems for me, so I added the following:
//Remove redirection when filters with same name are set in URL (i.e. filters from input_groups), otherwise only passes last value
# e.g. example.com/category/page/2/?filter_fabric=cotton&filter_fabric=polyester => example.com/category/page/2/?filter_fabric=polyester
function _disable_redirect_query_params() {
global $wp_query;
if ($wp_query->query_vars['wc_query'] !== 'product_query' || is_admin() ) {
return;
}
if (isset($_GET['filter_tygmaterial']) ) {
remove_action('template_redirect', 'redirect_canonical');
}
}
add_action( 'wp', '_disable_redirect_query_params' );
I am not sure if there are any potential side effects of this, so if anyone has something in mind, please comment or let me know!

Echo shortcode in WordPress AJAX function return

I have searched all over here and the web but cant seem to get this to work - hopefully you all can help.
I am trying to setup product filters for WooCommerce on the category page (like filter products depending on color etc)
I have the ajax working but I have a shortcode that I want to display for each product and this doesnt work - any ideas how to get it to show?
Code below:
PHP
function ajax_filter_posts_scripts() {
// Enqueue script
wp_register_script('afp_script', plugins_url() . '/plugin-name/js/product-filter-ajax.js', false, null, false);
wp_enqueue_script('afp_script');
wp_localize_script( 'afp_script', 'afp_vars', array(
'afp_nonce' => wp_create_nonce( 'afp_nonce' ), // Create nonce which we later will use to verify AJAX request
'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
)
);
}
add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);
JS
jQuery(document).ready(function($) {
$(".loading").hide();
var taxonomy = [];
var terms = [];
$('.filter-option input').click( function(event) {
var taxonomy_idx = $.inArray($(this).closest(".filter-title-wrapper").attr('data-attribute'), taxonomy);
if (taxonomy_idx == -1) {
taxonomy.push($(this).closest(".filter-title-wrapper").attr('data-attribute'));
} else {
taxonomy.splice(taxonomy_idx, 1);
}
var terms_idx = $.inArray($(this).val(), terms);
if (terms_idx == -1) {
terms.push($(this).val());
} else {
terms.splice(terms_idx, 1);
}
// Prevent default action - opening tag page
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
// Get tag slug from title attirbute
var selecetd_taxonomy = taxonomy.toString();;
var selected_term = terms.toString();
var selected_term_speach = '\'' + selected_term.split(',').join('\',\'') + '\'';
console.log(selecetd_taxonomy);
console.log(selected_term_speach);
// After user click on tag, fade out list of posts
$('.products').fadeOut();
$(".loading").fadeIn();
data = {
action: 'filter_posts', // function to execute
afp_nonce: afp_vars.afp_nonce, // wp_nonce
taxonomy: selecetd_taxonomy, // selected tag
term: selected_term_speach,
};
$.post( afp_vars.afp_ajax_url, data, function(response) {
$(".loading").fadeOut();
if( response ) {
// Display posts on page
$('.products').html( response );
// Restore div visibility
$('.products').fadeIn();
};
});
});
});
PHP TO GET POSTS
// Script for getting posts
function ajax_filter_get_posts( $taxonomy, $term ) {
ob_start();
global $woocommerce, $product;
// Verify nonce
if( !isset( $_POST['afp_nonce'] ) || !wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ) )
die('Permission denied');
$taxonomy = $_POST['taxonomy'];
$term = $_POST['term'];
$term = str_replace("\\", '', $term);
// WP Query
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1,
);
if ($term == "''") {
}
else {
$args = array(
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'terms' => array($term),
'field' => 'slug',
'operator' => 'IN'
),
)
);
}
?>
<h1> <?php echo $term ?> </h1>
<?php
$query = new WP_Query( $args );
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post(); ?>
<li <?php wc_product_class(); ?>>
<?php echo do_shortcode('[product_shortcode]'); ?>
</li>
<?php
?>
<?php endwhile; ?>
<?php else: ?>
<h2>No posts found</h2>
<?php endif;
die();
return ob_get_clean();
}
add_action('wp_ajax_filter_posts', 'ajax_filter_get_posts');
add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_get_posts');
Excuse the messyness of the code, just trying to get it to work before I can start to neaten it up. Any advice on how to approach this in a better way please let me know.
Thanks and appreciate the help!
UPDATE-----
Tried to add the shortcode callback, but this doesnt work or I have the wrong code
add_action( 'init', function() {
ps_register_shortcode_ajax( 'ajax_filter_get_posts', 'ajax_filter_get_posts' );
} );
function ps_register_shortcode_ajax( $callable, $action ) {
if ( empty( $_POST['action'] ) || $_POST['action'] != $action )
return;
call_user_func( $callable );
}
WordPress Ajax calls don't have the access to whole WordPress environment and that's why your shortcode not working. Instead of calling the shortcode directly, call its callback. Refer https://wordpress.stackexchange.com/questions/53309/why-might-a-plugins-do-shortcode-not-work-in-an-ajax-request for more details.

Wordpress Load More Posts onclick with ajax request jquery

I've developed custom theme from scratch with _S starter theme. I'm having issue getting Wordpress next posts via ajax request on click on read more button. I've tried many articles specifically the following articles, but no luck.
Reference Links:
Load More Posts Ajax Button in Wordpress
Load Next WordPress Posts With AJAX
Load Old WordPress Posts on the Same Page with AJAX
I've tried going with above custom loops and adding custom functions with jquery script but it don't work somehow.
Here is loop code example below:
Loop in index.php
<?php query_posts('showposts=5'); if (have_posts()) : while (have_posts()) : the_post(); ?>
<article class="post-item">
<h2><?php the_title(); ?></h2>
<?php the_excerpt(); ?>
</article>
<?php endwhile; ?>
<?php else : ?>
<h2>Sorry no posts are created yet.</h2>
<p>Please create some posts to see it in action.</p>
<?php endif; wp_reset_query(); ?>
<button class="load-more-btn">Load More</button>
I'm messing with this issue for over 4-5 days, so any one can help me out with this issue with working solution will be highly appreciable.
Thanks in advance.
I maybe have a solution for your.
First be sure to have a script enqueue in your theme
wp_enqueue_script('your_js_hanlde', get_template_directory_uri() . '/js/your_js_hanlde.js', array('jquery'), '1.0.0', true );
then localize add a function to add a js var in your dom
wp_localize_script('your_js_hanlde', 'ajaxurl', admin_url( 'admin-ajax.php' ) );
In your js, add an event on 'click' on your 'Load More' button
Pass an action name and the count of article you have in your dom, the response add the content before your button 'load more'
$("#load_more").click(function()
{
$.post(ajaxurl,
{
'action': 'your_load_more',
'count': $("article.post-item").length
},
function(response)
{
var posts = JSON.parse(response);
for( var i = 0; i < posts.length; i++ )
{
if( posts[i] == "0" )
$("#load_more").fadeOut();
else
$("#load_more").before(posts[i]);
}
});
});
create a function in your functions.php
function your_load_more()
{
$count = $_POST["count"];
$cpt = 1;
$args = array(
'posts_per_page' => -1,
'post_type' => 'post', // change the post type if you use a custom post type
'post_status' => 'publish',
);
$articles = new WP_Query( $args );
$ar_posts = array();
if( $articles->have_posts() )
{
while( $articles->have_posts() )
{
$articles->the_post();
$one_post = "";
if( $cpt > $count && $cpt < $count+6 )
{
$one_post .= "<article id='" . get_the_id() . "' class='post-item'>";
$one_post .= "<h3>" . get_the_title() . "</h3>";
$one_post .= "</article>";
$ar_posts[] = $one_post;
if( $cpt == $articles->found_posts )
$ar_posts[] = "0";
}
$cpt++;
}
}
echo json_encode($ar_posts);
die();
}
add_action( 'wp_ajax_your_load_more', 'your_load_more' );
add_action( 'wp_ajax_nopriv_your_load_more', 'your_load_more' );
It work for me.
I hope that help you.

WP navigation post of a custom post type

I need to include in single.php a navigation buttons with previous and next post of the custom post type called 'works'.
I include this
<?php echo get_next_posts_link('Go to next post'); ?>
<?php echo get_previous_posts_link('Go to prev post');?>
or this
<?php previous_post_link( $taxonomy = 'works' ); ?>
But don´t show nothing or the navigation include all posts and pages. Only need pagination the post of this CUT like a carousel gallery, for example.
I think u search this one:
https://codex.wordpress.org/Pagination
A pagination for the last Posts of this Post Type.
U dosen't need a special "Menü" for this.
Try this
<?php
$term_list = wp_get_post_terms($post->ID, 'TAXONOMY', array("fields" => "slugs"));
if (empty($term_list[1])) {
print_r($term_list[0]);
$termo = $term_list[0];
} else {
print_r($term_list[1]);
$termo = $term_list[1];
}
// get_posts in same custom taxonomy
$postlist_args = array(
'posts_per_page' => -1,
'orderby' => 'menu_order title',
'order' => 'ASC',
'post_type' => 'CUSTOM-POST-TYPE',
'taxonomy'=>'TAXONOMY',
'term'=>$termo,
);
$postlist = get_posts( $postlist_args );
// get ids of posts retrieved from get_posts
$ids = array();
foreach ($postlist as $thepost) {
$ids[] = $thepost->ID;
}
// get and echo previous and next post in the same taxonomy
$thisindex = array_search($post->ID, $ids);
$previd = $ids[$thisindex-1];
$nextid = $ids[$thisindex+1];
if ( !empty($previd) ) {
echo '<a rel="prev" href="' . get_permalink($previd). '">previous</a>';
}
if ( !empty($nextid) ) {
echo '<a rel="next" href="' . get_permalink($nextid). '">next</a>';
}
?>
Good Luck.
Regards
If using the same category does not work, then you should try this. Add the tag "works" to the posts in your custom post-type. Then you can get the previous_ and next_post_link to this tag:
<?php previous_post_link( '%link', 'Previous in works', TRUE, ' ', 'post_tag' ); ?>
<?php next_post_link( '%link', 'Next in works', TRUE, ' ', 'post_tag' ); ?>

Wordpress order posts by post type

I am trying to create a system which fetches post from 2 post types and i want to display the posts order by their post type. I am trying to first show the posts from one post type and then another post type but the query i used mixes it all. Can any one suggest a good solution for this. Here is my code.
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
'post_type' => array('review','directory'),
'orderby' => 'name',
'order' => 'ASC',
'posts_per_page' => '4',
'paged' => $paged ,
'tax_query' => array( array(
'taxonomy' => 'Reviews',
'field' => 'id',
'terms' => $cat_id
), ),
);
query_posts($args);
if (have_posts()) :
while (have_posts()) : the_post();
$product_terms = wp_get_post_terms(get_the_ID(), 'Reviews', array("fields" => "all", "order" => "DESC"));
$postype=get_post_type( get_the_ID() );
if($postype=='review')
{
?>
<div class="review-post">
<h3><?php the_title(); ?></h3>
<div class="review-cat-new">
<?php echo get_the_term_list( $post->ID, 'Reviews', 'Category: ', ', ', '' ); ?>
</div>
<?php
if(get_field('see_it'))
$seeit_text= get_field('see_it');
if(get_field('skip_it'))
$skipit_text= get_field('skip_it');
?>
<div class="see-skip">
<p class="see-it"><span>See it:</span>
<?php echo $seeit_text; ?>
</p>
<p class="skip-it"><span>Skip it:</span>
<?php echo $skipit_text; ?>
</p>
</div>
<?php echo custom_field_excerpt(); ?>
</div>
<?php }
else
{
?>
<div class="review-post">
<h3><?php the_title(); ?></h3>
<div class="review-cat-new">
<?php echo get_the_term_list( get_the_ID(), 'Reviews', 'Category: ', ', ', '' ); ?>
</div>
<?php echo the_field('enter_content_direc'); ?>
<?php
if(get_field('enter_textdirec'))
$text= get_field('enter_textdirec');
if(get_field('enter_linkdirec'))
$textlink= get_field('enter_linkdirec');
?>
<div class="see-skip">
<p class="see-it direc"><span><a target="_blank" style="color:#5D6D71; text-transform: lowercase;" href="<?php echo $textlink;?>"><?php echo $textlink;?> </a></span>
</p>
</div>
</div>
<?php }
endwhile;
echo '<div class="paging">';
wp_pagenavi();
echo '</div>';
endif;
So is there a way so that i can first show the posts form reviews and then directory?
Since Wordpress 4.0 you can just pass the option type (post_type) to the orderby parameter in the WP_Query object.
orderby (string | array) - Sort retrieved posts by parameter. To order by post type just pass:
'type' - Order by post type (available since Version 4.0). ('post_type' is also accepted.)
As seen in the docs https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters , you can use the regular wp query by passing an array to 'orderby' :
$wp_query = new WP_Query(
array(
's' => $search,
'orderby'=> array('type'=>'DESC', 'title'=>'ASC'),
'paged'=>$paged
)
);
if ( $wp_query->have_posts() ) {
while ( $wp_query->have_posts() ) {
$wp_query->the_post();
// do your loop stufff here
}
}
Finally i got the solution and it can be done using a filter.
The solution looks like this.
add_filter( 'posts_request' , 'modify_request' );
function modify_request( $query) {
global $wpdb;
if(strstr($query,"post_type IN ('review', 'directory')")){
$where = str_replace("ORDER BY {$wpdb->posts}.post_date","ORDER BY {$wpdb->posts}.post_type",$query);
}
return $where;
}
Order per post types with custom post type order:
add_filter('pre_get_posts', function ($query) {
if ($query->is_search && !is_admin()) :
$query->set('post_type', [ 'cpt-1', 'cpt-2', 'post', 'cpt-3']);
endif;
return $query;
});
add_filter('posts_orderby', function ( $order ) {
if ( ! is_admin() ) :
if ( is_search() && is_main_query() ) :
global $wpdb;
$order = "FIELD( post_type, 'cpt-1', 'cpt-2', 'post' ), {$wpdb->posts}.post_modified DESC";
endif;
// Disable this filter for future queries!
remove_filter( current_filter(), __FUNCTION__);
endif;
return $order;
});
First solution which comes to my mind is to get posts only for first category. Reset query (wp_reset_query()) and get them again for second category. You need to double up your code of course, but I don't see any other solution - it's WordPress - you're very limited.
Second solution is to query database directly like this:
$result = mysql_query('SELECT *
FROM `wp_posts`
WHERE post_type = "page"
OR post_type = "post"
ORDER BY post_type ASC , post_date DESC ');
$posts = array();
if($result) {
while ($row = mysql_fetch_assoc($result)) {
$posts[] = $row;
}
}
mysql_free_result($result);
echo('<pre>');
var_dump($posts);
echo('</pre>');
die();
Notice that I've used post and page types as these are default, and exist in my WP installation. But you can use different. You can play with this query as much as you want.

Categories