Searching for around two days to find an answer to my question, I finally registered for this StackExchange. :)
My Question is not simple, so I need to start at the very beginning. But to give you an idea of what this Post is about: Meanwhile my Plugin is working, but I do not like the code. I think there are better ways to solve this and so I am searching for wordpress ninjas who can help me with good hints and best practices. I really try to get into the deeps of wordpress, but it is kind of hard. Thank you in advance!
What my Plugin should do
The User of this Plugin should be able to use a shortcode to show a search form for specific post types. The Plugin is only needed on the pages containing this shortcode.
The post types are created via the plugin settings page. Every post of this type has a title, content and several custom fields from the acf plugin. There is one shortcode for every post type. The search form has one field to search all the post fields of the specified post type. The other two can be used to limit the results by two keywords (for example the location, which is an acf field).
The results are loaded via ajax and shown below the search form.
What I did already
I try to keep this question not too big. So I do not specifiy every single aspect. The following should work fine:
- Create on post type in the php file of the plugin. For the moment one static post type is enaugh.
- Create a shortcode which prints the search form and an empty container for the results.
- The Ajax request is working via javascript and gives the expected results.
Search Custom fields
This was quite hard, but I found a working code snippet and I understand what it is doing. The problem here is, that I just want to search acf fields with my specific search form. I do not want to touch the search of the existing site.
First I tried to check which site the user is on and use an if-statement with is_page() before I modify the search query. But as I use ajax, this seems not to work for me here...
My workaround is to set a global variable at the beginning of every ajax search query. Now I check if this variable is set before I modify the search query. At the end of my ajax function, I set this variable back to false. Yes, I think there is a better way to solve this, but I do no know how...
The functions which modify my search query are the following:
/** * Extend WordPress search to include custom fields * * http://adambalee.com */ /** * Join posts and postmeta tables * * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join */ function cf_search_join( $join ) { global $wpdb; //$cwlistpage=(is_page('list')); global $testcheck; $cwlistpage=$testcheck; if ( $cwlistpage ) { $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id '; } return $join; } add_filter('posts_join', 'cf_search_join' ); /** * Modify the search query with posts_where * * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_where */ function cf_search_where( $where ) { global $pagenow, $wpdb; //$cwlistpage=(is_page('list')); global $testcheck; $cwlistpage=$testcheck; if ( $cwlistpage ) { $where = preg_replace( "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/", "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where ); } return $where; } add_filter( 'posts_where', 'cf_search_where' ); /** * Prevent duplicates * * http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_distinct */ function cf_search_distinct( $where ) { global $wpdb; //$cwlistpage=(is_page('list')); global $testcheck; $cwlistpage=$testcheck; if ( $cwlistpage ) { return "DISTINCT"; } return $where; } add_filter( 'posts_distinct', 'cf_search_distinct' );
Limit the results by custom fields
All fields of the form are optional. An empty form will return all posts of this post type. The first field should search every field of the posts for the keyword. The second and third field should limit the results to the one containing this keyword. I solved this with if-statements and I know there must be a better solution.
/**
* Search with AJAX
*/
function cwlist_click_search() {
global $testcheck;
$testcheck = true;
$searchterm = $_POST['query'];
$searchlocation = $_POST['location'];
$searchdegree = $_POST['degree'];
// WP_Query arguments
$args = array (
'post_type' => 'offers',
'post_status' => 'publish',
's' => $searchterm
);
$query = new WP_Query( $args );
ob_start();
// The Loop
if ( $query->have_posts() ) : ?>
<br><br><p>
<?php while ( $query->have_posts() ) : $query->the_post();
if( ($searchlocation == NULL) || in_array(trim(strtolower($searchlocation)), array_map('strtolower', get_field('offer_location')))):
if( ($searchdegree == NULL) || (trim(strtolower($searchdegree)) === strtolower(get_field('offer_degree')))):?>
Titel: <?php the_title(); ?> <br>
Abschluss: <?php the_field('offer_degree'); ?> <br>
Ort: <?php the_field('offer_location'); ?> <br>
Anbieter: <?php the_field('offer_provider'); ?> <br>
<?php if(get_field('offer_subtitle')): ?>
- <?php the_field('offer_subtitle'); ?> <br>
<?php endif; ?>
<br>
<?php endif; endif; endwhile; ?>
</p>
<?php else: ?>
<!-- no posts found -->
Keine Angebote gefunden
<?php endif;
// Restore original Post Data
wp_reset_postdata();
$content = ob_get_clean();
echo $content;
die();
$testcheck = false;
}
add_action( 'wp_ajax_nopriv_cwlist_click_search', 'cwlist_click_search' );
add_action( 'wp_ajax_cwlist_click_search', 'cwlist_click_search' );
WP Debug
When I activate the plugin many lines like the following appear at the front page:
Notice: Trying to get property of non-object in C:\Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp-includes\query.php on line 4520 Notice: Trying to get property of non-object in C:\Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp-includes\query.php on line 4522 Notice: Trying to get property of non-object in C:\Users\CWalt\Documents\gitlab\steuerazubi\wordpress\wp-includes\query.php on line 4524 ...
I activated debugging to create a good plugin. What could I possibly did wrong?
More Post Types
Do you know a good approach to let the User specify more post types via the wordpress backend? The user should be able to create different search pages for different post types via shortcodes.
Thank you very very much for reading. I am thankful for every small hint.