Cum să creezi o pagină de arhivă personalizată pentru un post type custom într-un plugin WordPress

27 sept. 2013, 22:04:49
Vizualizări: 18.3K
Voturi: 16

Scriu un plugin care creează un post type custom numit "my_plugin_lesson":

$args = array (
    'public' => true,
    'has_archive' => true,
    'rewrite' => array('slug' => 'lessons', 'with_front' => false)
);
register_post_type ('my_plugin_lesson', $args);

Post type-ul custom are o arhivă, iar URL-ul arhivei este:

http://example.com/lessons

Doresc să personalizez aspectul acestei arhive; vreau să afișez postările într-un format tabelar, în locul arhivei standard WordPress. Înțeleg că se poate crea un șablon personalizat în temă prin fișierul archive-my_plugin_lesson.php; totuși, aș dori ca plugin-ul să funcționeze cu orice temă.

Cum pot modifica conținutul paginii de arhivă fără a adăuga sau modifica fișierele temei?

Edit: Înțeleg că pot folosi hook-ul archive_template. Totuși, acesta doar înlocuiește șablonul temei, care în continuare trebuie să fie specific temei. De exemplu, aproape orice șablon de temă va avea nevoie de funcțiile get_header, get_sidebar și get_footer, dar care ar trebui să fie id-ul div-ului de conținut? Acesta diferă în fiecare temă.

Ceea ce aș dori să fac este să înlocuiesc conținutul în sine cu propriul meu conținut și să-l folosesc în locul paginii de arhivă pentru post type-ul meu custom.

0
Toate răspunsurile la întrebare 4
1
17

Ceea ce aveți nevoie este să utilizați filtrul template_include și să încărcați selectiv șablonul din interiorul plugin-ului.

Ca o bună practică, dacă intenționați să distribuiți plugin-ul, ar trebui să verificați dacă archive-my_plugin_lesson.php (sau poate myplugin/archive-lesson.php) există în tema, iar dacă nu, să folosiți versiunea din plugin.

În acest fel, utilizatorii pot înlocui cu ușurință șablonul prin intermediul temei (sau a temei copil) fără a modifica codul plugin-ului.

Aceasta este metoda folosită de plugin-uri populare, de exemplu WooCommerce, doar ca să menționăm un nume.

add_filter('template_include', 'lessons_template');

function lessons_template( $template ) {
  if ( is_post_type_archive('my_plugin_lesson') ) {
    $theme_files = array('archive-my_plugin_lesson.php', 'myplugin/archive-lesson.php');
    $exists_in_theme = locate_template($theme_files, false);
    if ( $exists_in_theme != '' ) {
      return $exists_in_theme;
    } else {
      return plugin_dir_path(__FILE__) . 'archive-lesson.php';
    }
  }
  return $template;
}

Mai multe informații în Codex pentru

28 sept. 2013 14:38:19
Comentarii

Acest lucru înlocuiește doar fișierul șablon al temei, nu? Ce ar trebui să pun în fișierul archive-lesson.php al pluginului meu? Ar trebui să fie diferit pentru a funcționa cu fiecare temă. Chiar și temele implicite "Twenty" nu sunt de acord asupra div-urilor/secțiunilor de container care înconjoară conținutul.

Ben Miller Ben Miller
29 sept. 2013 07:35:37
0

Puteți folosi hook-ul archive_template pentru a procesa conținutul unui șablon de arhivă al temei, folosind schema de mai jos, dar evident veți putea procesa doar o fracțiune din temele existente, având în vedere că un șablon poate conține orice.

Schema constă în încărcarea șablonului într-un string ($tpl_str) în cadrul filtrului archive_template, înlocuirea conținutului dumneavoastră, includerea string-ului (folosind trucul eval( '?>' . $tpl_str );), și returnarea unui fișier gol astfel încât include-ul din "wp-includes/template-loader.php" să devină un no-op.

Mai jos este o versiune modificată a codului pe care îl folosesc într-un plugin, care se adresează șabloanelor "clasice" ce folosesc get_template_part și este mai preocupat de procesarea șabloanelor individuale decât de cele de arhivă, dar vă poate ajuta să începeți. Configurația este următoarea: plugin-ul are un subdirector numit "templates" care conține un fișier gol ("null.php") și șabloane de conținut (de ex. "content-single-posttype1.php", "content-archive-postype1.php"), precum și un șablon de rezervă "single.php" pentru cazurile individuale, și utilizează o versiune personalizată a get_template_part care caută în acest director.

define( 'MYPLUGIN_FOLDER', dirname( __FILE__ ) . '/' );
define( 'MYPLUGIN_BASENAME', basename( MYPLUGIN_FOLDER ) );

add_filter( 'single_template', 'myplugin_single_template' );
add_filter( 'archive_template', 'myplugin_archive_template' );

function myplugin_single_template( $template ) {
    static $using_null = array();

    // Ajustați cu tipurile dumneavoastră de postări personalizate.
    $post_types = array( 'posttype1', );

    if ( is_single() || is_archive() ) {
        $template_basename = basename( $template );
        // Această verificare poate fi eliminată.
        if ( $template == '' || substr( $template_basename, 0, 4 ) == 'sing' || substr( $template_basename, 0, 4 ) == 'arch' ) {
            $post_type = get_post_type();
            $slug = is_archive() ? 'archive' : 'single';
            if ( in_array( $post_type, $post_types ) ) {
                // Permiteți utilizatorului să suprascrie.
                if ( $single_template = myplugin_get_template( $slug, $post_type ) ) {
                    $template = $single_template;
                } else {
                    // Dacă nu ați trecut prin toate acestea înainte...
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        if ( $template && ( $content_template = myplugin_get_template( 'content-' . $slug, $post_type ) ) ) {
                            $tpl_str = file_get_contents( $template );
                            // Va trebui să ajustați aceste regex-uri pentru cazul dumneavoastră - mult noroc!
                            if ( preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*,\s*get_post_format\s*\(\s*\)\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'content\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE )
                            || preg_match( '/get_template_part\s*\(\s*\'[^\']+\'\s*,\s*\'' . $slug . '\'\s*\)/', $tpl_str, $matches, PREG_OFFSET_CAPTURE ) ) {
                                $using_null[$slug][$post_type] = true;
                                $tpl_str = substr( $tpl_str, 0, $matches[0][1] ) . 'include \'' . $content_template . '\'' . substr( $tpl_str, $matches[0][1] + strlen( $matches[0][0] ) );
                                // Acest truc include $tpl_str.
                                eval( '?>' . $tpl_str );
                            }
                        }
                    }
                    if ( empty( $using_null[$slug][$post_type] ) ) {
                        // Nu s-a putut analiza - căutați șablonul de rezervă.
                        if ( file_exists( MYPLUGIN_FOLDER . 'templates/' . $slug . '.php' ) ) {
                            $template = MYPLUGIN_FOLDER . 'templates/' . $slug . '.php';
                        }
                    } else {
                        // Succes! "null.php" este doar un fișier gol cu zero biți.
                        $template = MYPLUGIN_FOLDER . 'templates/null.php';
                    }
                }
            }
        }
    }
    return $template;
}

function myplugin_archive_template( $template ) {
    return myplugin_single_template( $template );
}

Versiunea personalizată a get_template_part:

/*
 * Versiunea WP get_template_part() care caută în tema, apoi în tema părinte, și în final în directorul de șabloane al plugin-ului (subdirectorul "templates").
 * De asemenea, caută inițial în subdirectorul "myplugin" dacă există în directoarele temei și temei părinte, astfel încât șabloanele plugin-ului să poată fi păstrate separate.
 */
function myplugin_get_template( $slug, $part = '' ) {
    $template = $slug . ( $part ? '-' . $part : '' ) . '.php';

    $dirs = array();

    if ( is_child_theme() ) {
        $child_dir = get_stylesheet_directory() . '/';
        $dirs[] = $child_dir . MYPLUGIN_BASENAME . '/';
        $dirs[] = $child_dir;
    }

    $template_dir = get_template_directory() . '/';
    $dirs[] = $template_dir . MYPLUGIN_BASENAME . '/';
    $dirs[] = $template_dir;
    $dirs[] = MYPLUGIN_FOLDER . 'templates/';

    foreach ( $dirs as $dir ) {
        if ( file_exists( $dir . $template ) ) {
            return $dir . $template;
        }
    }
    return false;
}

Pentru completitudine, iată șablonul de rezervă "single.php", care folosește versiunea personalizată a get_template_part:

<?php
get_header(); ?>

    <div id="primary" class="content-area">
        <div id="content" class="clearfix">
            <?php while ( have_posts() ) : the_post(); ?>

            <?php if ( $template = myplugin_get_template( 'content-single', get_post_type() ) ) include $template; else get_template_part( 'content', 'single' ); ?>

                <?php
                    // Dacă comentariile sunt deschise sau avem cel puțin un comentariu, încărcăm șablonul de comentarii
                    if ( comments_open() || '0' != get_comments_number() ) :
                        comments_template();
                    endif;
                ?>

            <?php endwhile; ?>

        </div><!-- #content -->
    </div><!-- #primary -->

<?php get_sidebar(); ?>
<?php get_footer(); ?>
11 sept. 2014 19:35:11
2

M-am tot gândit la aceeași întrebare, și iată soluția ipotetică la care am ajuns:

  • În cadrul plugin-ului, creează un shortcode care afișează bucla de arhivă așa cum dorești.
  • Când creezi tipul de postare personalizată, nu activa opțiunea 'archive'.
  • Adaugă o foaie de stiluri care controlează toate stilurile conținutului buclei tale.

La activarea plugin-ului, creează o pagină folosind wp_insert_post cu numele fiind tipul de postare și conținutul fiind shortcode-ul.

Poți oferi opțiuni în shortcode pentru considerații suplimentare de stil, sau poți adăuga clase containerului de postare pentru a se potrivi cu stilurile specifice temei sau stilurilor personalizate. Utilizatorul poate adăuga și conținut suplimentar înainte/după buclă prin editarea paginii.

30 mai 2015 22:32:43
Comentarii

Deși nu sunt cel care a postat inițial, căutam o soluție la aceeași problemă. Am urmat soluția ta ipotetică și acum pot confirma că funcționează și în practică.

Lucio Crusca Lucio Crusca
6 ian. 2016 16:21:01

Hei, grozav! Mă bucur că a fost util pentru cineva. Uitasem complet de asta.

SkyShab SkyShab
6 ian. 2016 17:50:20
1

Puteți utiliza filtrul single_template. Un exemplu de bază preluat din Codex:

function get_custom_post_type_template($single_template) {
     global $post;

     if ($post->post_type == 'my_post_type') {
          $single_template = dirname( __FILE__ ) . '/post-type-template.php';
     }
     return $single_template;
}

add_filter( "single_template", "get_custom_post_type_template" );
27 sept. 2013 22:18:41
Comentarii

Cred că hook-ul de filtru pentru un șablon de arhivă este archive_template, dar nu cred că va funcționa pentru ceea ce încerc să fac. Am editat întrebarea mea cu mai multe informații.

Ben Miller Ben Miller
28 sept. 2013 07:49:09