I am working with a hierarchy of pages and want to list the parent & children as a sidebar index (with current page bolded). It's sort of working, but the PHP script I've come up with is using the main page heading to create the link text. These headings are very long for SEO purposes, so I'd like to replace them with the ACF 'subtitle' field that I'm already using. Here's the project before I begin to explain:
https://newstart.staging.wpengine.com/treatment/mental-health/depression
In This Section shows the script-generated list first with the obnoxiously long titles. The shorter titles (beginning with "Mental Health") were hard coded as placeholders, and that is what I would like the script to end up looking like. For example:
Depression is a Huge Risk Factor for Substance Abuse
(should be...)
Depression
How can I replace these titles with the subtitles? The get_field value in ACF is subtitle
Here is what the PHP looks like now:
<?php
//---- GET THE PAGE'S ANCESTORS
global $post;
$anc = get_post_ancestors( $post->ID );
//---- IF $ANC HAS MORE THAN 1 VALUE
//---- THEN WE HAVE A 3RD LEVEL CHILD PAGE
//---- AND THUS WANT THE PARENT ID
$top_id = $post->ID;
if (count( $anc ) > 1 ){
$top_id = $anc[0];
}
//---- TAKEN FROM WP CODEX
$ancestor_id = $top_id;
//VERY IMPORTANT, THE ORDER OF THIS ARRAY
//ENSURE THE SORTING MATCHES IN WP_LIST_PAGES BELOW
$descendants = get_pages(array(
'child_of' => $ancestor_id,
'sort_order' =>'ASC',
'sort_column' => 'menu_order',
));
$incl = "";
foreach ($descendants as $page) {
if (($page->post_parent == $ancestor_id) ||
($page->post_parent == $post->post_parent) ||
($page->post_parent == $post->ID))
{
$incl .= $page->ID . ",";
}
}
//---- MAKE A FINAL ARRAY FOR USE
//---- AS THE PREV//NEXT NAVIGATION
$pages_array = explode( ',', $incl );
array_pop($pages_array); //pop off last empty value
array_unshift( $pages_array, $ancestor_id); //add the top level page
// echo '<pre>';
// print_r($pages_array);
// echo '</pre>';
?>
<?php
//FIND THE NEXT ITEM
//IN THE PAGES ARRAY
//AFTER THE CURRENT PAGE
$curr_key = array_search($post->ID, $pages_array);
$curr_key++;
?>
<?php if( $curr_key < count($pages_array) ){ ?>
<?php
$id = $pages_array[$curr_key];
$title = get_the_title( $id );
$post = get_post( $id );
?>
<div class="col-md-2 hidden-sm hidden-xs section-index">
<h6>In This Section</h6>
<ul>
<?php
wp_list_pages(array(
"include" => $ancestor_id,
"link_before" => "",
"title_li" => "",
));
wp_list_pages(array(
"child_of" => $ancestor_id,
"include" => $incl,
"link_before" => "",
"title_li" => "",
'sort_order' =>'ASC',
'sort_column' => 'menu_order',
));
?>
</ul>
I come from a design background so I am not good with PHP syntax yet. Most of this is inherited code that I only vaguely understand. Any help would be appreciated!
Related
I'm setting up a side navigation menu using wp_list_pages and I would like to convert the children links from URLs into anchor links i.e #link rather than the current https://example.com/link being generated by wp_list_pages .
I was attempting to use the following code:
<?php
$my_pages = wp_list_pages('echo=0&title_li=&child_of=5&depth=1');
$pieces = explode('"', $my_pages);
$i = 5;
$j = 3;
$limit = count($pieces);
for (;$i<$limit;) {
$tmp1 = '#'.$pieces[$j];
$pieces[$i] = $tmp1;
$i = $i+6;
$j = $j+6;
}
$tmp2 = implode('"',$pieces);
echo $tmp2;
?>
But it seems to be very old and I can't wrap my head around how to properly implement it into my current structure. Maybe this code is useless for what I'm trying to do but I couldn't find anything that would work.
This is what I have currently:
<div class="hero-container">
<?php
global $children;
global $post;
if ( $post->post_parent ) {
$children = wp_list_pages( array(
'title_li' => '',
'child_of' => $post->post_parent,
'echo' => 0
) );
} else {
$children = wp_list_pages( array(
'title_li' => '',
'child_of' => $post->ID,
'echo' => 0
) );
}
if ( $children ) : ?>
<?php echo '<div class="hero-side-menu">', '<h1>', get_the_title(), '</h1>', '<ul>', $children, '</ul>', '</div>' ?>
<?php endif; ?>
</div>
Any suggestions would be very much appreciated as I've been trying to figure this out for a few days and have gotten nowhere... also would appreciate an explanation as I'm trying to learn where I went wrong!
I need to modify the children of the parent pages to have #anchor links rather than URLS as I've condensed the pages into their parents but still wish to have them as options within the side menu.
Clarification: I have a page with children pages that I referred to as parents however, they are indeed children. I would like to keep the URLS for the children pages and then make the children of the children #links.
This depends a bit on what you want the anchor text to be. Whether it's an ID or a title, etc. But you can modify that to your need.
You may want to try get_pages() instead, so you have a little more control over the output. Something like the following:
<div class="hero-container">
<?php
global $post;
$current_page_title = $post->post_title; // current page title
$child_pages =
get_pages(
array(
'child_of' => $post->ID
),
);
if ($child_pages) : ?>
<div class="hero-side-menu">
<h1><?php echo $current_page_title; ?></h1>
<ul>
<?php foreach ($child_pages as $page) : ?>
<li><?php echo $page->post_title; ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
</div>
I have a script that is displaying child page list on parent page and a list o child pages without the current child page.
I would like to add the parent page on child pages, but I don't know how to achieve it. Could you please help me out?
This is my code:
if ('page-parent') {
echo '<h3>See also</h3>';
// if we are on a parent page set the $parent variable to current post id
// otherwise set $parent variable to current post parent
$parent = $post->post_parent == 0 ? $post->ID : $post->post_parent;
// if we use current post parent as $parent, exclude the current page
$exclude = $parent == $post->post_parent ? $post->ID : false;
// get all the children
$args = array( 'parent' => $parent, 'sort_column' => 'menu_order' );
if ( $exclude ) $args['exclude'] = $exclude;
$child_pages = get_pages($args);
// show only if there are children
if ( ! empty($child_pages) ) {
global $post;
foreach ( $child_pages as $post ) { setup_postdata( $post );
?>
<div class="child-thumb">
<?php the_title(); ?>
</div>
<?php
}
wp_reset_postdata();
}
}
You need to use 'child_of' argument instead of 'parent'. 'parent' in get_pages means to fetch or not to fetch parental pages.
But your case needs to fetch children of given page.
So you must use
$args = array( 'child_of' => $parent,
'sort_column' => 'menu_order' );
To display one single parent page above children, you can use get_post function:
if ($post->post_parent>0){
$parent_page=get_post($post->post_parent);
echo '<div>'.$parent_page->post_title.'</div>';
}
if ( ! empty($child_pages) ) {
///and so on...
For more information: https://codex.wordpress.org/Function_Reference/get_pages
I'd like to shorten this code and instead of manually placing all children Id's, I'd like to pull out only the id's and set it to array. this could be something dynamic in the future when they are adding new child page from the parent page.
if ( in_array($post->ID, ['39','41','43','45']) ) {
$menuPage = 'about';
} elseif ( in_array($post->ID, ['47','49','51','53','55','57']) ) {
$menuPage = 'asset';
}
get_template_part( _menu, $menuPage );
I tried some codes but it technically display the title only. Where I am currently using similar to this code.
<ul class="uk-nav uk-navbar-dropdown-nav uk-list uk-list-inline">
<?php
$args = array(
'depth' => 1,
'include' => 15,
'title_li' => '',
);
wp_list_pages($args);
$args['child_of'] = $args['include'];
unset($args['include']);
wp_list_pages($args);
?>
</ul>
You can verify the menu to be printed by using wp_get_post_parent_id( $post_ID );, see codex: https://codex.wordpress.org/Function_Reference/wp_get_post_parent_id
Will check the parent ID of every visited child page, then use PHP switch to match the menu.
switch(wp_get_post_parent_id( $post->ID )){
case 1: //parent page ID
$menuPage = 'about';
break;
case 2: //parent page ID
$menuPage = 'asset';
break;
default:
$menuPage = 'default-menu';
}
Also, if you only want to return the child pages from a specific parent, you can use:
$args = array(
'child_of' => $post->ID,
);
$pages = get_pages($args);
Here is an example loop:
$args = array('s' => 'Example search term', 'cat' => 100, 'posts_per_page' => -1);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) { $query->the_post();
foreach((get_the_category()) as $category) {
echo $category->cat_name . '<br />';
}
}
}
wp_reset_query();
Assuming that the category with the id# 100 is a parent category for several subcategories, this loop successfully returns a list of heavily duplicated category names.
How could I list only unique category names and count them? And put both values into appropriate variables.
Along with the complete list of all found results and their count, too...
Of course I'll try to figure out the solution myself while waiting for your kind answer, as always. But, actually, a little help would be much appreciated.
So, I'll respond to myself. Again )
Thanks to #Perumal93's hint which directed me the correct way, I now have the solution.
In case it would be usable for anyone like me, here is the commented code ready for copy and paste:
$args = array('s' => 'Example search term', 'cat' => 100, 'posts_per_page' => -1);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
$categories = array(); // 1. Defining the empty array outside of the loop
while ( $query->have_posts() ) { $query->the_post();
foreach((get_the_category()) as $category) {
$categories[] = $category->cat_name; // 2. Filling the array with required data
}
}
$u_categories = array_unique($categories); // 3. Clearing the array from repeated data
$u_categories_cnt = count($u_categories); // 4. Counting the cleared array items
foreach( $u_categories as $category ) { // 5. Outputting
if($category == end($u_categories)) { echo $category.'.'; } // the cleared
elseif($category == prev($u_categories)) { echo $category.' and '; } // array in a
else {echo $category.', '; } // human
} // friendly way
echo $u_categories_cnt; // 6. Outputting the cleared array items count
}
wp_reset_query();
That's it
I have a small function in my WordPress theme which generates a list of menus depending on category id. I have also setup an even/odd identifier to add spacers in between, the last one is removed via jQuery (unless you can provide a way of doing this in PHP code).
Each menu shows the spacers accordingly apart from one random one?
function momentmag_tertiary_nav($cat_ID, $name = '') {
$categories = get_categories( array('child_of' => $cat_ID, 'hide_empty' => false) );
$siteurl = get_bloginfo('url');
$i = count($categories);
$catparent = get_categories( array('include' => $cat_ID, 'hide_empty' => false) );
echo '<ul class="'.$name.'-drop">';
foreach($categories as $category) {
echo '<li>'.$category->cat_name.'</li>';
if ($i % 2 != 0) {
echo '<li class="spacer"></li>';
}
}
echo '</ul>';
}
Example of working menu:
Then this one randomly doesn't apply the spacers where as all the others do, there is 10 in total:
any ideas? this is really dodgy!