I’m writing a plugin that creates a custom post type named “my_plugin_lesson”:
$args = array (
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'lessons', 'with_front' => false)
);
register_post_type ('my_plugin_lesson', $args);
The custom post type has an archive, and the URL of the archive is:
http://example.com/lessons
I want to customize the look of this archive; I want to list the posts in a table format, rather than the standard WordPress blog post archive. I understand that a custom archive template could be created in the theme by making the archive-my_plugin_lesson.php
file; however, I would like the plugin to work with any theme.
How can I alter the content of the archive page without adding or modifying theme files?
Edit:
I understand that I could use the archive_template
filter hook. However, all this does is replace the theme template, which still needs to be theme-specific. For example, just about every theme template will need the get_header
, get_sidebar
, and get_footer
functions, but what should the id of the content <div>
be? This is different in every theme.
What I would like to do is to replace the content itself with my own content, and use that in place of the archive page for my custom post type.
What you need is hooking
template_include
filter and selectively load your template inside plugin.As a good practice, if you plan to distribute your plugin, you should check if
archive-my_plugin_lesson.php
(or maybemyplugin/archive-lesson.php
) exists in theme, if not use the plugin version.In this way is easy for users replace the template via theme (or child theme) without edit the plugin code.
This is the method used by popular plugins, e.g. WooCommmerce, just to say one name.
More info on Codex for
You can use the
archive_template
hook to process the content of a theme’s archive template, by using the scheme below, but obviously you’ll only ever be able to process a fraction of the themes out there, given that a template can basically contain any old thing.The scheme is to load the template into a string (
$tpl_str
) in thearchive_template
filter, substitute your content, include the string (using the trickeval( '?>' . $tpl_str );
), and then return a blank file so that theinclude
in “wp-includes/template-loader.php” becomes a no-op.Below is a hacked version of code I use in a plugin, which targets “classic” templates that use
get_template_part
and is more concerned with processing single templates than archive, but should help you get started. The setup is that the plugin has a subdirectory called “templates” which holds a blank file (“null.php”) and content templates (eg “content-single-posttype1.php”, “content-archive-postype1.php”) as well as a fall back template “single.php” for the single case, and utilizes a custom version ofget_template_part
that looks in this directory.The custom
get_template_part
:For completeness here’s the fall back “single.php”, that uses the custom
get_template_part
:I’ve been pondering the same question, and this is the hypothetical solution I’ve come up with:
the way you desire.
option.
Upon plugin activation create a page using wp_insert_post with the name being the post type and the content being the shortcode.
You can provide options in the shortcode for additional style considerations, or add classes to the post container to match theme specific or custom styles. The user can also add additional content before/after the loop by editing the page.
You can use the filter
single_template
. A basic example taken from the Codex: