WordPress.org

Ready to get started?Download WordPress

Forums

Custom Post Type and WP_query (8 posts)

  1. RyAnaon
    Member
    Posted 4 months ago #

    Hello,

    I'm not really sure about the section but I tried.

    For a week now, I'my trying to use que custom post type correctly for my project.

    But now, I managed to do what I need for the single page.

    I need one more thing and this is for the archive page.

    Is it possible to group the post type by month with only one wp-query or do I need to create one request for one month on my side and update it every month?

    And how to display a field on the archive page like the date?

    Here is the code for my page-cruises.php

    <?php
    /*Template Name: Cruises list*/
    
    get_header(); ?>
    
        <div id="primary" class="content-area eight columns">
            <div id="content" class="site-content" role="main">
    
    			<article class="hentry">
    
    			    <?php
                        if ( function_exists('yoast_breadcrumb') )
                        {
                            yoast_breadcrumb('<p id="breadcrumbs">','</p>');
                        }
                    ?>
    
    				<?php $loop = new WP_Query(array( 'post_type' => 'cruises', 'posts_per_page' => 10, 'order' => 'ASC' )); ?>
    
    				<?php while ( $loop->have_posts() ) : $loop->the_post(); ?>
    
    				<header class="entry-header">
    
    				<?php the_title( '<h1 class="entry-title"><a href="' . get_permalink() . '" title="' . the_title_attribute( 'echo=0' ) . '" rel="bookmark">', '</a></h1>' ); ?>
    
    				</header>
    
    				<div class="entry-content">
    					<?php  the_excerpt(); ?>
    				</div>
    				<?php endwhile; ?>
    
    			</article>
    
    		</div><!-- #content .site-content -->
    
    	</div><!-- #primary .content-area -->
    
    <?php get_sidebar(); ?>
    
    <?php get_footer(); ?>

    and the custom post type on function.php :

    add_action('init', 'cruises_init');
    function cruises_init()
    {
        $labels = array
        (
            'name' => _x('Croisières', 'post type general name'),
            'singular_name' => _x('Croisière', 'post type singular name'),
            'add_new' => _x('Ajouter nouvelle', 'portfolio item'),
            'add_new_item' => __('Ajouter nouvelle croisière'),
            'edit_item' => __('Modifier croisière'),
            'new_item' => __('Nouvelle croisière'),
            'view_item' => __('Voir croisière'),
            'search_items' => __('Chercher croisière'),
            'not_found' =>  __('Rien trouvé'),
            'not_found_in_trash' => __('Rien trouvé dans la poubelle'),
            'parent_item_colon' => ''
        );
    
        $args = array
        (
            'labels' => $labels,
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'query_var' => true,
            'rewrite' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'menu_position' => null,
            'supports' => array('title', 'editor', 'thumbnail', 'revisions', 'page-attributes')
        );
    
        register_post_type( 'cruises' , $args );
    
        register_taxonomy("Armateur", array("cruises"), array("hierarchical" => true, "label" => "Armateurs", "singular_label" => "Armateur", "rewrite" => true));
    
        add_action("admin_init", "admin_init");
    
        function admin_init(){
            add_meta_box("cruises_titles", "Titres de la croisière", "cruises_titles", "cruises", "normal", "low");
            add_meta_box("cruises_details", "Détails de la croisière", "cruises_details", "cruises", "normal", "low");
            add_meta_box("cabins", "Cabines", "cabins", "cruises", "normal", "low");
        }
    
        function cruises_titles()
        {
            global $post;
            $custom = get_post_custom($post->ID);
            $slogan = $custom["slogan"][0];
            $theme = $custom["theme"][0];
            ?>
            <p><label>Slogan :</label><br />
                <input type="text" name="slogan" value="<?php echo $slogan; ?>" /></p>
            <p><label>Thème :</label><br />
                <input type="text" name="theme" value="<?php echo $theme; ?>" /></p>
        <?php
        }
    
        function cruises_details()
        {
            global $post;
            $custom = get_post_custom($post->ID);
            $ship = $custom["ship"][0];
            $travel = $custom["travel"][0];
            $departure = $custom["departure"][0];
            $duration = $custom["duration"][0];
            $price = $custom["price"][0];
    	    $details = $custom["details"][0];
            ?>
            <p><label>Navire :</label><br />
                <input type="text" name="ship" value="<?php echo $ship; ?>" /></p>
            <p><label>Circuit :</label><br />
                <textarea cols="50" rows="5" name="travel"><?php echo $travel; ?></textarea></p>
            <p><label> Date départ :</label><br />
                <input type="text" name="departure" value="<?php echo $departure; ?>" /></p>
            <p><label>Durée :</label><br />
                <input type="text" name="duration" value="<?php echo $duration; ?>" /></p>
            <p><label>Prix de départ  :</label><br />
                <input type="text" name="price" value="<?php echo $price; ?>" /></p>
    	    <p><label>Détails et conditions :</label><br />
    		    <textarea cols="50" rows="5" name="details"><?php echo $details; ?></textarea></p>
            <?php
        }
    
        function cabins()
        {
            global $post;
            $custom = get_post_custom($post->ID);
            $cabin1 = $custom["cabin1"][0];
            $cabin2 = $custom["cabin2"][0];
            $cabin3 = $custom["cabin3"][0];
            $cabin4 = $custom["cabin4"][0];
            $cabin5 = $custom["cabin5"][0];
            ?>
            <p><label>Cabine intérieure :</label><br />
                <input type="text" name="cabin1" value="<?php echo $cabin1; ?>" /></p>
            <p><label>Cabine vue sur mer :</label><br />
                <input type="text" name="cabin2" value="<?php echo $cabin2; ?>" /></p>
            <p><label>Cabine avec balcon :</label><br />
                <input type="text" name="cabin3" value="<?php echo $cabin3; ?>" /></p>
            <p><label>Cabine avec mini-suite :</label><br />
                <input type="text" name="cabin4" value="<?php echo $cabin4; ?>" /></p>
            <p><label>Cabine avec suite :</label><br />
                <input type="text" name="cabin5" value="<?php echo $cabin5; ?>" /></p>
        <?php
        }
    
        function save_details()
        {
            global $post;
    
            update_post_meta($post->ID, "slogan", $_POST["slogan"]);
            update_post_meta($post->ID, "theme", $_POST["theme"]);
            update_post_meta($post->ID, "ship", $_POST["ship"]);
            update_post_meta($post->ID, "travel", $_POST["travel"]);
            update_post_meta($post->ID, "departure", $_POST["departure"]);
            update_post_meta($post->ID, "duration", $_POST["duration"]);
            update_post_meta($post->ID, "price", $_POST["price"]);
    	    update_post_meta($post->ID, "details", $_POST["details"]);
            update_post_meta($post->ID, "cabin1", $_POST["cabin1"]);
            update_post_meta($post->ID, "cabin2", $_POST["cabin2"]);
            update_post_meta($post->ID, "cabin3", $_POST["cabin3"]);
            update_post_meta($post->ID, "cabin4", $_POST["cabin4"]);
            update_post_meta($post->ID, "cabin5", $_POST["cabin5"]);
        }
    
        add_action('save_post', 'save_details');
    
    }
  2. bcworkz
    Member
    Posted 4 months ago #

    What you do depends on where the date is stored and in what format. I'm guessing you want the 'departure' date in post meta that is stored as a typical alpha-numeric date string. This sort of data is difficult if not impossible to deal with using WP_Query. The query involves mySQL conversion functions that are not available through WP_Query.

    Fortunately, we are able to modify the query established by WP_Query where we can add in the required conversion functions and whatever else we cannot accomplish through WP_Query arguments. The filters are all applied from the get_posts() method of WP_Query, they are listed in code on wp-includes/query.php starting about line 2856 for 3.8.1.

  3. bcworkz
    Member
    Posted 4 months ago #

    Almost forgot your date output question!

    Assuming the same departure date is what you want to display, and it is already correctly formatted, just add something like this to your archive page template:
    echo get_post_meta( $post->ID, "departure");

    This will need to be inside the "Loop".

  4. RyAnaon
    Member
    Posted 4 months ago #

    Thanks for the answer!

    I looked at the query.php file and I'm not sure if I will be able to modify this like I need without broke all my WP =D

    But yes, I want to order the archive page by "Departure" which is a meta_data stored on a string.

    Is there a function to display a little calendar for this in the administration and replace the

    <p><label> Date départ :</label><br />
                <input type="text" name="departure" value="<?php echo $departure; ?>" /></p>
    ?

    And for the second message, I did it like that :

    <?php $departure = get_post_meta($post->ID, "departure"); ?>
    
    				<?php echo '<h3>'.$departure[0].'</h3>'; ?>

    It returns an array so I fixed the little "mistake" with your echo.

    I'll search for someone who knows how to do what I need and post it here if we have a solution!

    Thanks again!

  5. bcworkz
    Member
    Posted 4 months ago #

    With HTML5 there is an input tag type "date" that displays a calendar with no extra coding. Unfortunately, IE and FF only display a text type input box instead of the calendar. There are numerous date picker calendar apps for javascript and jQuery you can use inside of meta boxes. If you haven't implemented custom javascript in WP before, you should know that you need to use wp_enqueue_script() to reference your script and establish any dependencies such as to jQuery. The generic instructions offered with date picker and other such apps will tell you put meta links or <script> blocks in the head section. That won't work well in WP. Besides that, following the instructions usually works fine.

    I suppose all those filters in source code can appear pretty intimidating if you're unfamiliar with such things. It's not as bad as it looks. I could help you with the PHP part of using the filters. The problem is I'm pretty clueless with mySQL functions and syntax so I've no idea how we would need to alter the clauses passed through these filters.

    Another possibility, depending on how much existing data you have, is to reconfigure the data to store departure dates as UNIX timestamps. Then you can numerically sort by meta values with WP_Query with no need for filters. Of course the input and output code would need to be adjusted to translate input strings to timestamps and then back again on output. This is actually the preferable configuration for this sort of thing due to the ease of querying numbers.

    A compromise approach would be to leave the departure date strings and add another meta key (or make the departure field into an array) for the equivalent timestamp for use in sorting, leaving the date string for display.

    Sorry about the array thing from get_post_meta(). I always forget about that detail for some reason :( It's a quirk of the function, and there is a third parameter with which you can suppress the array behavior. Using $departure[0] is fine as well, but I prefer suppressing the array to begin with like so:
    echo '<h3>'.get_post_meta($post->ID, "departure", true).'</h3>';
    Either way is equally valid (unless you purposely create an array as mentioned above), this is just FYI.

  6. RyAnaon
    Member
    Posted 4 months ago #

    With HTML5 there is an input tag type "date" that displays a calendar with no extra coding.

    How did I forget that... No problems for the dependencies with that, the people using the admin panel are only using Chrome under my order =)

    The problem with the source code isn't only the "intimidating" part, the fact is that I used 10 days to do exactly what I need while working on all the other work I had to do and it's pretty boring now.

    But if you have an exemple about how to do this, I could use some more time to complete the work.

    Is there a specific function to use in WP to store the data as Timestamps like you proposed?

    This sounds like a good option here!

    And thanks for the syntax, I'll use it now, I prefer that if I need this variable only here.

    You can see how I work in normal time :

    <?php get_header(); ?>
    
        <div id="primary" class="content-area full-width columns">
            <div id="content" class="site-content" role="main">
    
                <?php while ( have_posts() ) : the_post(); ?>
                    <?php
                        $slogan = get_post_meta($post->ID, 'slogan', true);
                        $theme = get_post_meta($post->ID, 'theme', true);
                        $ship =get_post_meta($post->ID, 'ship', true);
                        $travel =get_post_meta($post->ID, 'travel', true);
                        $departure =get_post_meta($post->ID, 'departure', true);
                        $duration = get_post_meta($post->ID, 'duration', true);
                        $price = number_format(get_post_meta($post->ID, 'price', true), 2, ',','\'');
    	                $details = get_post_meta($post->ID, 'details', true);
                        $cabin1 = number_format(get_post_meta($post->ID, 'cabin1', true), 2, ',','\'');
                        $cabin2 = number_format(get_post_meta($post->ID, 'cabin2', true), 2, ',','\'');
                        $cabin3 = number_format(get_post_meta($post->ID, 'cabin3', true), 2, ',','\'');
                        $cabin4 = number_format(get_post_meta($post->ID, 'cabin4', true), 2, ',','\'');
                        $cabin5 = number_format(get_post_meta($post->ID, 'cabin5', true), 2, ',','\'');
    					$company = get_taxonomy('Armateur');
                    ?>
                <article class="hentry">
    
                    <?php
                        if ( function_exists('yoast_breadcrumb') )
                        {
                            yoast_breadcrumb('<p id="breadcrumbs">','</p>');
                        }
                    ?>
    
                    <header class="entry-header">
    
                        <h1 class="entry-title">
                            <?php the_title(); ?>
                        </h1>
    	                <?
    	                if ( has_post_thumbnail() )
    	                {
    		                the_post_thumbnail();
    	                }
    	                ?>
                        <h2>
                            <?php
                                if ($slogan != ''){echo $slogan;}
                            ?>
                        </h2>
                        <h3>
                            <?php
                                if ($theme != ''){echo $theme;}
                            ?>
                        </h3>
                    </header>
    
                    <div class="entry-content">
    	                <div id="left" style="width: 50%; float: left; padding-right: 10px; text-align: justify;">
                            <?php the_content(); ?>
    	                </div>
    	                <div id="right" style="width: 50%; float: right; padding: 5px 5px 5px 10px; background-color: #E7E7E7;">
    	                    <p>
    	                        <b>Bateau</b> : <?php echo $ship ; ?>
    	                    </p>
    	                    <p>
    	                        <b>Trajet</b> : <?php echo $travel ; ?>
    	                    </p>
    	                    <p>
    	                        <b>Départ</b> : <?php echo $departure ; ?>
    	                    </p>
    	                    <p>
    	                        <b>Durée</b> : <?php echo $duration ; ?> jours
    	                    </p>
    	                    <p>
    	                        <b>Prix de départ</b> : <?php echo $price ; ?>
    	                    </p>
    	                </div>
    	                <div id="details" style="clear: both;">
    		                <h3>Détails</h3>
    		                <p style="text-align: justify;">
    		                    <?php echo $details; ?>
    		                </p>
    	                </div>
                        <table style="width:100%; text-align: center;">
                            <tr>
                                <td style="text-align: center; font-weight: bold; background-color: #E7E7E7;">
                                    Cabine 1
                                </td>
                                <td style="text-align: center; font-weight: bold; background-color: #E7E7E7;">
                                    Cabine 2
                                </td>
                                <td style="text-align: center; font-weight: bold; background-color: #E7E7E7;">
                                    Cabine 3
                                </td>
                                <td style="text-align: center; font-weight: bold; background-color: #E7E7E7;">
                                    Cabine 4
                                </td>
                                <td style="text-align: center; font-weight: bold; background-color: #E7E7E7;">
                                    Cabine 5
                                </td>
                            </tr>
                            <tr>
                                <td style="text-align: center; background-color: #E7E7E7;">
                                    <?php echo $cabin1 ; ?>
                                </td>
                                <td style="text-align: center; background-color: #E7E7E7;">
                                    <?php echo $cabin2 ; ?>
                                </td>
                                <td style="text-align: center; background-color: #E7E7E7;">
                                    <?php echo $cabin3 ; ?>
                                </td>
                                <td style="text-align: center; background-color: #E7E7E7;">
                                    <?php echo $cabin4 ; ?>
                                </td>
                                <td style="text-align: center; background-color: #E7E7E7;">
                                    <?php echo $cabin5 ; ?>
                                </td>
                            </tr>
                        </table>
                    </div>
    
                </article>
    
                <?php endwhile; // end of the loop. ?>
    
            </div><!-- #content .site-content -->
        </div><!-- #primary .content-area -->
    <?php get_footer(); ?>
  7. bcworkz
    Member
    Posted 4 months ago #

    Use of the various filters will vary greatly by circumstance, and you will not need them at all if you switch to timestamps. But for the sake of education, lets say you want to discard the default ORDER BY clause (wp_posts.post_date DESC, the actual 'ORDER BY ' is added elsewhere) and insert TIMESTAMP(wp_posts.post_date) ASC. I've no idea if the SQL syntax is correct, it doesn't really matter for this exercise. Anyway, this is the code to do this:

    add_filter('posts_orderby', 'ra_date_order');
    function ra_date_order( $clause ) {
       return 'TIMESTAMP(wp_posts.post_date) ASC';
    }

    If you needed to use part of the default clause, it gets more complicated with string manipulation and need to know what the default possibilities are, which can yield fragile code. At least a solution exists.

    Transforming back and forth to timestamps is very easy in PHP. To convert a date to timestamp, use strtotime(). It accepts just about any English date string and correctly converts it to a timestamp. If you use non-English month names, any possible inputs will need to be translated, or only allow numeric inputs. There is some ambiguity with numeric dates. The function relies on the separator to decide if the month and days are American order using the slash separator (mm/dd/yy) or rest of the world order using the dot or dash separator (dd.mm.yy or dd-mm-yy). If there is any chance of input confusing the function, it must be resolved before calling it.

    To convert back, use date(). The returned date string can be in almost any format you can imagine. See the documentation for details.

  8. RyAnaon
    Member
    Posted 3 months ago #

    Thx again for your time and sorry for the delay with my answer.

    I can't make this works like I want and for the moment, I can't waste my time!

    I'll let everything like that and come back later, when I could.

    I have other problems now, I'll do another post.

    Thank you again!

Reply

You must log in to post.

About this Topic