2

I am building an advanced search form but the search is showing all post all time with this error too array_key_exists() expects parameter 2 to be array, string was given

this is my code in header.php

<?php $query_types = get_query_var('post_type'); ?>
<?php

     $args = array(
                 'public'   => true,
                 '_builtin' => false
             );

     $output = 'names'; // names or objects, note names is the default
     $operator = 'and'; // 'and' or 'or'

     $post_types = get_post_types( $args, $output, $operator ); 

     //array array_slice ( array $array , int $offset [, int $length = NULL [, bool $preserve_keys = false ]] ) see http://php.net/manual/en/function.array-slice.php
    foreach ( array_slice($post_types, 0, 5) as $post_type ) { //display max 5 post_type
         ?> 
    <li>
        <a>
           <input id="<?php  echo $post_type ?>" class="btn btn-lg" type="checkbox" name="post_type[]" value="<?php  echo $post_type ?>" <?php if (!empty($query_types) && array_key_exists($post_type , $query_types)) { echo 'checked="checked"'; } ?>/> 
           <!-- array_key_exists($post_type , $query_types) -->
           <label for="<?php  echo $post_type ?>"><span><?php  echo $post_type ?></span></label> 
       </a> 
    </li> 
 <?php 
} 
?>

in searchform.php a have this:

<?php
    $postType = array("construction","renovation","agrandissement","bradage");

    foreach ($postType as &$value) {
        echo '<input type="hidden" name="post_type[]" value="'.$value.'" />';
    }
    unset($value); // break the reference with the last element
?>

when I add && is_array($query_types) in header.php array_key_exists() expects parameter 2 to be array, string given doesn`t show anymore but the result is empty. i also get

%5B%5D  

in the url

mywebsite.com/?s=LED70266765IKEA&post_type%5B%5D=boutique

please help me figuring out what I am doing wrong.

UPDATE:

here is my search.php

<?php

 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

?>
<section id="primary" class="row">
    <main id="main" class="container" role="main">
    <?php if ( have_posts() ) : ?>

        <header class="page-header">
            <h5 class="page-title">
                <?php printf( __( 'Résultats de recherche pour: %s', 'igorconstructions' ), '<span>' . esc_html( get_search_query() ) . '</span>' ); ?>
            </h5>
        </header><!-- .page-header --> 
        <?php
        // Start the loop.
        while ( have_posts() ) : the_post();

            /**
             * Run the loop for the search to output the results.
             * If you want to overload this in a child theme then include a file
             * called content-search.php and that will be used instead.
             */
            get_template_part( 'template-parts/content', 'search' );

        // End the loop.
        endwhile;
        ?>
        <!-- PAGINATION -->
        <div class="row">
            <div class="col-md-12">
                <div class="paging-navigation text-right">
                    <?php    
                        the_posts_pagination( array(
                            'screen_reader_text' => ( '' ),
                            'type'      => 'list',
                            'end_size'      => 3,
                            'mid_size'      => 3,
                            'format' => '?paged=%#%',
                            'prev_text' => '<span class="icon-angle-left">&larr;</span>',
                            'next_text' => '<span class="icon-angle-right">&rarr;</span>',
                            'before_page_number' => 'Page',
                            'after_page_number'  => '', 
                        ) ); 
                    ?>      
                </div><!--  end pagination container -->
            </div><!-- end large-12 -->
        </div>
        <!-- end PAGINATION -->
        <?php 
    // If no content, include the "No posts found" template.
    else :
        get_template_part( 'template-parts/content', 'none' );

    endif;
    ?>

    </main><!-- .site-main -->
</section><!-- .content-area -->

and content-search.php looks like this:

 <?php if(isset($_GET['post_type'])) {
    $type = $_GET['post_type'];
    //$type = $wp_query->query['post_type'];
    if ( in_array( $type, array('boutique','news','text') ) ) {?>

    <section class="col-md-4">
        <article id="product-<?php the_ID(); ?>" <?php post_class(); ?>>    
            <!--
                Thumbnail
            -->
            <div class="product-image">
                <figure  class="product-thumb">
                    <!-- === Confitional thumbnail=== -->
                    <?php if (  (function_exists('has_post_thumbnail')) && (has_post_thumbnail())) : ?> 
                            <!--Image size //thumbnail medium large full-->
                            <?php the_post_thumbnail('medium', 'blog-thumb', array('class' => 'blog-thumb')); ?>

                            <?php else :?>

                            <img class="blog-thumb" src="<?php echo get_template_directory_uri(); ?>/images/cat-images/<?php $category = get_the_category(); echo $category[0]->slug; ?>.jpg" /> 

                    <?php endif; ?>
                </figure>
            </div>

            <div class="product-description">
                 <!--
                    The Title
                -->
                <h4>
                    <a href="<?php the_permalink() ?>" rel="bookmark" title="m'en dire plus à ce sujet '<?php the_title_attribute(); ?>' svp!"><?php the_title(); ?></a>
                </h4>
                <P>
                    <?php 
                        $url = get_post_meta( $post->ID, 'price', true ); 

                        if ($url) {
                            echo '<strong>à partir de:</strong> <strong class=thumbnail-price>'.$url.' FCFA TTC</strong>/ Unité';
                        }
                    ?>
                </P> 
            </div>

            <div class="user-actions">
            <!--
                User actions
            -->

                <!-- Product reference-->

                <p class="text-right">
                    <strong>Référence: </strong>
                    <span><?php echo get_post_meta( $post->ID, 'reference', true ) ?></span>
                </p>
                <p class="text-right">
                    <button class="action-btn-prim">
                        <a href="<?php the_permalink() ?>">Voir l'article</a>
                    </button>
                </p>
                <form class="text-right"> 
                    <button class="add-to-cart action-bt"> 
                        <a><svg class="pull-left" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" width="20px" height="20px" viewBox="0 0 29 30" version="1.1">

                            <g xmlns="http://www.w3.org/2000/svg" id="Group">
                                <path fill="floralwhite" d="M5.87076823,28.1796875 C4.57567676,28.1796875 3.52246094,27.1264717 3.52246094,25.8313802 C3.52246094,24.5362887 4.57567676,23.4830729 5.87076823,23.4830729 C7.1658597,23.4830729 8.21907552,24.5362887 8.21907552,25.8313802 C8.21907552,27.1264717 7.1658597,28.1796875 5.87076823,28.1796875 L5.87076823,28.1796875 Z M5.87076823,24.6572266 C5.22322249,24.6572266 4.69661458,25.1838345 4.69661458,25.8313802 C4.69661458,26.4789259 5.22322249,27.0055339 5.87076823,27.0055339 C6.51831396,27.0055339 7.04492188,26.4789259 7.04492188,25.8313802 C7.04492188,25.1838345 6.51831396,24.6572266 5.87076823,24.6572266 L5.87076823,24.6572266 Z" id="Shape"/>
                                <path fill="floralwhite" d="M18.7864583,28.1796875 C17.4913669,28.1796875 16.438151,27.1264717 16.438151,25.8313802 C16.438151,24.5362887 17.4913669,23.4830729 18.7864583,23.4830729 C20.0815498,23.4830729 21.1347656,24.5362887 21.1347656,25.8313802 C21.1347656,27.1264717 20.0815498,28.1796875 18.7864583,28.1796875 L18.7864583,28.1796875 Z M18.7864583,24.6572266 C18.1389126,24.6572266 17.6123047,25.1838345 17.6123047,25.8313802 C17.6123047,26.4789259 18.1389126,27.0055339 18.7864583,27.0055339 C19.4340041,27.0055339 19.960612,26.4789259 19.960612,25.8313802 C19.960612,25.1838345 19.4340041,24.6572266 18.7864583,24.6572266 L18.7864583,24.6572266 Z" id="Shape"/>
                                <path fill="floralwhite" d="M12.3286133,9.39322917 C12.0039598,9.39322917 11.7415365,9.13080583 11.7415365,8.80615234 L11.7415365,0.587076823 C11.7415365,0.26242334 12.0039598,0 12.3286133,0 C12.6532668,0 12.9156901,0.26242334 12.9156901,0.587076823 L12.9156901,8.80615234 C12.9156901,9.13080583 12.6532668,9.39322917 12.3286133,9.39322917 L12.3286133,9.39322917 Z" id="Shape"/>
                                <path fill="floralwhite" d="M12.3286133,9.39322917 C12.1783216,9.39322917 12.0280299,9.33569564 11.91355,9.22121566 L8.39108903,5.69875472 C8.16154199,5.46920768 8.16154199,5.09817513 8.39108903,4.86862809 C8.62063607,4.63908105 8.99166862,4.63908105 9.22121566,4.86862809 L12.3286133,7.97602572 L15.4360109,4.86862809 C15.6655579,4.63908105 16.0365905,4.63908105 16.2661375,4.86862809 C16.4956846,5.09817513 16.4956846,5.46920768 16.2661375,5.69875472 L12.7436766,9.22121566 C12.6291966,9.33569564 12.4789049,9.39322917 12.3286133,9.39322917 L12.3286133,9.39322917 Z" id="Shape"/>
                                <path fill="floralwhite" d="M18.7864583,24.6572266 L5.87076823,24.6572266 C5.54611475,24.6572266 5.28369141,24.3948032 5.28369141,24.0701497 C5.28369141,23.7454963 5.54611475,23.4830729 5.87076823,23.4830729 L18.3214935,23.4830729 L22.9112601,3.97509717 C22.9740773,3.70973844 23.2106693,3.52246094 23.4830729,3.52246094 L27.5926107,3.52246094 C27.9172642,3.52246094 28.1796875,3.78488428 28.1796875,4.10953776 C28.1796875,4.43419124 27.9172642,4.69661458 27.5926107,4.69661458 L23.9480378,4.69661458 L19.3582712,24.2045903 C19.2954539,24.4699491 19.058862,24.6572266 18.7864583,24.6572266 L18.7864583,24.6572266 Z" id="Shape"/>
                                <path fill="floralwhite" d="M19.3735352,22.3089193 L4.10953776,22.3089193 C3.85650765,22.3089193 3.63283138,22.1474731 3.55298893,21.9073587 L0.0305279948,11.3399759 C-0.029940918,11.1609175 0.000587076823,10.9636597 0.11095752,10.8110197 C0.221327962,10.6577926 0.398625163,10.5673828 0.587076823,10.5673828 L21.7218424,10.5673828 C22.0464959,10.5673828 22.3089193,10.8298062 22.3089193,11.1544596 C22.3089193,11.4791131 22.0464959,11.7415365 21.7218424,11.7415365 L1.40193945,11.7415365 L4.53282015,21.1347656 L19.3735352,21.1347656 C19.6981886,21.1347656 19.960612,21.397189 19.960612,21.7218424 C19.960612,22.0464959 19.6981886,22.3089193 19.3735352,22.3089193 L19.3735352,22.3089193 Z" id="Shape"/>
                            </g>
                            </svg>
                             Ajouter
                        </a>
                    </button>
                </form>
            </div>
            <hr>
        </article>
    </section>     
    <?php } 
  elseif($type == 'construction'){


  }
  elseif($type == 'blog'){


   }
 }else { ?>

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>


<?php if ( 'post' === get_post_type() ) : ?>

<?php else : ?>

    <?php get_the_title() ?>

<?php endif; ?>

2 Answers 2

1
+50

The core issue is that you're having trouble creating a filtered search. Why not use a pre_get_posts hook to modify the query before it actually gets called, then you don't need to modify the template files at all:

/**
 * Modify WP_Query before it asks the database what data to retrieve
 * Belongs in functions.php
 *
 * @param WP_Query Object $query
 *
 * @return void
 */
function wpse_265499( $query ) {

    // Don't run on admin
    if( $query->is_admin ) {
        return;
    }

    // IF main query and search page
    if( $query->is_main_query() && $query->is_search() ) {

        // IF we have our post type array set 
        if( isset( $_GET, $_GET['post_type'] ) && ! empty( $_GET['post_type'] ) ) {
            $query->set( 'post_type', $_GET['post_type'] );     // Will be set as boutique
        }

    }

}
add_action( 'pre_get_posts', 'wpse_265499' );

The above would be added to your functions.php file and what pre_get_posts does is before it goes to the database and grabs the data to be displayed, we can modify what is being requested. In this case we're saying IF we have post_types set in the URL as a $_GET, grab only those post types. So your main query will now only show the post types assigned in $_GET at which point there's no need for the conditional statements in your template.


Let's break this down starting with the error itself.

array_key_exists() expects parameter 2 to be array, string was given

So based on the error we know that array_key_exists() needs parameter 2 to be an array, so that it can search for a key, but at some point a string was given instead of an array.

As far as I can tell you only have one instance of array_key_exists() and it looks like this:

array_key_exists( $post_type , $query_types )

Combined with the PHP error we can surmise that $query_types must be a string instead of the array that we need for array_key_exists() to work. Let's look at how $query_types is set:

$query_types = get_query_var( 'post_type' );

If we look at the get_query_var() function we see it can return an array because the return type is mixed. That being said, we're only asking for one post_type so it's probably returning a string for the queried post type.

I'm not sure what it is you're trying to accomplish but hopefully that clears up the reason you're getting that error.

5
  • thank you for your time i am just trying to create an advanced search form for CPT somehow i only get all posts as results and that array_key_exists error. May 5, 2017 at 10:07
  • @Bansoaistheanswer I've updated my answer, you may want to use pre_get_posts instead of conditional statements in the template.
    – Howdy_McGee
    May 10, 2017 at 14:31
  • ok now it shows all cpt posts no matter what i search. May 10, 2017 at 14:43
  • @Bansoaistheanswer I've just tested this in my theme and it works as expected. Given the following query string: ?s=a&post_type%5B%5D=post&post_type%5B%5D=boutique will only show those two post types. You're removing your conditional code in content-search.php ( reverting it back to the original file ) and pasting the pre_get_posts hook above into your functions.php, right?
    – Howdy_McGee
    May 10, 2017 at 14:50
  • 1
    thank you for your help i found the problem it was a line of code i added in functions.php if ( $query->is_search ) { $meta_query_args = array( array( 'key' => 'price', 'value' => $query->query_vars['s'] = '', 'compare' => 'LIKE', ) ); $query->set('meta_query', $meta_query_args); }; May 10, 2017 at 14:59
0

The answer by Howdy_McGee is correct, but just to expand upon their answer:

get_query_var() is a function that requires one parameter and the second is an optional default value. It is a wrapper for WP_Query::get() that has the same parameters. This method checks whether WP_Query->query_vars[ $query_var ] exists, and if it does, returns that value.

Query vars can be set using the WP_Query::set() method, and the value can be anything: null, integer, string, array, object, whatever. So the get method will return anything as long as it exists. In the case it doesn't exist, it will return whatever the second parameter was passed to get_query_var(). In this case, that was nothing, so it uses the default of an empty string.

array_key_exists(), as you've found out, requires that the second parameter be an array. Since we don't know that get_query_var() might not return an array, then we need to make sure before we pass it to a function that requires an array as an input.

//* Cast as an array
$query_types = (array) get_query_var( 'post_type', [] );

PHP casting to array will "for any of the types integer, float, string, boolean and resource, converting a value to an array results in an array with a single element with index zero and the value of the scalar which was converted."

Since the $query_types will be guaranteed to be an array, you shouldn't have that error, and hopefully your advanced search will work as intended.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.