Ask your WordPress questions! Pay money and get answers fast! (more info)

Turn this into a widget -- pass form variables. WordPress

  • SOLVED

Edit to update this question with the correct functioning code.

This code correctly builds a widget for WordPress. The widget has a form, which passes variables to a post query, the query is then displayed using the archive.php of the theme to display the results. We also populate the form by searching the posts and grabbing all of the unique instances of a term.


<?php

class Property_Search_Widget extends WP_Widget
{
/** constructor -- name this the same as the class above */

function __construct()

{
/* Widget settings. */
$widget_ops = array('classname' => 'property-search-widget', 'description' => 'Property search widget.');
/* Widget control settings. */
$control_ops = array('property-search-widget');
/* Create the widget. */
parent::WP_Widget('property-search-widget', 'Property Search Widget', $widget_ops, $control_ops);
add_action('pre_get_posts', 'property_search_vars');

function property_search_vars($query)

{
if ($query->is_main_query()) {
$meta_query = array();
if ($_GET['searchcity']) {
$meta_query[] = array('key' => '__city', 'value' => $_GET['searchcity'], 'compare' => '=');
}

if ($_GET['beds']) {
$meta_query[] = array('key' => '__bedrooms', 'value' => $_GET['beds'], 'compare' => '>=', 'type' => 'numeric');
}

if ($_GET['baths']) {
$meta_query[] = array('key' => '__bathrooms', 'value' => $_GET['baths'], 'compare' => '>=', 'type' => 'numeric');
}

if ($_GET['min_price']) {
$meta_query[] = array('key' => '__price', 'value' => $_GET['min_price'], 'compare' => '>=', 'type' => 'numeric');
}

if ($_GET['max_price']) {
$meta_query[] = array('key' => '__price', 'value' => $_GET['max_price'], 'compare' => '<=', 'type' => 'numeric');
}

if (!empty($meta_query)) {
$meta_query['relation'] = 'AND';
$query->set('meta_query', $meta_query);
}
}
}
}

/** @see WP_Widget::widget -- do not rename this */

function widget($args, $instance)

{
extract($args);
$title = $instance['title'];
echo $before_widget;

if ($title) {
echo $before_title . $title . $after_title;
}

global $wpdb;

$cities = $wpdb->get_col($wpdb->prepare("

SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = 'mls'
", '__city', 'publish'));

$property_types = get_terms(array(
'hide_empty' => 0,
'taxonomy' => 'property_type',
));
?>

<div class="hmls-search-wrapper">

<form action="<?php echo get_post_type_archive_link('mls') ?>" method="get" id="quick-search-form">

<dl id="mls-search-city">
<dt>City</dt>
<dd class="content">
<fieldset>
<select name="searchcity">
<option value="">All Cities</option>
<?php foreach ($cities as $city): ?>
<option value="<?php echo $city ?>"<?php selected($_GET['city'], $city) ?>><?php echo $city ?></option><?php endforeach; ?>
</select>
</fieldset>
</dd>
</dl>

<?php
$prices = array(1, 50000, 75000, 100000, 125000, 150000, 175000, 200000, 250000, 300000, 350000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1500000);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<select id="minimum_price" name="min_price">
<option value="">Min</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>"<?php selected($_GET['min_price'], $price) ?>>
$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="widget_column_half">
<select id="maximum_price" name="max_price">
<option value="">Max</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>" <?php selected($_GET['max_price'], $price) ?>>
$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>

<?php
$beds = range(1, 6);
$baths = range(1, 4);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<label>Beds</label>
<select id="minimum_beds" name="beds">
<option value="">-</option>
<?php foreach ($beds as $bed) : ?>
<option value="<?php echo $bed ?>" <?php selected($_GET['beds'], $bed) ?>><?php echo $bed ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="widget_column_half">
<label>Baths</label>
<select id="minimum_baths" name="baths">
<option value="">-</option>
<?php foreach ($baths as $bath) : ?>
<option value="<?php echo $bath ?>" <?php selected($_GET['baths'], $bath) ?>><?php echo $bath ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>
<p class="submit"><input type="submit" name="search" value="Search Listings"/></p>
</form>

</div>

<?php
echo $after_widget;
}

/** @see WP_Widget::form -- do not rename this */

function form($instance)

{
/* Set up some default widget settings. */
$defaults = array('title' => 'Search Listings');
$instance = wp_parse_args((array)$instance, $defaults);
$title = esc_attr($instance['title']);
?>

<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>"/>
</p>

<?php
}
} // end class example_widget

add_action('widgets_init', create_function('', 'return register_widget("Property_Search_Widget");'));

Answers (3)

2012-10-21

jazbek answers:

Hi Scott,

Can you tell me whether cities, property_types, price, beds and baths are set up as custom taxonomies or custom meta fields?


jazbek comments:

Here is a widget you should be able to use. Assuming the following:

city = custom taxonomy
property_type = custom taxonomy
price = custom field
beds = custom field
baths = custom field

^^ If any of the above is an incorrect assumption, or I didn't use the correct key names for the custom fields, let me know and I can edit the code.

Place the following in your functions.php:

<?php

// register a sidebar -- leave the next line out if you already have your sidebars set up.
register_sidebar();

// if you need to add the sidebar you just registered to your theme, put the following in your template where you want the sidebar to show up:
// dynamic_sidebar('Sidebar 1');

/**
* Property Search Widget Class
*/
class Property_Search_Widget extends WP_Widget {


/** constructor -- name this the same as the class above */
function __construct()
{
/* Widget settings. */
$widget_ops = array( 'classname' => 'property-search-widget', 'description' => 'Property search widget.' );

/* Widget control settings. */
$control_ops = array('property-search-widget' );

/* Create the widget. */
parent::WP_Widget( 'property-search-widget', 'Property Search Widget', $widget_ops, $control_ops );

if (is_search())
{
add_action( 'pre_get_posts', 'property_search_vars' );
function property_search_vars( $query )
{
if ( $query->is_main_query() && $_GET['property_search'] == 1)
{
$query->set('post_type', 'mls');
$meta_query = array();
if ($_GET['beds'])
{
$meta_query[] = array('key' => 'beds', 'value' => $_GET['beds'], 'compare' => '>=');
}
if ($_GET['baths'])
{
$meta_query[] = array('key' => 'baths', 'value' => $_GET['baths'], 'compare' => '>=');
}
if ($_GET['min_price'])
{
$meta_query[] = array('key' => 'price', 'value' => $_GET['min_price'], 'compare' => '>=');
}
if ($_GET['max_price'])
{
$meta_query[] = array('key' => 'price', 'value' => $_GET['max_price'], 'compare' => '<=');
}
if ( ! empty($meta_query))
{
$meta_query['relation'] => 'AND';
$query->set('meta_query', $meta_query);
}
}
}
}
}

/** @see WP_Widget::widget -- do not rename this */
function widget($args, $instance)
{
extract( $args );
$title = $instance['title'];

echo $before_widget;
if ($title)
{
echo $before_title . $title . $after_title;
}
$cities = get_terms( array(
'hide_empty' => 0,
'taxonomy' => 'city',
) );

$property_types = get_terms (array(
'hide_empty' => 0,
'taxonomy' => 'property_type',
) );

?>

<div class="hmls-search-wrapper">
<form action="<?php echo home_url('/') ?>" method="get" id="quick-search-form">

<dl id="mls-search-city">
<dt>City</dt>
<dd class="content">
<fieldset>
<select name="city">
<option value="">All Cities</option>
<?php foreach ( $cities as $city ): ?><option value="<?php echo $city->slug ?>"<?php selected($_GET['city'], $city->slug) ?>><?php echo $city->name ?></option><?php endforeach; ?>
</select>
</fieldset>
</dd>
</dl>

<dl id="mls-search-city">
<dt>Property Type</dt>
<dd class="content">
<fieldset>
<select name="property_type">
<option value="">All Properties</option>
<?php foreach ( $property_types as $property_type): ?><option value="<?php echo $property_type->slug ?>"<?php selected($_GET['property_type'], $property_type) ?>><?php echo $property_type->name ?></option><?php endforeach; ?>
</select>
</fieldset>
</dd>
</dl>

<?php
$prices = array(50000, 75000, 100000, 125000, 150000, 175000, 200000, 250000, 300000, 350000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1500000);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<select id="minimum_price" name="min_price">
<option value="">Min</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>"<?php selected($_GET['min_price'], $price) ?>>$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>

<div class="widget_column_half">
<select id="maximum_price" name="max_price">
<option value="">Max</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>" <?php selected($_GET['max_price'], $price) ?>>$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>

<?php
$beds = range(1, 6);
$baths = range(1, 4);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<label>Beds</label>
<select id="minimum_beds" name="beds">
<option value="">-</option>
<?php foreach ($beds as $bed) : ?>
<option value="<?php echo $bed ?>" <?php selected($_GET['beds'], $bed) ?>><?php echo $bed ?></option>
<?php endforeach; ?>
</select>
</div>

<div class="widget_column_half">
<label>Baths</label>
<select id="minimum_baths" name="baths">
<option value="">-</option>
<?php foreach ($baths as $bath) : ?>
<option value="<?php echo $bath ?>" <?php selected($_GET['baths'], $bath) ?>><?php echo $bath ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>
<input type="hidden" name="property_search" value="1">
<p class="submit"><input type="submit" name="search" value="Search Listings" /></p>
</form>
<?php
echo $after_widget;
}

/** @see WP_Widget::form -- do not rename this */
function form($instance)
{
/* Set up some default widget settings. */
$defaults = array( 'title' => 'Search Listings');
$instance = wp_parse_args( (array) $instance, $defaults );
$title = esc_attr($instance['title']);
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<?php
}


} // end class example_widget
add_action('widgets_init', create_function('', 'return register_widget("Property_Search_Widget");'));


Scott Hack comments:

city = custom taxonomy ( correct, this is a taxonomy, but is all meta data. meta field is __city )
property_type = custom taxonomy ( correct )
price = custom field ( correct, but field name is wrong. It is __price )
beds = custom field ( correct, but field name is wrong. It is __bedrooms )
baths = custom field ( correct, but field name is wrong. it is __bathrooms )


jazbek comments:

Since the site won't let me edit my last comment, I'm reposting the edited code here (with indentation this time, and a few fixed errors :). Let me know if you run into any issues:
<?php

// register a sidebar -- leave the next line out if you already have your sidebars set up.
register_sidebar();

// if you need to add the sidebar above to your theme, put the following
// in your template where you want the sidebar to show up:
// dynamic_sidebar('Sidebar 1');

/**
* Property Search Widget Class
*/
class Property_Search_Widget extends WP_Widget {

/** constructor -- name this the same as the class above */
function __construct()
{
/* Widget settings. */
$widget_ops = array( 'classname' => 'property-search-widget', 'description' => 'Property search widget.' );

/* Widget control settings. */
$control_ops = array('property-search-widget' );

/* Create the widget. */
parent::WP_Widget( 'property-search-widget', 'Property Search Widget', $widget_ops, $control_ops );

if (is_search())
{
add_action( 'pre_get_posts', 'property_search_vars' );
function property_search_vars( $query )
{
if ( $query->is_main_query() && $_GET['property_search'] == 1)
{
$query->set('post_type', 'mls');
$meta_query = array();
if ($_GET['city'])
{
$meta_query[] = array('key' => '__city', 'value' => $_GET['city'], 'compare' => '=');
}
if ($_GET['beds'])
{
$meta_query[] = array('key' => '__bedrooms', 'value' => $_GET['beds'], 'compare' => '>=');
}
if ($_GET['baths'])
{
$meta_query[] = array('key' => '__bathrooms', 'value' => $_GET['baths'], 'compare' => '>=');
}
if ($_GET['min_price'])
{
$meta_query[] = array('key' => '__price', 'value' => $_GET['min_price'], 'compare' => '>=');
}
if ($_GET['max_price'])
{
$meta_query[] = array('key' => '__price', 'value' => $_GET['max_price'], 'compare' => '<=');
}
if ( ! empty($meta_query))
{
$meta_query['relation'] = 'AND';
$query->set('meta_query', $meta_query);
}
}
}
}
}

/** @see WP_Widget::widget -- do not rename this */
function widget($args, $instance)
{
extract( $args );
$title = $instance['title'];

echo $before_widget;
if ($title)
{
echo $before_title . $title . $after_title;
}

global $wpdb;

$cities = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = 'mls'
", '__city', 'publish') );

$property_types = get_terms (array(
'hide_empty' => 0,
'taxonomy' => 'property_type',
) );

?>

<div class="hmls-search-wrapper">
<form action="<?php echo home_url('/') ?>" method="get" id="quick-search-form">

<dl id="mls-search-city">
<dt>City</dt>
<dd class="content">
<fieldset>
<select name="city">
<option value="">All Cities</option>
<?php foreach ( $cities as $city ): ?><option value="<?php echo $city ?>"<?php selected($_GET['city'], $city) ?>><?php echo $city ?></option><?php endforeach; ?>
</select>
</fieldset>
</dd>
</dl>

<dl id="mls-search-city">
<dt>Property Type</dt>
<dd class="content">
<fieldset>
<select name="property_type">
<option value="">All Properties</option>
<?php foreach ( $property_types as $property_type): ?><option value="<?php echo $property_type->slug ?>"<?php selected($_GET['property_type'], $property_type) ?>><?php echo $property_type->name ?></option><?php endforeach; ?>
</select>
</fieldset>
</dd>
</dl>

<?php
$prices = array(50000, 75000, 100000, 125000, 150000, 175000, 200000, 250000, 300000, 350000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1500000);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<select id="minimum_price" name="min_price">
<option value="">Min</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>"<?php selected($_GET['min_price'], $price) ?>>$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>

<div class="widget_column_half">
<select id="maximum_price" name="max_price">
<option value="">Max</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>" <?php selected($_GET['max_price'], $price) ?>>$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>

<?php
$beds = range(1, 6);
$baths = range(1, 4);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<label>Beds</label>
<select id="minimum_beds" name="beds">
<option value="">-</option>
<?php foreach ($beds as $bed) : ?>
<option value="<?php echo $bed ?>" <?php selected($_GET['beds'], $bed) ?>><?php echo $bed ?></option>
<?php endforeach; ?>
</select>
</div>

<div class="widget_column_half">
<label>Baths</label>
<select id="minimum_baths" name="baths">
<option value="">-</option>
<?php foreach ($baths as $bath) : ?>
<option value="<?php echo $bath ?>" <?php selected($_GET['baths'], $bath) ?>><?php echo $bath ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>
<input type="hidden" name="property_search" value="1">
<p class="submit"><input type="submit" name="search" value="Search Listings" /></p>
</form>
</div>
<?php
echo $after_widget;
}

/** @see WP_Widget::form -- do not rename this */
function form($instance)
{
/* Set up some default widget settings. */
$defaults = array( 'title' => 'Search Listings');
$instance = wp_parse_args( (array) $instance, $defaults );
$title = esc_attr($instance['title']);
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<?php
}


} // end class example_widget
add_action('widgets_init', create_function('', 'return register_widget("Property_Search_Widget");'));


Scott Hack comments:

For the time being, lets take property type out of the equation. I don't see it above in the query, but I do in the form... but I want to eliminate it as an issue.

When doing some testing a few things I've noticed.

If the city name has a space, it chokes.
None of the other filters appear to work.


jazbek comments:

Hi Scott,

Thanks for the reply.. admittedly it is somewhat hard to make a perfect working widget without having access to your code or database, but here's another round with property type removed, and an edit to make the other filters work:

<?php

// register a sidebar -- leave the next line out if you already have your sidebars set up.
register_sidebar();

// if you need to add the sidebar above to your theme, put the following
// in your template where you want the sidebar to show up:
// dynamic_sidebar('Sidebar 1');

/**
* Property Search Widget Class
*/
class Property_Search_Widget extends WP_Widget {

/** constructor -- name this the same as the class above */
function __construct()
{
/* Widget settings. */
$widget_ops = array( 'classname' => 'property-search-widget', 'description' => 'Property search widget.' );

/* Widget control settings. */
$control_ops = array('property-search-widget' );

/* Create the widget. */
parent::WP_Widget( 'property-search-widget', 'Property Search Widget', $widget_ops, $control_ops );

add_action( 'pre_get_posts', 'property_search_vars' );
function property_search_vars( $query )
{
if ( $query->is_main_query())
{
$meta_query = array();
if ($_GET['city'])
{
$meta_query[] = array('key' => '__city', 'value' => $_GET['city'], 'compare' => '=');
}
if ($_GET['beds'])
{
$meta_query[] = array('key' => '__bedrooms', 'value' => $_GET['beds'], 'compare' => '>=');
}
if ($_GET['baths'])
{
$meta_query[] = array('key' => '__bathrooms', 'value' => $_GET['baths'], 'compare' => '>=');
}
if ($_GET['min_price'])
{
$meta_query[] = array('key' => '__price', 'value' => $_GET['min_price'], 'compare' => '>=');
}
if ($_GET['max_price'])
{
$meta_query[] = array('key' => '__price', 'value' => $_GET['max_price'], 'compare' => '<=');
}
if ( ! empty($meta_query))
{
$meta_query['relation'] = 'AND';
$query->set('meta_query', $meta_query);
}
}
}
}

/** @see WP_Widget::widget -- do not rename this */
function widget($args, $instance)
{
extract( $args );
$title = $instance['title'];

echo $before_widget;
if ($title)
{
echo $before_title . $title . $after_title;
}

global $wpdb;

$cities = $wpdb->get_col( $wpdb->prepare( "
SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
WHERE pm.meta_key = '%s'
AND p.post_status = '%s'
AND p.post_type = 'mls'
", '__city', 'publish') );

$property_types = get_terms (array(
'hide_empty' => 0,
'taxonomy' => 'property_type',
) );

?>

<div class="hmls-search-wrapper">
<form action="<?php echo get_post_type_archive_link('mls') ?>" method="get" id="quick-search-form">

<dl id="mls-search-city">
<dt>City</dt>
<dd class="content">
<fieldset>
<select name="city">
<option value="">All Cities</option>
<?php foreach ( $cities as $city ): ?><option value="<?php echo $city ?>"<?php selected($_GET['city'], $city) ?>><?php echo $city ?></option><?php endforeach; ?>
</select>
</fieldset>
</dd>
</dl>

<?php
$prices = array(50000, 75000, 100000, 125000, 150000, 175000, 200000, 250000, 300000, 350000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000, 1500000);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<select id="minimum_price" name="min_price">
<option value="">Min</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>"<?php selected($_GET['min_price'], $price) ?>>$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>

<div class="widget_column_half">
<select id="maximum_price" name="max_price">
<option value="">Max</option>
<?php foreach ($prices as $price) : ?>
<option value="<?php echo $price ?>" <?php selected($_GET['max_price'], $price) ?>>$<?php echo number_format($price) ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>

<?php
$beds = range(1, 6);
$baths = range(1, 4);
?>

<dl id="mls-search-city">
<dt>Price</dt>
<dd class="content">
<fieldset>
<div class="widget_column_half">
<label>Beds</label>
<select id="minimum_beds" name="beds">
<option value="">-</option>
<?php foreach ($beds as $bed) : ?>
<option value="<?php echo $bed ?>" <?php selected($_GET['beds'], $bed) ?>><?php echo $bed ?></option>
<?php endforeach; ?>
</select>
</div>

<div class="widget_column_half">
<label>Baths</label>
<select id="minimum_baths" name="baths">
<option value="">-</option>
<?php foreach ($baths as $bath) : ?>
<option value="<?php echo $bath ?>" <?php selected($_GET['baths'], $bath) ?>><?php echo $bath ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
</dd>
</dl>
<p class="submit"><input type="submit" name="search" value="Search Listings" /></p>
</form>
</div>
<?php
echo $after_widget;
}

/** @see WP_Widget::form -- do not rename this */
function form($instance)
{
/* Set up some default widget settings. */
$defaults = array( 'title' => 'Search Listings');
$instance = wp_parse_args( (array) $instance, $defaults );
$title = esc_attr($instance['title']);
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<?php
}


} // end class example_widget
add_action('widgets_init', create_function('', 'return register_widget("Property_Search_Widget");'));

2012-10-22

John Cotton answers:

You've got to go with the grain of WordPress to get the most out of it. Here, you've got a few mixed up notions.

Dealing with each, let first ignore that you have a search form and go straight to the output.

What you want is a list of custom posts or, in WP parlance, an archive. So your output code (ie everything after the </form>) needs to be in archive-mls.php.

Turning to the form, your form code is best placed in a widget to get it on the sidebar (you could hardcode it in sidebar.php if you wanted it on every page, but having it as a widget gives you more flexibility). There's a good description of [[LINK href="http://codex.wordpress.org/Widgets_API"]]how to make a widget[[/LINK]] on the Codex.

The key thing with the form is that you need to point it to the archive page. Assuming you're slug for the the custom post type is mls that would be action="/mls" in the HTML.

Now you can add some extra code to the top of the archive to handle the form posting. For example:



$args = array(
'post_type' => 'mls',
'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1
);

$meta = array();

if( isset($_POST['beds']) ) {
$meta[] = array(
'key' => '__bedrooms',
'value' => $_POST['beds'],
'type' => 'numeric',
'compare' => '>='
)
}

if( isset($_POST['baths']) ) {
$meta[] = array(
'key' => '__bathrooms',
'value' => $_POST['beds'],
'type' => 'numeric',
'compare' => '>='
)
}

// etc etc for each of your meta elements.

// Set the meta query into your args..
$args['meta_query'] = $meta;


// ....carry on as before.



Does that all make sense?

John


Scott Hack comments:

John,

Are there not any other options except pointing to a specific page?


John Cotton comments:

<blockquote>Are there not any other options except pointing to a specific page?</blockquote>
Sorry, what do you mean? Pointing the form at a specific page?

Are you saying that you want the results in the sidebar?


Scott Hack comments:

No, not in the sidebar. Adding the code to the archive template isn't ideal, but is certainly do-able. Would it be possible to create short code that contained the parse/catch code from the form and then the short code could be placed on any page I'd like?

I was also curious if it was possible to do it any other way. The gentleman above you has attempted a solution that is using the root url and passing variables via the url, but that isn't working correctly either.

I've setup his solution a test at http://www.nolinlakerealestate.com ( in the bottom ) for reference.


John Cotton comments:

Hi Scott

You can send it to any page you like! And yes, you could have a shortcode that processed it.

A shortcode might look like this:



function process_search() {

if( $_POST['search_submit'] ) { // check that there's some search query to process

// do your query and output result

}

}
add_shortcode( 'process_search', 'process_search');


It just seems an strange UI to me. When a user searches, I would have thought they would be sent to a consistent search results page. All I was suggesting was to give you a simple WP friendly structure. To me you have a set of mls type posts and an archive file would list those. However, sometimes you want a shorter/filtered list - so add some code to respond like that when the search happens.

Perhaps if you could explain why you want the results to be output in different places, I could make a better suggestion.


John

2012-10-21

Dbranes answers:

hi, here is a skeleton for the widget, you can paste into your functions.php file:

/**
* Custom Search Widget Class
*/
add_action('widgets_init', create_function('', 'return register_widget("custom_search_widget");'));

class custom_search_widget extends WP_Widget {

/** constructor */
function __construct() {
parent::__construct(
'my_custom_search_widget', // Base ID
'Custom Search', // Name
array( 'description' => 'Custom Search', ) // Args

);

}

/**
* Front-end display of widget.
*
* @see WP_Widget::widget()
*
* @param array $args Widget arguments.
* @param array $instance Saved values from database.
*/

public function widget( $args, $instance ) {
extract( $args );
$current_search=esc_attr($instance['my_custom_search']);
echo $before_widget;
if ( ! empty( $title ) )
echo $before_title . $title . $after_title;
?>

<div class="custom_search_box">

... your custom html + php search code here ...

</div>

<?php
echo $after_widget;
}


/** @see WP_Widget::update */

function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['my_custom_search'] = esc_attr($new_instance['my_custom_search']);
return $instance;
}

/** @see WP_Widget::form */
function form($instance) {
$current_search=esc_attr($instance['my_custom_search']);
echo "Some Custom Field: <input name=". $this->get_field_name('my_custom_search')." value=".$current_search.">";

}
}


You can move the search-form part into the widget and the query part into a page template: example.com/search-result
and then use this pageurl in the form action.

You can access the form data via $_REQUEST ( works both as $_GET and $_POST) variable and use it fill $args.

fx. put this into your template to check it out:

echo "<pre>";
print_r($_REQUEST);
echo "</pre>";


Here is a basic way to get the form-input values:

if(isset($_REQUEST['search'])){
// get input values
//
if(isset($_REQUEST['city'])){
$city=$_REQUEST['city'];
}
if(isset($_REQUEST['beds'][0])){
$beds=$_REQUEST['beds'][0];
}
if(isset($_REQUEST['baths'][0])){
$baths=$_REQUEST['baths'][0];
}

// validate and format input values
// ...

// query args
//
$args = array(
'post_type' => 'mls',
'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
'meta_query' => array(
'relation' => 'AND',
array(
'key' => '__city',
'value' => $city,
'compare' => '='
),
array(
'key' => '__bedrooms',
'value' => $beds,
'type' => 'numeric',
'compare' => '>='
),
array(
'key' => '__bathrooms',
'value' => $baths,
'type' => 'numeric',
'compare' => '>='
),
);

$wp_query = new WP_Query($args);

//... cut ...
}