Support » Developing with WordPress » How to get metadata in select?

  • So I’m building an advanced search form in which I need to ble able to look for posts and cpts with a specific meta_key which is “estado_de_video” and it has two meta_values which are “finalizado” and “en emision”.

    So far I tried doing this:

    
    <div class="col-md-4">
        <div class="form-group">
            <label for="q_taxonomy">Estado</label>
            <select class="form-control" id="q_taxonomy">
                <option value="any" selected>Sin especificar</option>
    			<?php 
                $meta_key = 'estado_de_video';
                $meta_value = array('Emisión', 'Finalizado');
                $post_metadata = get_metadata($meta_key, $meta_value);
                if ( $post_metadata ) {
                  foreach ( $post_metadata  as $metadata ) {
                    echo '<option>' . $metadata . '</option>';
                  }
                }
                ?>
            </select>
        </div>
    </div>
    

    I currently get nothing. Can somebody guide me through it, please ?

    To make it more clear , I just want to get the custom field “estado_de_video”; I have currently used it twice in different posts(two posts), one has “emision” while the second one has “finalizado”.

    Thanks in advance.

Viewing 7 replies - 1 through 7 (of 7 total)
  • Joey

    (@leglesslizard)

    Hey,

    What are you after exactly here? Are you trying to implement a filter on a post archive page that allows you to select a “video state” and shows all of the posts for that selection?

    Before using functions have a look in the codex at what they do get_metadata for example will get the metadata available for the given key for the given post object (or ID). So this is why it isn’t working for you.

    Instead you’d probably be better off looking at WP_Query and using the arguments required to get all the posts for the chosen meta. Check it out here: https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters

    For actually populating the select field: if it’s just those 2 options why not hard code it?

    Dion

    (@diondesigns)

    I agree that you should hardcode the meta values into your code…especially since you are calling/using get_metadata() incorrectly. You should also add value attributes to your <option> tags, And you might want to add nane="q_taxonomy" to the <select> tag.

    Thread Starter kirasiris

    (@kirasiris)

    Well I’m building an advanced search page for my post types. This page will sort post by looking into these “post_type, taxonomy, meta_value(en_emision or en_final) and year”.

    Depending on what option is selected the posts should appear

    I already have function which is actually the one that I’m trying to use with this page but the problem is that I just cannot make it work(with the meta values), I mean if I select a cpt it shows the posts, if I select a taxonomy it shows me the posts related to that taxonomy and the year works fine as well.

    I already said that I have function which is pretty much done I just need to edit a bit more and a bit of help.

    If you guys want me to post another question and put both the html file and the function(which is very large) I will be more than please and grateful for the help.

    • This reply was modified 2 years, 11 months ago by kirasiris.
    Joey

    (@leglesslizard)

    No need for another question but you could post the code if you think it’ll help people to understand your query. Your original query was about populating a select box, with the advice given this should now look something like this:

    <div class="col-md-4">
        <div class="form-group">
            <label for="q_taxonomy">Estado</label>
            <select class="form-control" id="q_taxonomy" name="q_taxonomy">
                <option value="any" selected>Sin especificar</option>
    	    <option value="emision">Emision</option>
                <option value="finalizado">Finalizado</option>
            </select>
        </div>
    </div>

    With regards to sorting the posts you’ll require a custom meta query to return the correct posts as described here: https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters

    I can only assume you’re doing similar queries for your taxonomies etc

    Thread Starter kirasiris

    (@kirasiris)

    Well I just found out I can not edit the question(they should have implemented it long ago..) so I will just paste them(html file and function) here:

    HTML file(custom page):

    
    <?php 
    /*
    Template Name: Direcotorio
    Template Post Type: page
    */
    ?>
    <?php get_header(); ?>
    	<div class="container">
        	<div class="row">
            	
    
    <div id="my-adv-search">
    <!-- Post Type -->
    <div class="col-md-3">
        <div class="form-group">
            <label for="q_post_type">Tipo</label>
            <select class="form-control" id="q_post_type">
                <option selected>Selecciona una opcion</option>
                <?php
    			$args = array(
    				'public'	=> true,
    				'_builtin' => false,
    			);
    			$post_types = get_post_types($args);
    				foreach( $post_types as $post_type ) {
    					echo '<option>' . $post_type . '</option>' ;	
    				}
    			?>
            </select>
        </div>
    </div>
    
    <!-- Genero -->
    <div class="col-md-3">
        <div class="form-group">
            <label for="q_taxonomy">Genero</label>
            <select class="form-control" multiple id="q_taxonomy">
                <option value="any" selected>Selecciona una opcion</option>
    			<?php 
                $args = array(
                  'public'   => true,
                  '_builtin' => false
                ); 
                $output = 'names'; // or objects
                $operator = 'and'; // 'and' or 'or'
                $taxonomies = get_taxonomies( $args, $output, $operator ); 
                if ( $taxonomies ) {
                  foreach ( $taxonomies  as $taxonomy ) {
                    echo '<option>' . $taxonomy . '</option>';
                  }
                }
                ?>
            </select>
        </div>
    </div>
    
    <!-- Estado -->
    <div class="col-md-3">
        <div class="form-group">
            <label for="q_orderby">Estado</label>
            <select class="form-control" id="q_orderby">
                <option value="any" selected>Selecciona una opcion</option>
                <?php
                foreach ( [
                  'author'        => 'Author',
                  'comment_count' => 'Popularity (# of Comments)',
                  'year'          => 'Year',
                  'en_emision'   => 'Emision',
                  'en_final'   => 'Finalizado',
                  //'order'         => 'ASC ? DESC',
                ] as $value => $label ) {
                  printf( '<option value="%s">%s</option>',
                    esc_attr( $value ), esc_html( $label ) );
                }
                ?>
            </select>
        </div>
    </div>
    
    <!-- Year -->
    <div class="col-md-3">
        <div class="form-group">
            <label for="q_year">Año</label>
            <select class="form-control" id="q_year">
                <option value="any" selected>Selecciona una opcion</option>
                <?php
    			$args = array(
    				'public'	=> true,
    				'_builtin'	=> false,
    				'type'		=> 'yearly',
    				'format'	=> 'option',
    			);
    			wp_get_archives($args);
    			?>
            </select>
        </div>
        
    </div>
    
    <!-- Nonce field. -->
    <?php wp_nonce_field( 'my-adv-search', 'q_nonce' ); ?>
    
    <!-- Search Button -->
    <div class="col-md-12">
        <input type="submit" class="btn btn-success" id="buscar_btn" value="Search">
        <br><br>
        <noscript><b>Tu buscador no soporta Javascript, haciendo imposible mostrar los posts.</b></noscript>
        <div id="resultados"><div class="cargando_medio"></div></div>
    </div>
    </div><!-- End #my-adv-search -->
    
            </div>
        </div>
    
    <?php get_footer(); ?>
    <script type="text/javascript">
    jQuery( function( $ ){
        var ajaxurl = '/wptests/wp-admin/admin-ajax.php';
    
        function searchPosts( btn ) {
            var _btn_text = btn.value;//, q_order;
    
            btn.disabled = true;
            btn.value = 'Searching..';
    
    //        q_order = $( '#q_order-asc' ).is( ':checked' ) ?
    //            'ASC' : 'DESC';
    
            return $.post( ajaxurl, {
                action: 'my_adv_search',
                q_nonce: $( '#q_nonce' ).val(),
                q_post_type: $( '#q_post_type' ).val(),
                q_taxonomy: $( '#q_taxonomy' ).val(),
                q_year: $( '#q_year' ).val(),
                q_orderby: $( '#q_orderby' ).val(),
    //            q_order: q_order,
            } ).done( function( s ){
                if ( 'session_expired' === s ) {
                    location.reload();
                    return;
                }
    
                $( '#resultados' ).html( s );
            } ).always( function(){
                btn.value = _btn_text;
                btn.disabled = false;
            } );
        }
    
        $( '#buscar_btn', '#my-adv-search' ).on( 'click', function( e ){
            e.preventDefault();
    
            // Run AJAX search.
            searchPosts( this );
    
            // Remove button focus.
            this.blur();
        } );
    } );
    </script>
    

    and the function file: which is almost done, you will see where I’m having troubles at:

    
    // Buscador Avanzado
    add_action( 'wp_ajax_my_adv_search', 'ajax_my_adv_search' );
    add_action( 'wp_ajax_nopriv_my_adv_search', 'ajax_my_adv_search' );
    function ajax_my_adv_search() {
        if ( ! check_ajax_referer( 'my-adv-search', 'q_nonce', false ) ) {
            echo 'session_expired';
            wp_die();
        }
    
        $post_type = isset( $_POST['q_post_type'] ) ? $_POST['q_post_type'] : '';
        $taxonomy = isset( $_POST['q_taxonomy'] ) ? $_POST['q_taxonomy'] : [];
        $year = isset( $_POST['q_year'] ) ? $_POST['q_year'] : '';
        $orderby = isset( $_POST['q_orderby'] ) ? $_POST['q_orderby'] : [];
        $order = isset( $_POST['q_order'] ) ? $_POST['q_order'] : '';
    
        // Note that if $post_type is 'any', all post statuses will be included. In
        // that case, you may want to set specific post statuses below.
        $post_status = 'publish';
    
        // by Taxonomy
        $taxonomy = array_filter( (array) $taxonomy );
        if ( ! in_array( 'any', $taxonomy ) ) {
            $taxonomy = array_unique( array_map( 'trim', $taxonomy ) );
    
            add_filter( 'posts_join', function( $c ) use ( $taxonomy ) {
                if ( ! empty( $taxonomy ) ) {
                    global $wpdb;
                    // 1 below is one/number and not the lowercase of L
                    $c .= " INNER JOIN {$wpdb->term_relationships} AS ctr1 ON ctr1.object_id = {$wpdb->posts}.ID" .
                        " INNER JOIN {$wpdb->term_taxonomy} AS ctt1 ON ctt1.term_taxonomy_id = ctr1.term_taxonomy_id";
                }
                return $c;
            } );
    
            add_filter( 'posts_where', function( $c ) use ( $taxonomy ) {
                if ( ! empty( $taxonomy ) ) {
                    $tax_list = array_map( 'esc_sql', $taxonomy );
                    $tax_list = "'" . implode( "', '", $tax_list ) . "'";
    
                    // 1 below is one/number and not the lowercase of L
                    $c .= " AND ( ctt1.taxonomy IN ($tax_list) )";
                }
                return $c;
            } );
        }
    
        // by Custom Field Value - Metadata
        $orderby = array_filter( (array) $orderby );
        if ( in_array( 'any', $orderby ) ) {
            // Don't sort by post date.
            $orderby2 = false;
        } else {
            $orderby = array_unique( array_map( 'trim', $orderby ) );
    
            // TRUE if we're sorting by year.
            $ob_year = false;
    
            foreach ( $orderby as $i => $s ) {
                // Sort posts by year.
                if ( 'year' === $s ) {
                    $ob_year = true;
                    unset( $orderby[ $i ] );
                }
    //// PROBLEM BEGINS HERE
                // Sort posts by meta value en_emision from meta key estado_de_video. Note that this would only return
                // posts that have the custom field 'en_emision'.
                if ( 'en_emision' === $s ) {
                    $meta_key = 'en_emision';
                    $orderby2 = 'meta_value';
                    unset( $orderby[ $i ] );
                }
    
                // Sort posts by meta value en_final from meta key estado_de_video. Note that this would only return
                // posts that have the custom field 'en_final'.
                if ( 'en_final' === $s ) {
                    $meta_key = 'en_final';
                    $orderby2 = 'meta_value';
                    unset( $orderby[ $i ] );
                }
            }
    
    //// PROBLEM ENDS HERE
            add_filter( 'posts_orderby', function( $c, $q ) use ( $ob_year ) {
                if ( $ob_year ) {
                    global $wpdb;
    
                    // Use the value parsed by WP_Query.
                    $order = $q->get( 'order' );
    
                    $c .= $c ? ', ' : '';
                    $c .= "YEAR({$wpdb->posts}.post_date) $order";
                }
                return $c;
            }, 10, 2 );
    
            $ok = isset( $orderby2 );
            if ( ! $ok && empty( $orderby ) ) {
                // Don't sort by post date.
                $orderby2 = false;
            } elseif ( ! $ok ) {
                // Pass to WP_Query as a string.
                $orderby2 = implode( ' ', $orderby );
            }
        }
    
        // by Year
        if ( ! is_numeric( $year ) ) {
            $year = '';
        }
    
        
    
        $q = new WP_Query( [
            'post_status' => $post_status,
            'post_type'   => array($post_type),
            'posts_per_page' => -1,
            'post_parent' => 0,
            'year'        => $year,
            'meta_key'    => isset( $meta_key ) ? $meta_key : '',
            'orderby'     => $orderby2,
            'order'       => $order,
    
        ] );
    
        if ( $q->have_posts() ) {
            echo '<ul>';
            while ( $q->have_posts() ) {
                $q->the_post();
                ?>
                <li><a href="<?php the_permalink(); ?>"><?php the_title() ?></a></li>
                <?php
            }
            echo '</ul>';
        } else {
            echo '<div class="alert alert-danger">Ningun Resultado</div>';
        }
    
        wp_die();
    }
    

    If you guys want to implement them in your theme just to test it out or to do something similar exactly, feel free to do so(should be easy to implement); I don’t mind but yeah, that’s it. I will probably edit the taxonomy one later on just to make the taxonomies(categories or tags; I have not decided yet) appear according to what post type has been selected(but that’s not necessary right now; probably another question if I dont figure it out.).

    Bare with me!!.

    Thanks again.

    Joey

    (@leglesslizard)

    It looks to me like you’re trying to order the posts by custom meta field “estado_de_video” is that right? And this field either has a value of “en_emision” or “en_final”?

    The issue here is when ordering by a custom meta field you pass in the field key (estado_de_video) and you orderby either meta_value (for strings) or meta_value_num (for integers). You are passing in the meta_value which it won’t find as it is looking for a meta key.

    I think if you adjust your query as follows you may be closer to what you want:

    $q = new WP_Query( [
            'post_status' => $post_status,
            'post_type'   => array($post_type),
            'posts_per_page' => -1,
            'post_parent' => 0,
            'year'        => $year,
            'orderby'     => '', //SET THIS AS REQUIRED
            'order'       => $order,
    
        ] );
    if ( isset( $meta_key ) && '' != $meta_key ) {
        $q['meta_key'] = 'estado_de_video';
        $q['meta_value'] = $meta_key;
    }

    This should just return the posts with the meta value as expected

    Thread Starter kirasiris

    (@kirasiris)

    Nothing yet man. It just keeps retrieving the “Ningun resultado”. I actually posted the same question in Stackoverflow as well. If you want to keep yourself up to date in case you might need it later on or if you want to keep helping, here is the link: QUESTION.

    You can see there what other “extra” stuff I have tried.

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘How to get metadata in select?’ is closed to new replies.