dynamicinternet Webdesign

Das Blog

Themen, Tutorials sowie Tipps & Tricks über Webdesign, (X)HTML und CSS, Programmierung, WordPress und was uns sonst noch bewegt.

RSS abonnieren

WordPress 2.8 Single Post Navigation Widget

Seit WordPress 2.8 gibt es eine neue Widget API. Im Beitrag WordPress 2.8 Widget erstellen habe ich an einem einfachen Beipiel beschrieben, wie man ein Widget programmiert. Dieser Beitrag ist auch auf WP Engineer erschienen und ist dort einer der erfolgreichsten Artikel. Diesmal habe ich mir etwas komplexeres ausgedacht und zusammen mit Heiko gebaut.

Es handelt sich um ein Post Navigation Widget, welches in der Artikel-Einzelansicht (single.php) die x nächsten Beiträge vor und x nächsten Beiträge nach dem aufgerufenen Artikel listet. Ich finde, das ist eine schöne Möglichkeit, auch ältere Beiträge in der Sidebar erscheinen zu lassen. Hier mal ein Screenshot, links vom Backend, rechts vom der Sidebar:

WordPress 2.8 Post Navigation Widget

Nun zum Code. Um die Klasse WPE_Widget_Post_Navigation habe ich aus Sicherheitsgründen abgefragt, ob die Klasse WP_Widget überhaupt existiert, damit es bei WordPress Versionen unter 2.8 nicht zu Fehlermeldungen kommt.

if (class_exists('WP_Widget')) {
    class WPE_Widget_Post_Navigation extends WP_Widget {
 
        function WPE_Widget_Post_Navigation() {
            $widget_ops = array('classname' => 'wpe_widget_post_navi', 'description' => __( "Some posts before and after the current post") );
            $this->WP_Widget('wpe-post-navi', __('WPE Single Post Navigation'), $widget_ops);
        }
 
        function widget($args, $instance) {
            if(is_single()) {
                global $post, $wpdb;
                extract($args);
 
                if ( !$number = (int) $instance['number'] )
                    $number = 5;
                elseif( $number < 1 )
                    $number = 1;
                elseif( $number > 10 )
                    $number = 10;
 
                $title_before 		= apply_filters('widget_title', empty($instance['title_before']) ? 'Posts before' : $instance['title_before']);
                $title_after	 	= apply_filters('widget_title', empty($instance['title_after']) ? 'Posts after' : $instance['title_after']);
                $before_widget_2	= preg_replace("/(wpe\-post\-navi-\d+)/", "$1-1", $before_widget);
 
                $querystr = "
                    SELECT *
                    FROM $wpdb->posts wposts
                    WHERE wposts.ID != $post->ID
                    AND wposts.post_type = 'post'
                    AND wposts.post_status = 'publish'
                    AND wposts.post_date %s '$post->post_date'
                    ORDER BY wposts.post_date %s
                    LIMIT $number
                 ";
 
                $leading_posts = $wpdb->get_results(sprintf($querystr, '<', 'DESC'), OBJECT);
                $trailing_posts = $wpdb->get_results(sprintf($querystr, '>', 'ASC'), OBJECT);
 
                if ($trailing_posts && count($trailing_posts)) {
                    echo $before_widget_2 . $before_title . $title_before . $after_title . "<ul>";
                    $trailing_posts = array_reverse($trailing_posts);
                    foreach ($trailing_posts as $post) {
                        setup_postdata($post);
                        ?> <li><a href="<?php the_permalink() ?>" title="<?php echo esc_attr(get_the_title() ? get_the_title() : get_the_ID()); ?>"><?php if ( get_the_title() ) the_title(); else the_ID(); ?> </a></li><?php
                    }
                    echo "</ul>" . $after_widget;
                }
 
                if ($leading_posts && count($leading_posts)) {
                    echo $before_widget . $before_title . $title_after . $after_title . "<ul>";
                    foreach ($leading_posts as $post) {
                        setup_postdata($post);
                        ?> <li><a href="<?php the_permalink() ?>" title="<?php echo esc_attr(get_the_title() ? get_the_title() : get_the_ID()); ?>"><?php if ( get_the_title() ) the_title(); else the_ID(); ?> </a></li><?php
                    }
                    echo "</ul>" . $after_widget;
                }
                wp_reset_query();
            }
        }
 
        function update( $new_instance, $old_instance ) {
            $instance = $old_instance;
            $instance['title_before'] = strip_tags($new_instance['title_before']);
            $instance['number'] = (int) $new_instance['number'];
            $instance['title_after'] = strip_tags($new_instance['title_after']);
 
            return $instance;
        }
        function form( $instance ) {
            $title_before = ($instance['title_before'] == '') ? 'Posts before' : esc_attr($instance['title_before']);
            $title_after = ($instance['title_after'] == '') ? 'Posts after' : esc_attr($instance['title_after']);
            if ( !$number = (int) $instance['number'] )
                $number = 5;
            elseif ( $number < 1 )
                $number = 1;
            elseif ( $number > 10 )
                $number = 10;
    ?>
            <p><label for="<?php echo $this->get_field_id('title_before'); ?>">Title before:</label>
            <input class="widefat" id="<?php echo $this->get_field_id('title_before'); ?>" name="<?php echo $this->get_field_name('title_before'); ?>" type="text" value="<?php echo $title_before; ?>" /></p>
            <p><label for="<?php echo $this->get_field_id('title_after'); ?>">Title after:</label>
            <input class="widefat" id="<?php echo $this->get_field_id('title_after'); ?>" name="<?php echo $this->get_field_name('title_after'); ?>" type="text" value="<?php echo $title_after; ?>" /></p>
            <p><label for="<?php echo $this->get_field_id('number'); ?>">Number of posts to show before and after current post:</label>
            <input id="<?php echo $this->get_field_id('number'); ?>" name="<?php echo $this->get_field_name('number'); ?>" type="text" value="<?php echo $number; ?>" size="3" /><br />
            <small>(at most 10)</small></p>
    <?php
        }
    }
    register_widget('WPE_Widget_Post_Navigation');
}

Das sollte soweit eigentlich selbsterklärend sein. Nun zur Funktion widget(), die die eigentliche Arbeit verrichtet. Hier mußten wir ein bischen tricksen, weil das Widget eigentlich 2 Widgets untereinander baut, die dann die gleiche id bekommen hätten. Das wäre nicht valide, darum hängt der Code ein -1 an eins der Widgetelemente:

$before_widget_2 = preg_replace("/(wpe\-post\-navi-\d+)/", "$1-1", $before_widget);

Dann werden 2 Queries ausgeführt. Eins für die Post vor dem Beitrag und eins für die Posts nach dem Beitrag. Danach erfolgt die Ausgabe, falls Posts vorhanden sind.

Den Code könnt ihr hier als zip downloaden. Danach entpacken und den Code in eure functions.php kopieren und bitte beachten, das Widget ist für WordPress 2.8.

13 Kommentare
  1. Jared sagt:

    Danke dir Michael. Sehr coole Idee – es freut mich das du sowas mit deinen Lesern teilst.

  2. Micha sagt:

    Nix zu danken ;)

    Hab den Code mal hier eingebaut.

  3. Hallo,
    die Idee des Widgets finde ich sehr gut, habe ich bei mir auch gleich eingebaut, allerdings muss noch ein bisschen gebastelt werden, mit der Formatierung komme ich noch nicht ganz klar.

    Wie kann man denn, wie hier 4 davor und 5 danach einstellen?
    Ich dachte dies ist eine gemeinsame Einstellung …

    So und nun werd ich hier mal weiter stöbern, denn hier scheint es noch einiges zu geben :)

    Grüße Victor

  4. Micha sagt:

    @zauberer: Die Anzahl gilt für Beides, davor und danach. Sollten zB. davor nur 2 Beiträge vorhanden sein, werden nur 2 angezeigt. Ansonsten immer die Anzahl, die du eingestellt hast.

  5. ah danke, sieht hier heute ja auch schon anders aus, gestern stand da noch eine 4 und 5 – confused :)

    Und ab jetzt habt ihr auch einen Feedleser mehr … mal sehen was ich noch so für Tipps finde.

    Auf jeden Fall ein großes DANKE für das Widget.

    V.

  6. Hallo Micha, das widget funktioniert bestens, ich habe allerdings versucht die Überschrift anzupassen in der function.php:


    'before_widget' => '',
    'after_widget' => '',
    'before_title' => '',
    'after_title' => '',

    doch leider bekomme ich immer noch so ein Listsymbol davor angezeigt, was muss ich denn da ändern?
    Vielleicht kannst du mir noch einen Tipp geben.

    Danke Victor

  7. Micha sagt:

    @zauberer: schreib mal in dein Stylesheet

    .#sidebar li { list-style-type: none; }, dann sind die Punkte von der Überschrift weg.

  8. danke, ist geändert und funktioniert. Ich bewundere ja euch Programmierer, dies ist für mich auch Zauberei :)

  9. Micha sagt:

    @zauberer

    Programmierung ist genauso wenig Zauberei wie deine Zauberei Zauberei ist. Geiler Satz, oder?

    Ich habe einen Freund, Ralph Kunze, der ist auch Magier wie du. Sein Können fasziniert mich sehr.

  10. Das kann ich natürlich nicht so stehen lassen:) Programmierung ist vielleicht keine Zauberei, doch meine Zauberei ist Zauberkunst, was natürlich ein Programmierer nie eingestehen kann, denn in einer Welt aus logischen Verknüpfungen, die sich ja “nur aus Nullen und Einsen” zusammensetzt und bis auf´s letzte Semikolin zu erklären ist, fällt es natürlich schwer zu sagen: “Ich weiss es nicht”. (Dies gilt übrigends auch für Lehrer, die müssen ja alles wissen :)

    Aber in einer Zaubershow gibt es eine Vielzahl von nicht erklärbaren Dingen. Natürlich lebt die Zauberkunst nicht nur vom Trick allein und ich denke Ralph (Zauberschloß lässt grüßen) wird mir da zustimmen, das Entertainment, der Aufbau um das Kunststück und das Publikum herum, das ist doch das was es letztendlich mit ausmacht … aber genug Zauberei, ich wollte ja mit meiner vorigen Antwort mal auf andere Art und Weise sagen, das ich die Arbeit eben sehr bewunder und es für mich Zauberei ist hier zu sitzen, etwas in meine Tastatur ein zu geben und es im Internet auf irgendeiner Seite sofort zu sehen …
    puh, nun brauch ich aber was zu trinken! NOch einen schönen Abend und auf diesem Wege auch einen Gruß an Ralph und das im nächsten Jahr so einige Projekte gelingen werden :)

    V.

  11. Kolibria sagt:

    Hey,

    Vielen lieben Dank,
    für dieses echt nützliche Widget.

    Ich würde allerdings gerne nur Posts aus der aktuellen Kategorie auflisten, hast du dafür vielleicht einen Tip für mich?

    lg Kolibria

  12. Micha sagt:

    Das Query müßte erweitert werden. Das ist ber nicht in 5 Minuten gemacht.

  13. Kolibria sagt:

    hey,

    danke für den Hinweis.

    Ich hab nun versucht die Query zu erweitern, erstmal nur mit einem standard – Wert:

    $querystr = "
    SELECT *
    FROM $wpdb->posts wposts, $wpdb->terms wterms
    WHERE wposts.ID != $post->ID
    AND wposts.post_type = 'post'
    AND wposts.post_status = 'publish'
    AND wterms.term_id = '10'
    AND wposts.post_date %s '$post->post_date'
    ORDER BY wposts.post_date %s
    LIMIT $number
    ";

    Weist du in welcher Tabelle (Feld) die Kat. gespeichert wird, oder ist das gar nicht so einfach aufgelistet?

    lg und danke nochmals
    Kolibria

Einen Kommentar schreiben