WooCommerce: Assigning an endpoint to a custom template in my account pages

29,539

Solution 1

Finally I could solve the problem using a snippet provided for the same people of WooCommerce (There are more tips in that page). For anyone interested, paste all the following code in functions.php:

function my_custom_endpoints() {
    add_rewrite_endpoint( 'special-page', EP_ROOT | EP_PAGES );
}

add_action( 'init', 'my_custom_endpoints' );

function my_custom_query_vars( $vars ) {
    $vars[] = 'special-page';

    return $vars;
}

add_filter( 'query_vars', 'my_custom_query_vars', 0 );

function my_custom_flush_rewrite_rules() {
    flush_rewrite_rules();
}

add_action( 'wp_loaded', 'my_custom_flush_rewrite_rules' );

I think this way allows more control to order/renaming the menu:

function my_custom_my_account_menu_items( $items ) {
    $items = array(
        'dashboard'         => __( 'Dashboard', 'woocommerce' ),
        'orders'            => __( 'Orders', 'woocommerce' ),
        //'downloads'       => __( 'Downloads', 'woocommerce' ),
        //'edit-address'    => __( 'Addresses', 'woocommerce' ),
        //'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
        'edit-account'      => __( 'Edit Account', 'woocommerce' ),
        'special-page'      => 'Special Page',
        'customer-logout'   => __( 'Logout', 'woocommerce' ),
    );

    return $items;
}

add_filter( 'woocommerce_account_menu_items', 'my_custom_my_account_menu_items' );

In the following function I included the file to maintain some "order", but it also admits direct code.

Be sure to place the special-page.php file in the myaccount folder.

function my_custom_endpoint_content() {
    include 'woocommerce/myaccount/special-page.php'; 
}

add_action( 'woocommerce_account_special-page_endpoint', 'my_custom_endpoint_content' );

Important: Once did this, go to Dashboard > Settings > Permalinks and click "Save Settings" in order to flush rewrite rules (thanks @optimiertes)

Source: Tabbed My Account page

Solution 2

First my-account/special-page/ should be myaccount/special-page/ in woocommerce 2.6+.

This solution is Incomplete and I am still working On…

You can use first this hook:

add_action( 'init', 'add_wc_endpoint' );
function add_wc_endpoint(){
    add_rewrite_endpoint( 'special-page', EP_ROOT | EP_PAGES );
}

Then filtering wc_get_templateto call your files when the request match your endpoint:

add_filter( 'wc_get_template', 'custom_vc_endpoint', 10, 5 );
function custom_vc_endpoint($located, $template_name, $args, $template_path, $default_path){

    if( $template_name == 'myaccount/special-page.php' ){
        global $wp_query;
        if(isset($wp_query->query['special-page'])){
            $located = get_template_directory() . '/woocommerce/myaccount/special-page.php';
        }
    }

    return $located;
}

If you use a child theme, replace get_template_directory() by get_stylesheet_directory()… Paste this code in function.php file of your active child theme or theme.

To avoid a 404 error "page not found", you will need to refresh rewrite rules adding to your code:

flush_rewrite_rules();

Update: Finally Dario (the OP) found a working solution. Look at his answer.

References:

Solution 3

There is a better way to use a template in your custom page in woocommerce:

function my_custom_endpoint_content() {
    wc_get_template( 'myaccount/special-page.php' ); 
}

add_action( 'woocommerce_account_special-page_endpoint', 'my_custom_endpoint_content' );

this should work without using the wc_get_template filter.

Solution 4

You can add this code to your theme's function.php:

class My_Custom_My_Account_Endpoint {
/**
 * Custom endpoint name.
 *
 * @var string
 */
public static $endpoint = 'special-page';
/**
 * Plugin actions.
 */
public function __construct() {
    // Actions used to insert a new endpoint in the WordPress.
    add_action( 'init', array( $this, 'add_endpoints' ) );
    add_filter( 'query_vars', array( $this, 'add_query_vars' ), 0 );
    // Change the My Accout page title.
    add_filter( 'the_title', array( $this, 'endpoint_title' ) );
    // Insering your new tab/page into the My Account page.
    add_filter( 'woocommerce_account_menu_items', array( $this, 'new_menu_items' ) );
    add_action( 'woocommerce_account_' . self::$endpoint .  '_endpoint', array( $this, 'endpoint_content' ) );
}
/**
 * Register new endpoint to use inside My Account page.
 *
 * @see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
 */
public function add_endpoints() {
    add_rewrite_endpoint( self::$endpoint, EP_ROOT | EP_PAGES );
}
/**
 * Add new query var.
 *
 * @param array $vars
 * @return array
 */
public function add_query_vars( $vars ) {
    $vars[] = self::$endpoint;
    return $vars;
}
/**
 * Set endpoint title.
 *
 * @param string $title
 * @return string
 */
public function endpoint_title( $title ) {
    global $wp_query;
    $is_endpoint = isset( $wp_query->query_vars[ self::$endpoint ] );
    if ( $is_endpoint && ! is_admin() && is_main_query() && in_the_loop() && is_account_page() ) {
        // New page title.
        $title = __( 'Special Page', 'woocommerce' );
        remove_filter( 'the_title', array( $this, 'endpoint_title' ) );
    }
    return $title;
}
/**
 * Insert the new endpoint into the My Account menu.
 *
 * @param array $items
 * @return array
 */
public function new_menu_items( $items ) {
    // Remove the logout menu item.
    $logout = $items['customer-logout'];
    unset( $items['customer-logout'] );
    // Insert your custom endpoint.
    $items[ self::$endpoint ] = __( 'Special Page', 'woocommerce' );
    // Insert back the logout item.
    $items['customer-logout'] = $logout;
    return $items;
}
/**
 * Endpoint HTML content.
 */
public function endpoint_content() {
    include('woocommerce/myaccount/special-page.php');
}
/**
 * Plugin install action.
 * Flush rewrite rules to make our custom endpoint available.
 */
public static function install() {
    flush_rewrite_rules();
}
}
new My_Custom_My_Account_Endpoint();
// Flush rewrite rules on plugin activation.
register_activation_hook( __FILE__, array( 'My_Custom_My_Account_Endpoint', 'install' ) );

If you don't know where is your theme's function.php:

1.Log in to the WordPress Admin interface
2.In the left sidebar, hover over Appearances, then click Theme Editor
3.In the right sidebar, click functions.php

Share:
29,539
Dario Ferrer
Author by

Dario Ferrer

Updated on July 09, 2022

Comments

  • Dario Ferrer
    Dario Ferrer almost 2 years

    This function adds a tab named "Special Page" into "My Account" tab list:

    add_filter( 'woocommerce_account_menu_items' , 'jc_menu_panel_nav' );
    
    function jc_menu_panel_nav() {
        $items = array(
            'dashboard'       => __( 'Dashboard', 'woocommerce' ),
            'orders'          => __( 'Orders', 'woocommerce' ),
            'downloads'       => __( 'Downloads', 'woocommerce' ),
            'edit-address'    => __( 'Addresses', 'woocommerce' ),
            'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
            'edit-account'    => __( 'Account Details', 'woocommerce' ),
            'special-page' => __( 'Special Page', 'woocommerce' ), // My custom tab here
            'customer-logout' => __( 'Logout', 'woocommerce' ),
        );
    
        return $items;
    }
    

    That results in this:

    enter image description here

    But the link points to my-account/special-page/, and naturally gives a 404 error.

    How I can assign this URL to a file named special-page.php?

  • Admin
    Admin almost 8 years
    worked only in localhost, now am testing this online and the clients is forcing me to get this to work today !
  • WebArtisan
    WebArtisan over 7 years
    thx for solution. Tip: Change "after_switch_theme" hook to any other headers hook "wp_loaded" - for example. And It will works without swithing themes.
  • optimiertes
    optimiertes about 7 years
    Go to Dashboard > Settings > Permalinks and click "Save Settings" might be easier for flushing the rewrite rules.
  • Akash Agrawal
    Akash Agrawal about 6 years
    Hi. I did the same as in the above solution, but I'm getting a page not found 404 error. Is there anything that needs to be updated in wordpress 4?
  • Akash Agrawal
    Akash Agrawal about 6 years
    Flushing rewrite rules from Permalinks page didn't help. Though adding flush_rewrite_rules(); in the code did the trick. Thanks for you suggestion
  • LoicTheAztec
    LoicTheAztec about 6 years
    @AkashAgrawal Ok I have added this at the end of this answer. Thanks
  • Akash Agrawal
    Akash Agrawal about 6 years
    This is a my-account endpoint and my-account tab/pages and other tabs along with it are secured. The user has to login to access these pages, is there any procedure by which I can access my custom endpoint without login?
  • LoicTheAztec
    LoicTheAztec about 6 years
    @AkashAgrawal As this endpoints are part of tabbed my account menu, you will not be able to access them without login and I really don't know yet if it's possible todo what you are asking… It should be better to make an accessible clone of the related my account tabs in an other accessible section of your website (that you will display for non logged users)…
  • Ralph Smit
    Ralph Smit about 4 years
    This might be great code, but not such a great answer. Some extra explanation could be useful. More importantly: Advising to change the theme's functions.php through the Theme Editor is just plain bad practice, especially without mentioning that theme changes shoudl always be made in a child theme.
  • LoicTheAztec
    LoicTheAztec over 3 years
    This answer code is mostly copied from official WooCommerce "Tabbed “My Account” pages in 2.6" documentation and the author is Claudio Sanches (official WooCommerce developper)… It is already linked In the OP answer