Checking whether post_parent = 0 in WordPress - php

I am creating a site using WordPress using a theme which has this PHP at the top of each page and I am confused as to what it does.
<?php
global $post;
global $wp_query;
if ( $post->post_parent != 0 ) {
$thePostID = $post->post_parent;
} else {
$thePostID = $wp_query->post->ID;
};
?>
I was just wondering if anyone could explain exactly what this does? I think it checks to see if the post_parent id is 0 which isn’t allowed in WordPress and sets the post id to the post_parent but I’m not 100% sure.

I think it checks to see if the post_parent id is 0 which isn’t allowed in WordPress
The $post->post_parent is allowed to be 0. If the value is 0, it simply means that the page is a top level page.
A page that has a $post->post_parent other than 0, is a child of another page.
For example, take this page structure as an example:
id page_title post_parent
1 Home 0
2 About 0
3 Staff 2
4 History 2
5 Contact 0
The resulting page/menu structure would be:
Home
About
Staff
History
Contact
The code in question:
if ($post->post_parent != 0) {
$thePostID = $post->post_parent;
} else {
$thePostID = $wp_query->post->ID;
}
I'm not sure why your theme might have the code, but a possible reason might be to get a menu related to the current page. If you're viewing the top level page (i.e. $post->post_parent == 0), then it would show all child pages, or if you're viewing a sub page, the menu might show all sibling pages.
A sample menu generated using this method
Add this to your functions.php file so it's accessible throughout the theme.
/**
* Get top parent for the current page
*
* If the page is the highest level page, it will return its own ID, or
* if the page has parent(s) it will get the highest level page ID.
*
* #return integer
*/
function get_top_parent_page_id() {
global $post;
$ancestors = $post->ancestors;
// Check if the page is a child page (any level)
if ($ancestors) {
// Get the ID of top-level page from the tree
return end($ancestors);
} else {
// The page is the top level, so use its own ID
return $post->ID;
}
}
Add this code to your theme where you want to display a menu. You will need to customise it to suit your particular needs, but it gives you an example of why someone might use the code you asked about.
// Get the highest level page ID
$top_page_id = get_top_parent_page_id();
// Display basic menu for child or sibling pages
$args = array(
'depth' => 1,
'title_li' => FALSE,
'sort_column' => 'menu_order, post_title',
'child_of' => $top_page_id
);
echo wp_list_pages($args);

So as far as i see, this snippet does the following:
Loads the global post object.
Loads the global query object.
Checks (or tries to check) if the current post has a parent filter (?).
If it has, it sets the variable $thePostID to the id of the post_parent parameter of the current post object.
If it hasnt, it sets the post id in the wp_query to the id of the current post.
All together, this seems very unnecessary, bad performing and strange Oo.
Does ist work actually? ^^
I would advise you on using another theme if possible ;-)

Related

How to set up my Wordpress template structure for handling my custom post types

I'm having trouble setting up my Wordpress template. I'm not sure how to achieve the following. My website setup is the following:
I have a Custom Post Type "Chapter". A "Chapter" is parent to other CPT's. I have a few post types such as: reviews, interviews, blogposts, ...
On a chapter page I do a different WP_Query for every post type within this chapter.
page template single-chapter.php
Now I want to be able to click on "Blogpost (2)" and open an archive page of all blogpost within the current chapter. How can I achieve this? I assume I should create a template page "archive-blogpost.php". I already found that I can link to this page using:
<?php echo get_post_type_archive_link( 'blogpost' ); ?>
However I can't see how this page could know in what chapter i'm currently in?
I never used the WP Types plugin so far, but here is what you could do: add a chapter parameter to the archive link (with a rewrite rule for it), that you'll get in your blogposts archive template and display the posts conditionally to this parameter.
First we change the archive link to send the chapter slug:
<?php echo get_post_type_archive_link( 'blogpost' ) . '/' . $post->post_name; ?>
Then we define in functions.php this new rewrite tag:
function custom_rewrite_tag() {
add_rewrite_tag('%chapter%', '([^&]+)');
}
add_action('init', 'custom_rewrite_tag', 10, 0);
To make the URL looks good, we'll add a rewrite rule (so you don't have a url like /archive/?chapter=chapter-1, but /archive/chapter-1) - this still go to functions.php:
function custom_rewrite_rule($rules) {
add_rewrite_rule('^archive/([^/]+)/?$', 'index.php?post_type=blogposts&chapter=$matches[1]', 'top');
}
add_filter('init', 'custom_rewrite_rule', 10, 0);
You may have to change the URL / post type name depending of your configuration.
And last, you can get this query arg in your blogposts archive template with $wp_query->query_vars array:
$wp_query->query_vars['chapter']
Since I don't know much about WP Types, I'm not really sure about what follows, but it seems you could query the childs posts of the chapter with this:
if(isset($wp_query->query_vars['chapter']) && $chapter = get_page_by_path($wp_query->query_vars['chapter'])) {
$childargs = array(
'post_type' => 'blogposts',
'numberposts' => -1,
'meta_query' => array(array('
key' => '_wpcf_belongs_property_id', 'value' => $chapter->ID
))
);
$child_posts = get_posts($childargs);
} else {
// default template : display all posts
}
I used a WP types functions to achieve what I wanted:
$child_posts = types_child_posts("blogpost", array('post_id' => $_GET['wpv-pr-child-of']));
With this I can query all the child posts from the custom post type on a page.
I also use a session variable to keep track of the current chapter I'm in.

Manual post order arrangement

My goal is to allow exact, sticky, front-page only, positioning of posts based on user back-end input. All other WP behaviour should remain the default.
The front page displays 9 posts
User can select the position of the post on the front page (Off, 1-9)
Only one post can have an assigned position, the posts with the
latest post date is selected, others with the same positioned are
ignored and remain part of the regular orderby flow
In order to re-arrange my posts I run a second WP_Query to collect all posts that have a position assigned to them through a custom meta field. The meta field shows the option 1-9 on the admin post page but corresponds to the index numbers of an array, just like the WP_Query object posts array.
function get_positioned_posts() {
$positioned_posts = get_posts( array (
'meta_query' => array(
array(
'key' => 'post_position',
'value' => array('0','1','2','3','4','5','6','7','8'),
'compare' => 'IN',
),
),
));
return $positioned_posts;
}
Subsequently I get the MAIN posts array, loop over it and insert a positioned post when the index number matches the positioned_post value.
function mns_post_position( $posts) {
if ( is_home() && is_main_query() && ! is_admin() && ! is_search() && ! is_archive()) {
$positioned_posts = get_positioned_posts();
$positioned_post_ids = wp_list_pluck( $positioned_posts, 'ID' );
$num_posts = count( $positioned_posts );
// Find the positioned posts
for ($i = 0; $i < $num_posts; $i++) {
if ( in_array( $positioned_posts[$i]->ID, $positioned_post_ids ) ) {
$positioned_post = $positioned_posts[$i];
// Remove post from current position
array_splice( $posts, 4, 1 );
// Get post position and put it in the posts array
$position = intval(get_post_meta( $positioned_post->ID, 'post_position', true ));
array_splice($posts, $position, 0, array($positioned_post));
}
}
}
return $posts;
}
add_action('the_posts', 'mns_post_position', 1 );
This works great, but it only works for the homepage and not the paged pages. The "the_posts" action only gets the current X (9) posts and not the entire WP Query posts array. This causes unwanted behaviour:
There can be more than 9 posts on the frontpage if a positioned posts
comes from page > 2.
You can see a positioned posts twice, once on the frontpage and later
one a paged page.
Possible solutions
I need to find a way to build the query correctly on the first try.
I don't see how I can achieve this with pre_get_posts filter.
Using "menu_order" like some plugins is not an option. Ordering by date is required.
Find a hook that returns the ENTIRE WP_Query Posts array, which I
just rearrange with array_splice.

Wordpress pages in backend, list with filtered meta value

I'm trying something out with Wordpress. I want to use page as a shell for custom content, so I've setup an action that adds a specific meta_key for each regular page, so that I can single out the regular pages from my 'special-pages'.
function addMetaToPage($post_id) {
if ( wp_is_post_revision( $post_id ) )
return;
if(get_post_type($post_id) == 'page') {
add_post_meta($post_id, '_regular_page', 1, true);
}
}
if(is_admin()) {
add_action('save_post', 'addMetaToPage');
}
Then, in the admin backend where pages are listed I run this hook to prevent all my 'special-pages' to show up.
if(is_admin()) {
add_action('pre_get_posts', function($query) {
$query->set('meta_key', '_regular_page');
$query->set('meta_value', 1);
});
}
And it works. Only pages with meta _regular_page === 1 shows up. However, the counter just above the table that usually sais something like All (15) shows the total number of pages, even though only a couple of them are in the list. Check this screenshot. At this page I got 4 regular pages and 6 pages that dosn't have the _regular_page meta key.
Is there a way to actually fix this? I really thought that the counter was dependent on the WP_Query, but apparently not.
you can edit the count of ALL, Published and trash for the page section in the admin using the filter views_edit-page
you can use something like this
add_filter( "views_edit-page", "filter_regular_page_count", 10, 1);
function filter_regular_page_count( $views ) {
$regular_post_count = 5 ;// you can sort out how to get your regular post count
$views["all"] = 'All <span class="count">('.$regular_post_count.')</span>';
//same for published and trash
return $views;
}
here is example of var dump of views
array (size=3)
'all' => string 'All <span class="count">(7)</span>' (length=88)
'publish' => string '(7)</span>' (length=102)
'trash' => string '(2)</span>' (length=96)
if you want to do the same thing for the posts, WordPress use views_edit-post filter for the posts
actually wordpress use something like this as the filter of the views section ---> views_{$this->screen->id}

How pull in other pages' templates and content and output those on a "combining" page?

Imagine I have the following setup:
* Combining Page (Template: Combine Template)
* Sub Page 1 (Template: Basic Template)
* Sub Page 2 (Template: Other Template)
* Sub Page 3 (Template: Basic Template)
So I have three sub pages, two of which have the same template (which uses custom fields as well as regular content). I want the parent page's template to be able to work like this:
PSEUDO-CODE:
//Show the content for this combine page (e.g. a title)
if ( have_posts() ) : while ...this is the main loop...
$wp_query = new WP_Query();
$all_pages = $wp_query->query( array( "post_type" => "page", "posts_per_page" => -1 ) );
//Get child pages
$child_pages = get_page_children( $post->ID, $all_pages );
//Loop through child pages so we can add their HTML (made from applying their content to their templates)
foreach( $child_pages as $child_page )
{
/** WHAT DO I DO HERE? **/
//Pseudo code
$child_page_template = get_page_template( $child_page->page_name );
$child_output = apply_to( $child_page_template, get_page_content( $child_page->content ) );
}
EDIT
In addition, on the child page, I get a custom field and loop through it:
$values = get_post_custom_values( "mycustomfield" );
foreach ( $values as $value ) echo $value . "<br>";
END EDIT
How would I do this?
Is there anything built in to do this? Or would I need to use output buffers to isolate everything and print each to a buffer from within a function?
It seems like your perspective is just incorrect for the goal you're trying to reach.
Your pseudo code is reminiscent of a funky iframe style approach. Simply breaking your children pages into what WordPress calls "Template Parts" (basically PHP includes) would be the way to solve this (assuming I understand you correctly). Since Template Parts can be recycled and also have some WordPress-specific benefits when it comes to looping and passing arguments and stuff.

Check if a page is a parent or if it's a child page?

Is it possible to check if a page is a parent or if it's a child page?
I have my pages set up like this:
-- Parent
---- Child page 1
---- Child page 2
etc.
I want to show a certain menu if it's a parent page and a different menu if it's on the child page.
I know I can do something like below but I want to make it a bit more dynamic without including specific page ID's.
<?php
if ($post->post_parent == '100') { // if current page is child of page with page ID 100
// show image X
}
?>
You can test if the post is a subpage like this:
*(from http://codex.wordpress.org/Conditional_Tags)*
<?php
global $post; // if outside the loop
if ( is_page() && $post->post_parent ) {
// This is a subpage
} else {
// This is not a subpage
}
?>
Put this function in the functions.php file of your theme.
function is_page_child($pid) {// $pid = The ID of the page we're looking for pages underneath
global $post; // load details about this page
$anc = get_post_ancestors( $post->ID );
foreach($anc as $ancestor) {
if(is_page() && $ancestor == $pid) {
return true;
}
}
if(is_page()&&(is_page($pid)))
return true; // we're at the page or at a sub page
else
return false; // we're elsewhere
};
Then you can use it:
<?php
if(is_page_child(100)) {
// show image X
}
?>
I know this is an old question but I was searching for this same question and couldn't find a clear and simple answer until I came up with this one. My answer doesn't answer his explanation but it answers the main question which is what I was looking for.
This checks whether a page is a child or a parent and allows you to show, for example a sidebar menu, only on pages that are either a child or a parent and not on pages that do not have a parent nor children.
<?php
global $post;
$children = get_pages( array( 'child_of' => $post->ID ) );
if ( is_page() && ($post->post_parent || count( $children ) > 0 )) :
?>
For Wordpress, you can simply check:
<?php
if (wp_get_post_parent_id(get_the_ID())) {
echo "I am a child page";
}
?>
You can use the get_pages() function. it takes an associative array as an argument. you can give that array 'child_of' => get_the_ID() to get the children of the current page, and if it hasn't any children the whole get_pages() function will return false, otherwise it will return a value that evaluates to true, which can be assigned to a variable to use as a conditional in an if statement.
$iAmParent = get_pages(array('child_of' => get_the_ID()));

Categories