DevinVinson / WordPress-Plugin-Boilerplate

[WordPress] A foundation for WordPress Plugin Development that aims to provide a clear and consistent guide for building your plugins.
http://wppb.io
7.67k stars 2.25k forks source link

Custom post type registration, with_front, and error 404 #313

Open grantpalin opened 9 years ago

grantpalin commented 9 years ago

I'm using the boilerplate to implement a custom plugin for my own use. I've added code to register one custom post type and one custom taxonomy. I use a custom permalink structure for my posts, which my custom post type by default appears under. It works here - an instance does appear as expected when viewed from the front-end. To get around the permalink base, I tried adding with_front => false to the rewrite array; when I do this, there is no apparent error, but the same CPT entry generates a 404 error when viewed under the now-unprefixed permalink. Oddly, I have no issue with viewing the custom taxonomy archive. Also, the CPT archive listing does work - it's just the single view that does not.

I've added below the relevant code blocks.

In the activator class:

public static function activate() {
    require dirname(__FILE__) . 'taxonomies/class-projecting-tax.php';
    $tax = new Projecting_Tax();
    $tax->register_all();

    require dirname(__FILE__) . 'post_types/class-projecting-cpt.php';
    $cpt = new Projecting_CPT();
    $cpt->register_all();

    // flush rewrite rules for custom post types and taxonomies
    flush_rewrite_rules();
}

In the orchestration class:

private function define_admin_hooks() {
    // snip

    $tax = new Projecting_Tax();
    $this->loader->add_action( 'init', $tax , 'register_all' );

    $post_types = new Projecting_CPT();
    $this->loader->add_action( 'init', $post_types , 'register_all' );
}

In the CPT orchestration class:

public function register_all()
{
    require_once 'class-projecting-cpt-project.php';
    $cpt = new Projecting_CPT_Project();
    $cpt->register();
}

And in the CPT registration class:

function register() {
    $args = array(
        'label'               => __( 'project', 'projecting' ),
        'description'         => __( 'Projects!', 'projecting' ),
        'labels'              => array(
            'name'                => _x( 'Projects', 'Post Type General Name', 'projecting' ),
            'singular_name'       => _x( 'Project', 'Post Type Singular Name', 'projecting' ),
            // snip
        ),
        'supports'            => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'trackbacks', 'revisions', 'custom-fields', 'page-attributes', ),
        'taxonomies'          => array( 'project_type' ),
        'hierarchical'        => false,
        'public'              => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'menu_position'       => 20,
        'menu_icon'           => 'dashicons-portfolio',
        'show_in_admin_bar'   => true,
        'show_in_nav_menus'   => true,
        'can_export'          => true,
        'has_archive'         => 'projects', //archive slug
        'exclude_from_search' => false,
        'publicly_queryable'  => true,
        'rewrite'             => array(
            'slug'                => 'projects',
            'with_front'          => false, // doesn't work, CPT instance 404s
        ),
        'capability_type'     => 'page',
    );

    register_post_type( 'project', $args );
}

Apologies for all the code blocks, they seem the relevant ones to include. I'm still figuring out the boilerplate, it does seem to take some coordination effort to correctly register custom types/taxonomies.

Again, the CPT views correctly when with_front is left off or set to true, yet the same, with the updated permalink, 404s out when with_front is set to false.

http://.../blog/projects/projectname/ - OK http://.../projects/projectname/ -> 404 error

I could possibly live with updating my base custom permalink for posts (this artifact of the blog-only days is a nuisance at times) since I was thinking to do it anyway, but I'd like to know if there's a reason why the otherwise functional settings do not work here.

DevinVinson commented 9 years ago

Do you have the full project somewhere that I can poke around?

grantpalin commented 9 years ago

Yes, here's the repo: https://bitbucket.org/grantpalin/wp-plugin-projecting

scrchhrpn commented 8 years ago

I have same problem too. Actually, where is the best place or file in boilerplate to put function of register post type, calling that function from activate, flush_rewrite_rules and then add_action it? I have tried with the static function that regist cpt, and put it in class-plugin-name-admin, and everthing fine without 404. but i want to avoid static function to do that. Can you give the example how to put CPT and flush_rewrite_rules in a good way please? Thanks.

HenriqueSilverio commented 8 years ago

What I have doing in one of my plugins, is following the tips given by this blog post.

Let's assume that I am creating a plugin to manage library books. So what I do is:

1. Activator: In Plugin_Name_Activator::activate I check and create a flag, like this:

if( ! get_option( 'prefix_do_flush_rewrite' ) ) {

    add_option( 'prefix_do_flush_rewrite', true );

}

2. Admin Class: Then in Plugin_Name_Admin class, I create a method like this:

public function maybe_flush_rewrite_rules() {

    if( get_option( 'prefix_do_flush_rewrite' ) ) {

        flush_rewrite_rules();
        delete_option( 'prefix_do_flush_rewrite' );

    }

}

3. Main Class: Finally, to bring the blocks together, in Plugin_Name::define_admin_hooks instantiate the classes and register the hooks with appropriate priorities.

$plugin_admin = new Plugin_Name_Admin( $this->get_plugin_name(), $this->get_version() );
$books_manager = new Plugin_Name_Books( $this->get_plugin_name(), $this->get_version() );

$this->loader->add_action( 'init', $plugin_admin, 'maybe_flush_rewrite_rules', 20 );
$this->loader->add_action( 'init', $books_manager, 'setup_post_type', 10 );

The Plugin_Name_Books::setup_post_type method is where I call the WordPress register_post_type function.

Hope to help.