Simple dynamic breadcrumb - php

I think this script is of big interest to any noob around here :) including me :)
What I want to create is a little code that I can use in any file and will generate a breadcrumb like this:
If the file is called "website.com/templates/index.php" the breadcrumb should show:
Website.com > Templates
^^ link ^^plain text
If the file is called "website.com/templates/template_some_name.php" the breadcrumb should show:
Website.com > Templates > Template Some Name
^^ link ^^link ^^plain text

This may be overkill for a simple breadcrumb, but it's worth a shot. I remember having this issue a long time ago when I first started, but I never really solved it. That is, until I just decided to write this up now. :)
I have documented as best I can inline, at the bottom are 3 possible use cases. Enjoy! (feel free to ask any questions you may have)
<?php
// This function will take $_SERVER['REQUEST_URI'] and build a breadcrumb based on the user's current path
function breadcrumbs($separator = ' » ', $home = 'Home') {
// This gets the REQUEST_URI (/path/to/file.php), splits the string (using '/') into an array, and then filters out any empty values
$path = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
// This will build our "base URL" ... Also accounts for HTTPS :)
$base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
// Initialize a temporary array with our breadcrumbs. (starting with our home page, which I'm assuming will be the base URL)
$breadcrumbs = Array("$home");
// Find out the index for the last value in our path array
$last = end(array_keys($path));
// Build the rest of the breadcrumbs
foreach ($path AS $x => $crumb) {
// Our "title" is the text that will be displayed (strip out .php and turn '_' into a space)
$title = ucwords(str_replace(Array('.php', '_'), Array('', ' '), $crumb));
// If we are not on the last index, then display an <a> tag
if ($x != $last)
$breadcrumbs[] = "$title";
// Otherwise, just display the title (minus)
else
$breadcrumbs[] = $title;
}
// Build our temporary array (pieces of bread) into one big string :)
return implode($separator, $breadcrumbs);
}
?>
<p><?= breadcrumbs() ?></p>
<p><?= breadcrumbs(' > ') ?></p>
<p><?= breadcrumbs(' ^^ ', 'Index') ?></p>

Hmm, from the examples you gave it seems like "$_SERVER['REQUEST_URI']" and the explode() function could help you. You could use explode to break up the URL following the domain name into an array, separating it at each forward-slash.
As a very basic example, something like this could be implemented:
$crumbs = explode("/",$_SERVER["REQUEST_URI"]);
foreach($crumbs as $crumb){
echo ucfirst(str_replace(array(".php","_"),array(""," "),$crumb) . ' ');
}

Also made a little script using RDFa (you can also use microdata or other formats) Check it out on google
This script also keeps in mind your site structure.
function breadcrumbs($text = 'You are here: ', $sep = ' » ', $home = 'Home') {
//Use RDFa breadcrumb, can also be used for microformats etc.
$bc = '<div xmlns:v="http://rdf.data-vocabulary.org/#" id="crums">'.$text;
//Get the website:
$site = 'http://'.$_SERVER['HTTP_HOST'];
//Get all vars en skip the empty ones
$crumbs = array_filter( explode("/",$_SERVER["REQUEST_URI"]) );
//Create the home breadcrumb
$bc .= '<span typeof="v:Breadcrumb">'.$home.''.$sep.'</span>';
//Count all not empty breadcrumbs
$nm = count($crumbs);
$i = 1;
//Loop the crumbs
foreach($crumbs as $crumb){
//Make the link look nice
$link = ucfirst( str_replace( array(".php","-","_"), array(""," "," ") ,$crumb) );
//Loose the last seperator
$sep = $i==$nm?'':$sep;
//Add crumbs to the root
$site .= '/'.$crumb;
//Make the next crumb
$bc .= '<span typeof="v:Breadcrumb">'.$link.''.$sep.'</span>';
$i++;
}
$bc .= '</div>';
//Return the result
return $bc;}

use parse_url and then output the result in a loop:
$urlinfo = parse_url($the_url);
echo makelink($urlinfo['hostname']);
foreach($breadcrumb in $urlinfo['path']) {
echo makelink($breadcrumb);
}
function makelink($str) {
return ''.htmlspecialchars($str).'';
}
(pseudocode)

I started with the code from Dominic Barnes, incorporated the feedback from cWoDeR and I still had problems with the breadcrumbs at the third level when I used a sub-directory. So I rewrote it and have included the code below.
Note that I have set up my web site structure such that pages to be subordinate to (linked from) a page at the root level are set up as follows:
Create a folder with the EXACT same name as the file (including capitalization), minus the suffix, as a folder at the root level
place all subordinate files/pages into this folder
(eg, if want sobordinate pages for Customers.php:
create a folder called Customers at the same level as Customers.php
add an index.php file into the Customers folder which redirects to the calling page for the folder (see below for code)
This structure will work for multiple levels of subfolders.
Just make sure you follow the file structure described above AND insert an index.php file with the code shown in each subfolder.
The code in the index.php page in each subfolder looks like:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Redirected</title>
</head>
<body>
<?php
$root_dir = "web_root/" ;
$last_dir=array_slice(array_filter(explode('/',$_SERVER['PHP_SELF'])),-2,1,false) ;
$path_to_redirect = "/".$root_dir.$last_dir[0].".php" ;
header('Location: '.$path_to_redirect) ;
?>
</body>
</html>
If you use the root directory of the server as your web root (ie /var/www/html) then set $root_dir="": (do NOT leave the trailing "/" in). If you use a subdirectory for your web site (ie /var/www/html/web_root then set $root_dir = "web_root/"; (replace web_root with the actual name of your web directory)(make sure to include the trailing /)
at any rate, here is my (derivative) code:
<?php
// Big Thank You to the folks on StackOverflow
// See http://stackoverflow.com/questions/2594211/php-simple-dynamic-breadcrumb
// Edited to enable using subdirectories to /var/www/html as root
// eg, using /var/www/html/<this folder> as the root directory for this web site
// To enable this, enter the name of the subdirectory being used as web root
// in the $directory2 variable below
// Make sure to include the trailing "/" at the end of the directory name
// eg use $directory2="this_folder/" ;
// do NOT use $directory2="this_folder" ;
// If you actually ARE using /var/www/html as the root directory,
// just set $directory2 = "" (blank)
// with NO trailing "/"
// This function will take $_SERVER['REQUEST_URI'] and build a breadcrumb based on the user's current path
function breadcrumbs($separator = ' » ' , $home = 'Home')
{
// This sets the subdirectory as web_root (If you want to use a subdirectory)
// If you do not use a web_root subdirectory, set $directory2=""; (NO trailing /)
$directory2 = "web_root/" ;
// This gets the REQUEST_URI (/path/to/file.php), splits the string (using '/') into an array, and then filters out any empty values
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ;
$path_array = array_filter(explode('/',$path)) ;
// This line of code accommodates using a subfolder (/var/www/html/<this folder>) as root
// This removes the first item in the array path so it doesn't repeat
if ($directory2 != "")
{
array_shift($path_array) ;
}
// This will build our "base URL" ... Also accounts for HTTPS :)
$base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/'. $directory2 ;
// Initialize a temporary array with our breadcrumbs. (starting with our home page, which I'm assuming will be the base URL)
$breadcrumbs = Array("$home") ;
// Get the index for the last value in our path array
$last = end($path_array) ;
// Initialize the counter
$crumb_counter = 2 ;
// Build the rest of the breadcrumbs
foreach ($path_array as $crumb)
{
// Our "title" is the text that will be displayed representing the filename without the .suffix
// If there is no "." in the crumb, it is a directory
if (strpos($crumb,".") == false)
{
$title = $crumb ;
}
else
{
$title = substr($crumb,0,strpos($crumb,".")) ;
}
// If we are not on the last index, then create a hyperlink
if ($crumb != $last)
{
$calling_page_array = array_slice(array_values(array_filter(explode('/',$path))),0,$crumb_counter,false) ;
$calling_page_path = "/".implode('/',$calling_page_array).".php" ;
$breadcrumbs[] = "".$title."" ;
}
// Otherwise, just display the title
else
{
$breadcrumbs[] = $title ;
}
$crumb_counter = $crumb_counter + 1 ;
}
// Build our temporary array (pieces of bread) into one big string :)
return implode($separator, $breadcrumbs) ;
}
// <p><?= breadcrumbs() ? ></p>
// <p><?= breadcrumbs(' > ') ? ></p>
// <p><?= breadcrumbs(' ^^ ', 'Index') ? ></p>
?>

hey dominic your answer was nice but if your have a site like http://localhost/project/index.php the 'project' link gets repeated since it's part of $base and also appears in the $path array. So I tweaked and removed the first item in the $path array.
//Trying to remove the first item in the array path so it doesn't repeat
array_shift($path);
I dont know if that is the most elegant way, but it now works for me.
I add that code before this one on line 13 or something
// Find out the index for the last value in our path array
$last = end(array_keys($path));

Here is a great simple dynamic breadcrumb (tweak as needed):
<?php
$docroot = "/zen/index5.php";
$path =($_SERVER['REQUEST_URI']);
$names = explode("/", $path);
$trimnames = array_slice($names, 1, -1);
$length = count($trimnames)-1;
$fixme = array(".php","-","myname");
$fixes = array(""," ","My<strong>Name</strong>");
echo '<div id="breadwrap"><ol id="breadcrumb">';
$url = "";
for ($i = 0; $i <= $length;$i++){
$url .= $trimnames[$i]."/";
if($i>0 && $i!=$length){
echo '<li>'.ucfirst(str_replace($fixme,$fixes,$trimnames[$i]) . ' ').'</li>';
}
elseif ($i == $length){
echo '<li class="current">'.ucfirst(str_replace($fixme,$fixes,$trimnames[$i]) . ' ').'</li>';
}
else{
echo $trimnames[$i]='<li><span> </span></li>';
}
}
echo '</ol>';
?>

A better one using explode() function is as follows...
Don't forget to replace your URL variable in the hyperlink href.
<?php
if($url != ''){
$b = '';
$links = explode('/',rtrim($url,'/'));
foreach($links as $l){
$b .= $l;
if($url == $b){
echo $l;
}else{
echo "<a href='URL?url=".$b."'>".$l."/</a>";
}
$b .= '/';
}
}
?>

Here is my solution based on Skeptic answer. It gets page title from WordPress DB, not from URL because there is a problem with latin characters (slug doesn't has a latin characters). You can also choose to display "home" item or not.
/**
* Show Breadcrumbs
*
* #param string|bool $home
* #param string $class
* #return string
*
* Using: echo breadcrumbs();
*/
function breadcrumbs($home = 'Home', $class = 'items') {
$breadcrumb = '<ul class="'. $class .'">';
$breadcrumbs = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
if ($home) {
$breadcrumb .= '<li>' . $home . '</li>';
}
$path = '';
foreach ($breadcrumbs as $crumb) {
$path .= $crumb . '/';
$page = get_page_by_path($path);
if ($home && ($page->ID == get_option('page_on_front'))) {
continue;
}
$breadcrumb .= '<li>' . $page->post_title . '</li>';
}
$breadcrumb .= '</ul>';
return $breadcrumb;
}
Using:
<div class="breadcrumb">
<div class="container">
<h3 class="breadcrumb__title">Jazda na maxa!</h3>
<?php echo breadcrumbs('Start', 'breadcrumb__items'); ?>
</div>
</div>

This is the code that i personally use in my sites. Works outside of the box.
<?php
function breadcrumbs($home = 'Home') {
global $page_title; //global varable that takes it's value from the page that breadcrubs will appear on. Can be deleted if you wish, but if you delete it, delete also the title tage inside the <li> tag inside the foreach loop.
$breadcrumb = '<div class="breadcrumb-container"><div class="container"><ol class="breadcrumb">';
$root_domain = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'].'/';
$breadcrumbs = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
$breadcrumb .= '<li><i class="fa fa-home"></i><span>' . $home . '</span></li>';
foreach ($breadcrumbs as $crumb) {
$link = ucwords(str_replace(array(".php","-","_"), array(""," "," "), $crumb));
$root_domain .= $crumb . '/';
$breadcrumb .= '<li><span>' . $link . '</span></li>';
}
$breadcrumb .= '</ol>';
$breadcrumb .= '</div>';
$breadcrumb .= '</div>';
return $breadcrumb;
}
echo breadcrumbs();
?>
The css:
.breadcrumb-container {
width: 100%;
background-color: #f8f8f8;
border-bottom-color: 1px solid #f4f4f4;
list-style: none;
margin-top: 72px;
min-height: 25px;
box-shadow: 0 3px 0 rgba(60, 57, 57, .2)
}
.breadcrumb-container li {
display: inline
}
.breadcrumb {
font-size: 12px;
padding-top: 3px
}
.breadcrumb>li:last-child:after {
content: none
}
.breadcrumb>li:last-child {
font-weight: 700;
font-style: italic
}
.breadcrumb>li>i {
margin-right: 3px
}
.breadcrumb>li:after {
font-family: FontAwesome;
content: "\f101";
font-size: 11px;
margin-left: 3px;
margin-right: 3px
}
.breadcrumb>li+li:before {
font-size: 11px;
padding-left: 3px
}
Feel free to play around with the css padding and margins until you get it right for your own site.

function makeBreadCrumbs($separator = '/'){
//extract uri path parts into an array
$breadcrumbs = array_filter(explode('/',parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
//determine the base url or domain
$base = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
$last = end($breadcrumbs); //obtain the last piece of the path parts
$crumbs['Home'] = $base; //Our first crumb is the base url
$current = $crumbs['Home']; //set the current breadcrumb to base url
//create valid urls from the breadcrumbs and store them in an array
foreach ($breadcrumbs as $key => $piece) {
//ignore file names and create urls from directory path
if( strstr($last,'.php') == false){
$current = $current.$separator.$piece;
$crumbs[$piece] =$current;
}else{
if($piece !== $last){
$current = $current.$separator.$piece;
$crumbs[$piece] =$current;
}
}
}
$links = '';
$count = 0;
//create html tags for displaying the breadcrumbs
foreach ($crumbs as $key => $value) :
$x = array_filter(explode('/',parse_url($value, PHP_URL_PATH)));
$last = end($x);
//this will add a class to the last link to control its appearance
$clas = ($count === count($crumbs) -1 ? ' current-crumb' : '' );
//determine where to print separators
$sep = ( $count > -1 && $count < count($crumbs) -1 ? '»' :'');
$links .= "<a class=\"$clas\" href=\"$value\">$key</a> $sep";
$count++;
endforeach;
return $links;
}

Related

PHP dynamic breadcrumb script creates wrong URL after switching to PHP 8.0

I'm using a PHP script to create a dynamic breadcrumb navigation. I found it several years ago in another forum where it was originally posted in 2006. I updated it by removing some deprecated functions and it worked well so far. It creates the crumbs from the page URL:
$path = $this->_homepath;
$html ='';
$html .= 'Start';
$parts = explode('/', $_SERVER['PHP_SELF']);
$partscount = count($parts);
for($i = 1; $i < ($partscount - 1); $i++) {
$path .= $parts[$i] . '/';
$title = $parts[$i];
if ($this->_usereplacements == true) {
reset($this->_replacements);
foreach($this->_replacements as $search => $replace) {
$title = str_replace($search, $replace, $title);
}
}
if ($this->_replaceunderlines == true) {
$title = str_replace('_', ' ', $title);
}
if ($this->_ucfirst == true) {
$title = ucfirst($title);
}
if ($this->_ucwords == true) {
$title = ucwords($title);
}
$html .= $this->_separator . '' . $title . '';
}
The current page title, i.e. the last element of the bradcrumb, is generated as follows:
$title = '';
if ($title == '') {
$title = $parts[$partscount-1];
if ($this->_usereplacements == true) {
reset($this->_replacements);
foreach($this->_replacements as $search => $replace) {
$title = str_replace($search, $replace, $title);
}
}
if ($this->_removeextension == true) {
$title = substr($title, 0, strrpos($title, '.'));
}
if ($this->_replaceunderlines == true) {
$title = str_replace('_', ' ', $title);
}
if ($this->_ucfirst == true) {
$title = ucfirst($title);
}
if ($this->_ucwords == true) {
$title = ucwords($title);
}
}
$html .= $this->_separator . '<b>' . $title . '</b>';
I only copied relevant parts of the script and spared eg. the function declarations.
After switching from PHP 7.4 to 8.0 I found that the script is messing up a bit. Consider a page with this url: https://www.myhomepage.com/site1/site2/site3
For the crumbs of site1 the script is now generating the URL https://www.myhomepage.com/site1/site2/site1 insted of https://www.myhomepage.com/site1/, whereas for site2 it shows https://www.myhomepage.com/site1/site2/site1/site2 instead of https://www.myhomepage.com/site1/site2/. As you can see, the whole path https://www.myhomepage.com/site1/site2/ is always added as a prefix before the actual path of the crumb.
I haven't found a solution yet despite looking over this thing for two days. I suppose there have been some changes in PHP 8.0 which causes this behaviour, but I haven't found any clues in the incompatibility list (https://www.php.net/manual/de/migration80.php). I printed §path and $title and they look like they should. When echoing $html after each iteration in the for loop it shows already the wrong URLs. That's why I think that probably the for loop is the problem here. Do you have any suggestions?
Any help on this would be very much appreciated.
I finally was able to figure out what causes the strange behaviour of the script. In the declaration of the breadcrumb constructing function there is $this->_homepath = '/';. Later on I assign $path = $this->_homepath;. When I echo $path its empty instead of showing the aforementioned "/". So I directly set $path = '/'; and now everything works again as it should.

Breadcrumb menu PHP generating additional blank anchor links

Lets say I have the following URL:
https://site.website/products/products-level-2
And on products-level-2 I have a breadcrumb hero section. What I'm expecting to see is:
Products / Products Level 2
However, with my current approach, I'm seeing:
/ Products / Products Level 2 /
^^ the above has the following HTML output:
<!-- link 1 - not needed -->
<a class="crumbMenu" href="site.website"> </a>
<span class="slash">/</span>
<!-- link 2 -->
<a class="crumbMenu" href="site.website//products">Products </a>
<span class="slash">/</span>
<!-- link 3 -->
<a class="crumbMenu" href="site.website//products/products-level-2">Products Level 2</a>
<span class="slash">/</span>
<!-- link 4 - not needed -->
<a class="crumbMenu" href="site.website//products/products-level-2"> </a>
<span class="slash">/</span>
The above has the following issues:
It's outputting blank / not needed anchor links.
In the href, it's outputting double // (i.e. site.website//products)
I also do not want the last item (i.e products level 2) to be a link (since the user is viewing the breadcrumb on that page).
I don't want / to appear at the start and end of the breadcrumb.
Here is my current approach:
<?php
// 1. Get URL
$crumbs = explode("/",$_SERVER["REQUEST_URI"]);
$address = $_SERVER['HTTP_HOST'];
// 2. Strip extras
$build = '';
foreach($crumbs as $crumb){
$build .= '/'.$crumb;
$crumb = ucfirst(str_replace(array(".php","_"),array(""," "),$crumb) . ' ');
echo
"<a class='crumbMenu' href=".$address.$build.">".$crumb."</a>
<span class='slash'>/</span> ";
}
?>
To solve 1,2,4 just remove the leading and trailing slashes. To solve 3 you need to make a simple if:
// 1. Get URL
$crumbs = explode("/", trim($_SERVER["REQUEST_URI"], '/'));
$address = $_SERVER['HTTP_HOST'];
// 2. Strip extras
$build = '';
$lastKey = count($crumbs) - 1;
foreach($crumbs as $key => $crumb){
$build .= '/'.$crumb;
$crumb = ucfirst(str_replace(array(".php","_"),array(""," "),$crumb) . ' ');
echo $key < $lastKey
? "<a class='crumbMenu' href=".$address.$build.">".$crumb."</a>
<span class='slash'>/</span>"
: $crumb;
}
Demo: https://3v4l.org/BqD7C
Solution:
The final working code you end up with is as follows:
<?php
// 1. Get URL
$crumbs = explode("/",$_SERVER["REQUEST_URI"]);
array_filter($crumbs);
$count = count($crumbs);
$address = $_SERVER['HTTP_HOST'];
// 2. Strip extras
$build = '';
$i = 0;
foreach($crumbs as $crumb) {
$href = (++$i != $count ? 'href="' . $address . $build . '"' : '');
$build .= '/'.$crumb;
$crumb = ucfirst(str_replace(array(".php","_"),array(""," "),$crumb) . ' ');
echo
"<a class='crumbMenu' " . $href . ">".$crumb."</a>
<span class='slash'>/</span> ";
}
?>
Explanation:
1. It's outputting blank / not needed anchor links.
Simply run array_filter, this will remove any blank elements in the array.
array_filter($crumbs);
2. In the href, it's outputting double // (i.e. site.website//products)
The reason this happens is because it iterates through the blank element in the array first and as this adds a forward slash by default, by the second loop there is already a forward slash present, so it doubles up.
This issue is solved in the solution to question 1.
3. I also do not want the last item (i.e products level 2) to be a link (since the user is viewing the breadcrumb on that page).
After running array_filter on $crumbs you'll want to count how many elements are in the array using:
$count = count($crumbs);
Then when you are looping through the array, you'll want to workout when the loop is the last loop of the array:
$i = 0;
foreach($crumbs as $crumb) {
$href = (++$i != $count ? 'href="' . $address . $build . '"' : '');
// ...rest of foreach
$build .= '/' . $crumb;
$crumb = ucfirst(str_replace(array(".php","_"),array(""," "),$crumb) . ' ');
echo "<a class='crumbMenu' " . $href . ">".$crumb."</a><span class='slash'>/</span> ";
}
4. I don't want / to appear at the start and end of the breadcrumb.
This was resolved with my solution to your first question right at the top of this answer.
/* A character used as a divider between the breadcrumbs */
$separator = ' / ';
/* The current page uri from which to build breadcrumb trail */
$uri='https://'.$_SERVER['HTTP_HOST'].'/products/computers/microsoft/laptops/acer/professional';
/* capture the path and explode to create an array - removing empty entries in the process */
$crumbs=array_filter( explode( '/', parse_url( $uri, PHP_URL_PATH ) ) );
/* The host and protocol for building correct links */
$host=sprintf( '%s://%s/', parse_url( $uri, PHP_URL_SCHEME ), parse_url( $uri, PHP_URL_HOST ) );
/* placeholder array to store generated links */
$html=[];
/* iterate through the array and build relevant HTML content - append to output array */
foreach( $crumbs as $index => $crumb ){
/* tweak the text displayed */
$crumb = ucfirst( str_replace( array( ".php", "_" ), array( "", " " ), $crumb ) );
/* the path should be all the previous breadcrumb crumbs */
$path=[];
for( $i=1; $i < $index; $i++ ) $path[]=$crumbs[ $i ];
$path=implode( DIRECTORY_SEPARATOR, $path );
/* create the link used in the html display */
$html[]= ( $index==count( $crumbs ) ) ? sprintf('<span>%s</span>', $crumb ) : sprintf("<a href='%s%s' class='crumbMenu'>%s</a>", $host, $path, $crumb );
}
echo $uri, "
<style>
#breadcrumbs{border:1px solid gray;padding:1rem;font-family:calibri,verdana,arial}
#breadcrumbs *{padding:1rem;}
#breadcrumbs a,
#breadcrumbs span:hover{color:blue}
#breadcrumbs a:hover{color:red;}
#breadcrumbs span{font-weight:bolder;}
</style>
<div id='breadcrumbs'>",
implode( $separator, $html ),
"</div>";

How to create a dynamic breadcrumb nav in twig

I would like to create a dynamic breadcrumb nav in Twig.
Example url www.example.com/section/page
I want to get the url, split it into a breadcrumb such as: home > section > page
I've found this php code which works. Can anyone help convert it into Twig?
<?php
// This function will take $_SERVER['REQUEST_URI'] and build a breadcrumb based on the user's current path
function breadcrumbs($separator = ' » ', $home = 'Home') {
// This gets the REQUEST_URI (/path/to/file.php), splits the string (using '/') into an array, and then filters out any empty values
$path = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
// This will build our "base URL" ... Also accounts for HTTPS :)
$base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
// Initialize a temporary array with our breadcrumbs. (starting with our home page, which I'm assuming will be the base URL)
$breadcrumbs = array("".$home."");
// Find out the index for the last value in our path array
//$last = end(array_keys($path));
// Build the rest of the breadcrumbs
foreach ($path AS $x => $crumb) {
// Our "title" is the text that will be displayed (strip out .php and turn '_' into a space)
$title = ucwords(str_replace(Array('.php', '_'), Array('', ' '), $crumb));
// If we are not on the last index, then display an <a> tag
if ($x != $last)
$breadcrumbs[] = "".$title."";
// Otherwise, just display the title (minus)
else
$breadcrumbs[] = $title;
}
// Build our temporary array (pieces of bread) into one big string :)
return implode($separator, $breadcrumbs);
}
?>
<p><?= breadcrumbs() ?></p>
<p><?= breadcrumbs(' > ') ?></p>
<p><?= breadcrumbs(' ^^ ', 'Index') ?></p>
You don't need to convert that function into Twig, you just can tell Twig to make this function available into the template for you by extending twig:
$twig = new Twig_Environment($loader);
$function = new Twig_SimpleFunction('breadcrumb', function ($separator = ' » ', $home = 'Home') {
$path = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
// This will build our "base URL" ... Also accounts for HTTPS :)
$base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
// Initialize a temporary array with our breadcrumbs. (starting with our home page, which I'm assuming will be the base URL)
$breadcrumbs = array("".$home."");
// Find out the index for the last value in our path array
//$last = end(array_keys($path));
// Build the rest of the breadcrumbs
foreach ($path AS $x => $crumb) {
// Our "title" is the text that will be displayed (strip out .php and turn '_' into a space)
$title = ucwords(str_replace(Array('.php', '_'), Array('', ' '), $crumb));
// If we are not on the last index, then display an <a> tag
if ($x != $last)
$breadcrumbs[] = "".$title."";
// Otherwise, just display the title (minus)
else
$breadcrumbs[] = $title;
}
// Build our temporary array (pieces of bread) into one big string :)
return implode($separator, $breadcrumbs);
});
$twig->addFunction($function);
You then can use this function inside twig wherever you want:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<nav>
{{ breadcrumbs() }}
</nav>
</body>
</html>

How to remove the trailing double arrows "»" from breadcrumbs on the home page only

I found this useful PHP snippet and made a couple small modifications, but I have not been able to figure out how to exclude the home page from showing the trailing "»" after the word "Home". As a result, it ends up looking like this... Home » .
Is there a simple way to remove this without changing the way the breadcrumbs appear on any other page?
<?php
function breadcrumbs($sep = ' » ', $home = 'Home') {
//Use RDFa breadcrumb, can also be used for microformats etc.
$bc = '<div xmlns:v="http://rdf.data-vocabulary.org/#" id="crums">'.$text;
//Get the website:
$site = 'http://'.$_SERVER['HTTP_HOST'];
//Get all vars en skip the empty ones
$crumbs = array_filter( explode("/",$_SERVER["REQUEST_URI"]) );
//Create the home breadcrumb
$bc .= '<span typeof="v:Breadcrumb">'.$home.''.$sep.'</span>';
//Count all not empty breadcrumbs
$nm = count($crumbs);
$i = 1;
//Loop the crumbs
foreach($crumbs as $crumb){
//Make the link look nice
$link = ucfirst( str_replace( array(".php","-","_"), array(""," "," ") ,$crumb) );
//Loose the last seperator
$sep = $i==$nm?'':$sep;
//Add crumbs to the root
$site .= '/'.$crumb;
//Make the next crumb
$bc .= '<span typeof="v:Breadcrumb">'.$link.''.$sep.'</span>';
$i++;
}
$bc .= '</div>';
//Return the result
return $bc;}
?>
<p><?= breadcrumbs() ?></p>
You have to remove the separator character that is put each time after "Home". Add it only if there is something after "Home".
$crumbs = array_filter( explode("/",$_SERVER["REQUEST_URI"]) );
//Count all not empty breadcrumbs
$nm = count($crumbs);
$i = 1;
// Add first separator if there is at least one crumb
$homesep = $nm == 0?'':$sep;
//Create the home breadcrumb
$bc .= '<span typeof="v:Breadcrumb">'.$home.''.$homesep.'</span>';
//Loop the crumbs
foreach($crumbs as $crumb){
...
}

PHP multidimensional array recursion problem [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Walk array recursively and print the path of the walk
Anyone can help me on this code?
<?php
function buildMenuWalk(&$array, &$depth, $currentDepth = 1)
{
# start new level html
$html = '';
# walk till the depth defined on the config
if($currentDepth > $depth)
{
return null;
}
# loop through all items in this level
foreach($array as $key => &$value)
{
# if not in area map continue
if(!is_numeric($key))
{
continue;
}
# if no <li> has been created yet, open the <ul>
$html .= empty( $html ) ? '<ul class="dropdown">' : '';
#extract the label from this level's array, designated by $labelKey
$label = isset( $value['areaname'] ) ? $value['areaname'] : '';
# open an <li>
$html .= '<li>';
# generate url
$url = '';
if($currentDepth == $depth)
{
$url = ' href="'.
$url .= '"';
}
# construct content inside the <li>
$html .= '<a' . $url .'>' . $label . '</a>';
# run the function again to grab children levels
if(is_array($value))
{
$html .= buildMenuWalk($value, $depth, $currentDepth + 1);
}
# close <li>
$html .= '</li>';
}
# close <ul> if was generated content on this level
$html .= !empty( $html ) ? '</ul>' : '';
return $html;
}
$depth = 2;
$config['content']['map'][1]['areaname'] = 'area_1';
$config['content']['map'][1][1]['areaname'] = 'block_1';
$config['content']['map'][2]['areaname'] = 'area_2';
$config['content']['map'][2][1]['areaname'] = 'block_1';
$config['content']['map'][2][2]['areaname'] = 'bloack_2';
echo buildMenuWalk($config['content']['map'], $depth);
?>
If you check the code above, Im using to display a menu recursively ...
If the script identify the menu reached the depth, will display href="" inside the tag. Inside this href I want add all parent areas on the recursion.
For example:
$config['content']['map'][2]['areaname'] = 'area_2';
$config['content']['map'][2][1]['areaname'] = 'block_1';
$config['content']['map'][2][2]['areaname'] = 'bloack_2';
When script reaches the bloack_2, I need display:
<a href="area_2=2&block_2=2">
Since its a multidimensional array and can grow to like 4-5 dimension, the output href should count all these levels. For example area_2=1&block_10=5&sub_area_1=5&section_7=8 ...
I probably need some array to store all href path during the recursion, but I cant figure how to do it.
Thanks,
PS: The script will be used to build a dropdown menu. The parent levels don't need to be linked, so print the tag will display the child menu. The last child, will be linked, but need contain all parent params so the results can be filtered.
Link to the code running and returning values:
http://codepad.org/iyrcdfQP
Here is a modification of that same slice of code that makes the href= a little more like what you are describing, although it doesn't really make sense to me.
# generate url
$url = '';
if($currentDepth == $depth) {
$url = " href=".$GLOBALS['area_name']."=".$GLOBALS['area']."&$label=$key";
}
else {
$GLOBALS['area'] = $key;
$GLOBALS['area_name'] = $label;
}
I don't see why one would bother with recursoin and multiple dimensions in a world of 2 dimensions as the menu in a web page is!
I would go for 2 dimensions only, the first dimension is to keep all elements (without any criteria) and the second to keep infos about the element:
Check an example for yourself, you set which element to get the function displays it along with all ancestors and root elements of previous levels (as California is).
<?php
function buildMenuWalk($element,$menuElements)
{
for($i=0;$i<=$element;$i++)
{
//for a new level go to the next line
if(!isset($menuElements[$i]['ancestors']))
{
echo '<br>______________________________________</br>';
echo '<strong>',$menuElements[$i]['label'],'</strong> | ';
}
//if the element is reached display it along with ancestors
if($i==$element)
{
//echo all the ancestores
foreach($menuElements[$element]['ancestors'] as $value)
{
echo $menuElements[$value]['label'],' | ';
}
//display the element itself
echo '<font color=red>',$menuElements[$element]['label'],' | </font>';
}
}
}
//California
$menuElements[0]=Array('url'=>'http://www.California.com','label'=>'California');
$menuElements[1]=Array('url'=>'http://www.San Diego.com','label'=>'San Diego','ancestors'=>Array(0));
$menuElements[2]=Array('url'=>'http://www.San Jose.com','label'=>'San Jose','ancestors'=>Array(0,1));
$menuElements[3]=Array('url'=>'http://www.San Francisco.com','label'=>'San Francisco','ancestors'=>Array(0,1,2));
$menuElements[4]=Array('url'=>'http://www.Fresno.com','label'=>'San Francisco','ancestors'=>Array(0,1,2,3));
$menuElements[5]=Array('url'=>'http://www.Sacramento.com','label'=>'Sacramento','ancestors'=>Array(0,1,2,3,4));
//Wyoming
$menuElements[6]=Array('url'=>'http://www.Wyoming.com','label'=>'Wyoming');
$menuElements[7]=Array('url'=>'http://www.Cheyenne.com','label'=>'Cheyenne','ancestors'=>Array(6));
$menuElements[8]=Array('url'=>'http://www.Casper.com','label'=>'Casper','ancestors'=>Array(6,7));
$menuElements[9]=Array('url'=>'http://www.Laramie.com','label'=>'Laramie','ancestors'=>Array(6,7,8));
$menuElements[10]=Array('url'=>'http://www.Gillette.com','label'=>'Gillette','ancestors'=>Array(6,7,8,9));
$menuElements[11]=Array('url'=>'http://www.Rock Springs.com','label'=>'Rock Springs','ancestors'=>Array(6,7,8,9,10));
echo '<pre>';
buildMenuWalk(9,$menuElements);
?>
Since this function is recursively calling itself, you'll have to refer to a global variable to keep track of the previous tree. So here is the code that'll do what I think you want it to do. All of you have to change is the #generate url section.
# generate url
$url = '';
if($currentDepth == $depth) {
$url = " href=area=" . $GLOBALS['area'] . "&block=$key";
} else {
$GLOBALS['area'] = $key;
}

Categories