Multiple pages with same URL in WordPress - php

I have a WordPress site that has a standard Page called Places with URL
example.com/places/
And I have several child Pages called by cities
example.com/places/city-1
example.com/places/city-2
Now, I have a custom post type Place that should indicate a single place and should have permalink like
example.com/places/place-1
But then if I go to one of the previous links with city-1, city-2 I get 404 obviously because there is no place with that permalink.
Is there a way for WordPress to drop to previous permalink. So if there is no place with that name, look for a page with it.

You could probably use the the REFERER-value from the PHP server variable $_SERVER, but it´s not very reliable and can be altered.
I am using the plugin "Permalink Finder" in one of the pages I am maintaining and that works quite well for finding changed URL. You could give it a try and see if it works for you, too.

In case somebody ever having a similar problem, it can be done by using verbose page rules. This is an example I found at WordPress Stack Exchange
https://wordpress.stackexchange.com/questions/22438/how-to-make-pages-slug-have-priority-over-any-other-taxonomies-like-custom-post
add_action( 'init', 'wpse16902_init' );
function wpse16902_init() {
$GLOBALS['wp_rewrite']->use_verbose_page_rules = true;
}
add_filter( 'page_rewrite_rules', 'wpse16902_collect_page_rewrite_rules' );
function wpse16902_collect_page_rewrite_rules( $page_rewrite_rules )
{
$GLOBALS['wpse16902_page_rewrite_rules'] = $page_rewrite_rules;
return array();
}
add_filter( 'rewrite_rules_array', 'wspe16902_prepend_page_rewrite_rules' );
function wspe16902_prepend_page_rewrite_rules( $rewrite_rules )
{
return $GLOBALS['wpse16902_page_rewrite_rules'] + $rewrite_rules;
}

Related

Make custom post type that is rendered by plugin not queryable

I'm using the WooCommerce plugin and with it comes the products post type.
For my site, I've created actual pages for my products, so I don't need /products to exist.
Usually, if I had created the post type, I would add publicly_queryable' => false to make sure the /products url didn't exist, but this post type is created by WooCommerce so unsure how to go about it? Or if it has any implications.
Trying to remove these unnecessary pages from the sitemap.
So this answer came from this post over at the WordPress Stack Exchange site.
Add this to your theme's functions.php file and give it a try. I tested it on a clean WP install with just WooCommerce installed, and it seems to work as intended.
function change_wp_object() {
if(post_type_exists('product')){
$object = get_post_type_object('product');
$object->publicly_queryable = false;
}
}
add_action('init','change_wp_object');
I added a check to see if the 'product' post type exists (please note that your question says the post type is called 'products' but it is actually 'product'). Adding that if/condition helps eliminate errors thrown if WooCommerce wasn't installed or activated.
If you want to exclude post_type from Yoast SEO sitemap - try this code
function sitemap_exclude_post_type( $excluded, $post_type ) {
return $post_type === 'product';
}
add_filter( 'wpseo_sitemap_exclude_post_type', 'sitemap_exclude_post_type', 10, 2 );

WP v-5.5 $_GET parameter does not work in my plugin

I have developed a wordpress plugin. In my plugin I manage all pages by get parameters like (http://example.com/client-portal/?page=dashboard) and it was working till wordpress version 5.4
But new version of wordpress version 5.5 in automatically redirect http://example.com/client-portal/?page=dashboard to http://example.com/client-portal/. Get parameter vanished automatically.
I have added shortcode by this way -
//page short code for user page
add_shortcode( 'ccgclient_portal', array($this,'ccgclient_portal_shortcode_func') );
This is my shortcode function -
function ccgclient_portal_shortcode_func()
{
ob_start();
include_once 'pages/user/index.php';
return ob_get_clean();
}
And catch get parameters by -
if(isset($_GET['page']) && $_GET['page'] == 'dashboard'){
include_once 'dashboard.php';
}
I don't know what's wrong with the new version of wordpress (5.5).
Please can you help me ?
Thanks in advance.
I believe your issue is with the 'page' key, this is a post type slug and it's creating a conflict with WP in this version. This is the same as configuring the permalink to work with '?post=98979' or a similar format.
My suggestion is to try and use a different get key and see what happens.
Let me know what you get.
I have the same issue with my plugin.
My problem was not using a new key. My client defined "page" here. It is about all the old links around in the world.
Im my case I solved it like this:
add_action( 'parse_request', 'ai_parse_request', 1);
and in
function ai_parse_request( $query ) {
unset( $query->query_vars['page']);
return $query;
}
I remove the "page" parameter from the $query to avoid the 301 redirect.
I have made this "workaround" configurable as the page parameter is used actually for pagination in the blog. In you case you should only apply this if e.g. the parameter is not a number to make sure you don't break pagination globally!

Why does WordPress add a duplicate numeric slug upon post/page view?

This is my first post here, so I apologize in advance for any mishaps.
I've been searching for hours trying to figure this one out, but I simply can't seem to understand why this is happening.
The site I'm setting up is a child site (not in a multisite sense, but as a separate site/domain with the same branding). Some of the posts on my site will originate from the parent/main site (but will be made as new posts through copy-paste), and I want the original article ID as part of the permalinks.
E.g. http://www.example.com/hello-world/12345/, where 12345 is the article ID of the article on the parent/main site.
To accomplish this, I've added a custom field to my posts where I can add the article ID of the original article with external_article_id as Field Name. I've then tried to manipulate the permalinks with the following code:
add_filter('post_link', 'append_custom_permalink', 10, 2);
function append_custom_permalink($url, $post) {
$newurl = $url;
if ($post->post_type == 'post') {
$custom = get_post_custom_values('external_article_id', $post->ID);
if (!empty($custom))
$newurl = $url . $custom[0] . '/';
}
return $newurl;
}
Whenever I output the permalink to the posts it appears exactly as I want it, both in the editor and on the site. However, when I either click a link or enter the address manually, I get redirected automatically to http://www.example.com/hello-world/12345/12345/. It duplicates the additional numerical slug, and also happens when I replace $custom[0] with a hard-coded numeric value. This applies to all posts, and my permalink structure (in the settings) is set to /%postname%/.
I even tried setting the permalink structure to /%postname%/%ext_article_id%/ and replace %ext_article_id% with $custom[0], but with the exact same outcome. I also tried using the same code on another WordPress site, except this time with pages instead of posts, also with the exact same outcome.
Ideally I would like to use something like add_query_arg($custom[0], '', get_permalink($post->ID));, but omit the question mark that comes along with it.
Could someone please explain to me why this is happening, and how I can circumvent this? Do I need to use some other filter, or how can I approach this?
Thank you in advance!
In order to make this work you also need to make WordPress aware of the rewrite_tag and specify an additional permalink structure via add_permastruct. The following code should do the trick:
function append_custom_permalink( $post_link, $post ) {
if( $post->post_type == 'post' ) {
$custom = get_post_custom_values( 'external_article_id', $post->ID );
if( ! empty($custom) ) {
$post_link = $post_link.$custom[0].'/';
}
}
return $post_link;
}
add_filter('post_link', 'append_custom_permalink', 10, 2);
function sof_30058470_posts_rewrite() {
add_rewrite_tag('%external_article_id%', '([^/]+)', 'external_article_id=');
add_permastruct('external_article_id', '/%year%/%monthnum%/%day%/%postname%/%external_article_id%/', false);
}
add_action('init', 'sof_30058470_posts_rewrite', 10, 0);
Make sure to re-save your permalink structure at Settings->Permalinks once you added the code. You may also need to refresh/clear your browser cache.

How to use a custom post type archive as front page in WordPress?

I'd like to use a custom post type archive as a site's front page, so that
http://the_site.com/
is a custom post type archive displayed according to my archive-{post-type}.php file.
Ideally I would like to alter the query using is_front_page() in my functions.php file. I tried the following, with a page called "Home" as my front page:
add_filter('pre_get_posts', 'my_get_posts');
function my_get_posts($query){
global $wp_the_query;
if(is_front_page()&&$wp_the_query===$query){
$query->set('post_type','album');
$query->set('posts_per_page',-1);
}
return $query;
}
but the front page is returning the content of "Home" and seems to be ignoring the custom query.
What am I doing wrong? Is there a better way, in general, of going about this?
Note: I did post this in WordPress Answers but that community is comparatively tiny.
Posting the final solution as an answer (Isaac placed it as a comment) just for anyone still looking.
Isaac was on the right track with adding a filter via functions.php. What he did wrong was call is_front_page(), which doesn't work yet because we're in pre_get_posts and the query hasn't been executed yet.
We do have the current page ID however. So we can still solve this, by looking into the WordPress option register for an option called page_on_front, which returns the ID of the page the user set as frontpage.
(For an overview of all WordPress options, just visit <yourwordpressinstallation>/wp-admin/options.php in your browser.)
Which makes for the following solution as suggested by Ijaas:
add_action("pre_get_posts", "custom_front_page");
function custom_front_page($wp_query) {
// Compare queried page ID to front page ID.
if(!is_admin() && $wp_query->get("page_id") == get_option("page_on_front")) {
// Set custom parameters (values based on Isaacs question).
$wp_query->set("post_type", "album");
$wp_query->set("posts_per_page", -1);
// WP_Query shouldn't actually fetch the page in our case.
$wp_query->set("page_id", "");
}
}
You might have to alter a few conditional tags to make sure all plugins still work, depending on how heavily the query gets altered.
Hope this helps someone.
Update: as noted below, add !is_admin() to the if-statement to make sure the function only runs on the frontend. If you only want this action to run for the initial query, you could also add the main query check $wp_query->is_main_query().
In response to Robberts solution:
answered May 6 '13 at 12:04
adding && !isAdmin() to the if function other wise it replaces the post type query for all admin pages as well.
Just in case anyone has issues with this.
edit:
also adding && $wp_query->is_main_query() to the if statement stops it affecting widgets and the menu
so total code I have
if($wp_query->get("page_id") == get_option("page_on_front") && !isAdmin() && $wp_query->is_main_query()) {}
In order to get that query to work, you're going to have to add that code to a page template, create a page, set your template as the template for the page you just created, and then set that page as the home page in Settings => Reading in the admin area.
By the way, the is_front_page() function only returns true if you're on a page that's been set as the home page from the admin menu.
The other option would be to modify index.php, but if you did that, is_front_page() would always return false. In that case, you'd want to use is_home() instead.
I hope that helps.
Isaac, you are correct, I didn't thoroughly read your question and I made the assumption that you were looking to do this the "easy" way.
Anyway, I put your code on my test site and, indeed, it didn't work. I looked at my SQL log and it turns out that your code produces this in the query wp_posts.post_status = 'private'.
So, I tried adding the line $query->set('post_status', 'public'); to your function, and it worked just fine.
In summary, try this:
add_filter('pre_get_posts', 'my_get_posts');
function my_get_posts($query){
global $wp_the_query;
if(is_front_page()&&$wp_the_query===$query){
$query->set('post_type','album');
$query->set('posts_per_page',-1);
$query->set('post_status', 'public');
}
return $query;
}

Wordpress plugin: Hook on custom url

I want to make a plugin, that I will use for some jQuery AJAX loading of table data.
I have a function that prints the data correctly, but how do I "hook" into a specific url?
Like say, I want the function to be run, and the data to be printed whenever a request to /mycustomplugin/myurl.php is run? (Please note that the url/file should not exist)
I have no experience with WP plugins.
To filter your custom URL before Wordpress starts executing queries for other things use something like this:
add_action('parse_request', 'my_custom_url_handler');
function my_custom_url_handler() {
if($_SERVER["REQUEST_URI"] == '/custom_url') {
echo "<h1>TEST</h1>";
exit();
}
}
A simple
if ($_SERVER["REQUEST_URI"] == '/mycustomplugin/myurl.php') {
echo "<my ajax code>";
}
Should work wonders.
If you wanted to return regular wordpress data you could just include wp-blogheader.php into your custom php file like so
//Include Wordpress
define('WP_USE_THEMES', false);
require('Your_Word_Press_Directory/wp-blog-header.php');
query_posts('showposts=10&cat=2');
Just use regular theming tags to return the content you desire. This
Where is your table data coming from though? Are you trying to show this information on the admin side or the viewer side?
Also see for a full breakdown of calling hooked functions with wp_ajax http://codex.wordpress.org/AJAX_in_Plugins
add_action( 'init', 'my_url_handler' );
function my_url_handler() {
if( isset( $_GET['unique_hidden_field'] ) ) {
// process data here
}
}
using add_action( 'init', 'your_handler') is the most common way in plugins since this action is fired after WordPress has finished loading, but before any headers are sent. Most of WP is loaded at this stage, and the user is authenticated.

Categories