Php page with filters for custom fields

I will share how I achieved to implement what I consider to be an advanced custom search using WordPress out-of-the-box functionalities and ACF, without custom PHP scripts that are questionable.

  1. Creating a custom post type
  2. Adding a custom field to the custom post type
  3. Creating the search form
  4. Outputting the search results

Custom Post Type:
For the first step it is relatively easy, create your own custom post type, within your functions.php file or somewhere else:

Resources:
https://www.codexworld.com/wordpress-custom-post-types-without-plugin/

  function product_init() {
        $labels = array(
            'name' => 'Products',
            'singular_name' => 'Product',
            'add_new' => 'Add New Product',
            'add_new_item' => 'Add New Product',
            'edit_item' => 'Edit Product',
            'new_item' => 'New Product',
            'all_items' => 'All Products',
            'view_item' => 'View Product',
            'search_items' => 'Search Products',
            'not_found' =>  'No Products Found',
            'not_found_in_trash' => 'No Products found in Trash',
            'parent_item_colon' => '',
            'menu_name' => 'Products',
        );
    
        $args = array(
            'labels' => $labels,
            'public' => true,
            'has_archive' => true,
            'show_ui' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'rewrite' => array('slug' => 'product'),
            'query_var' => true,
            'menu_icon' => 'dashicons-randomize',
            'supports' => array(
                'title',
                'editor',
                'excerpt',
                'trackbacks',
                'custom-fields',
                'comments',
                'revisions',
                'thumbnail',
                'author',
                'page-attributes'
            )
        );
        register_post_type( 'product', $args );
        register_taxonomy('product_category', 'product', array('hierarchical' => true, 'label' => 'Category', 'query_var' => true, 'rewrite' => array( 'slug' => 'product-category' )));
    }
    
    add_action( 'init', 'product_init' );

Custom fields:
Creating a custom field without ACF was more complicated than I expected, use Advanced Custom Fields plugin instead, and create a custom field applied to 'Type of Content' > 'Product' – or either custom post type you have. Create the fields such as: ‘City’, etc.

Search form:
Create a file called searchform.php within your template’s folder, and it will contain a simple <form>:

<form id="searchform" method="get" action="<?php echo esc_url( home_url( "https://wordpress.stackexchange.com/" ) ); ?>">
    <input type="text" class="search-field" name="s" placeholder="Search" value="<?php echo get_search_query(); ?>">
    <input type="hidden" name="post_type[]" value="product" />
    <input type="submit" value="Search">
</form>

Resources:
https://wordpress.stackexchange.com/a/17119/219065
https://artisansweb.net/create-custom-search-form-wordpress/

Results:
Within the search.php file, I go the following code:

$args = array(
    'post_type'  => 'product',
    'meta_query' => array(
        array( 'key' => 'city', 'value' => 'Moscow', 'meta_compare' => 'LIKE' ),
        array( 'key' => 'city', 'value' => array('Edinburgh', 'Moscow'), 'meta_compare' => 'IN' ),
        'relation' => 'OR'
    )
);

$the_query = new WP_Query( $args );

if ( $the_query->have_posts() ) {
    while ( $the_query->have_posts() ) : $the_query->the_post();
        echo get_the_title();
    endwhile;
} else {
 echo "No posts";
}

wp_reset_postdata();

Resources:
https://www.smashingmagazine.com/2016/03/advanced-wordpress-search-with-wp_query/
https://rudrastyh.com/wordpress/meta_query.html
Meta_query compare operator explanation


postscript. You will have to tweak and adapt a big portion of the code because it is of course not ready to handle all situations where you are going to be using the search function. And I found many elements in the code unnecessary and incomplete (check the resources for more), but it serves just as an example and I hope it helps you.