Simple dynamic breadcrumb
Asked Answered
S

12

24

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

Sportive answered 7/4, 2010 at 16:36 Comment(1)
Anyone know how to do this in Twig? See my question here: #38551901Ap
T
33

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) . ' ');
}
Tizzy answered 7/4, 2010 at 16:39 Comment(0)
A
52

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 = ' &raquo; ', $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("<a href=\"$base\">$home</a>");

    // 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[] = "<a href=\"$base$crumb\">$title</a>";
        // 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>
Abducent answered 7/4, 2010 at 17:42 Comment(10)
No problem, I hope it helps :)Abducent
Also, not everybody's using short tags <? ?> :)Judgment
I come up with errors : Notice: Undefined index: HTTPS in C:\xampp\htdocs\xampp\examples\PORTFOLIO\DVD Rental System\classes\BreadCrumbTrail.php on line 9 Strict Standards: Only variables should be passed by reference in C:\xampp\htdocs\xampp\examples\PORTFOLIO\DVD Rental System\classes\BreadCrumbTrail.php on line 13Lennon
Not sure who copied who here. Just found thisScreech
Haha, that's awesome. I definitely wrote this myself, but I don't mind it becoming copy-pasta at all. :)Abducent
@DominicBarnes How can I do this in Twig? See my question here: #38551901Ap
@NahserBakht Get rid of the warnings by changing $base = ($_SERVER['HTTPS'] //code to $base = (isset($_SERVER['HTTPS']) and then change ` $last = end(array_keys($path));` to $pathkeys = array_keys($path); $last = end($pathkeys); Hope that helps!Tisbe
I'd like to ask if it's possible to not start with the index path? Example: instead of "/", it'll start with "/foo/bar/" as the base url.Mercymerdith
I had some trouble getting this to work due to the end() function not accepting non-variable references, so for anyone else getting the error check this answer https://mcmap.net/q/98794/-only-variables-should-be-passed-by-referenceIndophenol
This is amazing! Is there any way I can change what the breadcrumb says though? Like the file is called "Tos" but I would like the breadcrumbs to say "Terms & Conditions", same goes for the folders. Is there a way I could add another line to the PHP code that calls the variable, checks if the name exists (Checking for "Tos" in my example), and changing it to the new name ("Terms & Conditions in my example) before showing it on the site? Thanks again!Sparry
T
33

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) . ' ');
}
Tizzy answered 7/4, 2010 at 16:39 Comment(0)
O
8

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 = ' &raquo; ', $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"><a href="'.$site.'" rel="v:url" property="v:title">'.$home.'</a>'.$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"><a href="'.$site.'" rel="v:url" property="v:title">'.$link.'</a>'.$sep.'</span>';
    $i++;
}
$bc .=  '</div>';
//Return the result
return $bc;}
Ogdoad answered 28/7, 2012 at 20:47 Comment(0)
H
4

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 '<a href="'.urlencode($str).'" title="'.htmlspecialchars($str).'">'.htmlspecialchars($str).'</a>';
}

(pseudocode)

Horologe answered 7/4, 2010 at 16:51 Comment(0)
T
4

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 https://mcmap.net/q/541898/-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 = ' &raquo; ' , $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("<a href=\"$base\">$home</a>") ;

    // 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[] = "<a href=".$calling_page_path.">".$title."</a>" ;
        }

        // 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>
?>
Theomania answered 7/3, 2013 at 1:16 Comment(0)
G
2

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));
Gurango answered 4/2, 2011 at 10:17 Comment(0)
H
2

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><a href="/'.$url.'">'.ucfirst(str_replace($fixme,$fixes,$trimnames[$i]) . ' ').'</a></li>';
    }
    elseif ($i == $length){
        echo '<li class="current">'.ucfirst(str_replace($fixme,$fixes,$trimnames[$i]) . ' ').'</li>';       
    }
    else{
        echo $trimnames[$i]='<li><a href='.$docroot.' id="bread-home"><span>&nbsp;</span></a></li>';
    }
}
echo '</ol>';
?>
Hancock answered 29/1, 2014 at 4:53 Comment(0)
B
1

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 .= '/';
         }
     }
?>
Biak answered 20/2, 2015 at 13:10 Comment(0)
F
1

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><a href="' . get_site_url() . '">' . $home . '</a></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><a href="'. get_permalink($page) .'">' . $page->post_title . '</a></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>
Fractostratus answered 6/12, 2019 at 13:9 Comment(0)
F
0

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><a href="' . $root_domain . '" title="Home Page"><span>' . $home . '</span></a></li>';
    foreach ($breadcrumbs as $crumb) {
        $link = ucwords(str_replace(array(".php","-","_"), array(""," "," "), $crumb));
        $root_domain .=  $crumb . '/';
        $breadcrumb .= '<li><a href="'. $root_domain .'" title="'.$page_title.'"><span>' . $link . '</span></a></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.

Femur answered 17/11, 2018 at 21:46 Comment(0)
P
0
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 ? '&raquo;' :'');

    $links .= "<a class=\"$clas\" href=\"$value\">$key</a> $sep";
    $count++;

endforeach;

return $links; 

}

Patency answered 27/5, 2020 at 0:11 Comment(2)
This is how i made my own breadcrumb in PHP for more code example you may try codeparl.comPatency
Hope It will solve issue but please add explanation of your code with it so user will get perfect understanding which he/she really wants.Gametogenesis
T
0

I had other requirements and needed a far more flexible solution, a bread crumbs path for a folder 'somewhere' on my web server, which is not within the file structure of my website. Because of this, I can't use most solutions here.

On my Windows machine the path looks like this:

C:\wamp64\www\VIBE\screening_service\public\patients\patient_00005238\screening 20210608_1827

I wanted my breadcrumbs look like this:

public › patients › patient_00005238 › screening 20210608_1827

So, 'public' is the start folder (which I call $baseFolder in my code).

For the displayed text of the thumbs, I can take the URL's which belong to these folders, but I have to leave a part out, (which I will call $baseUrl) in my code. The part I need to leave out:

/VIBE/screening_service/

By later merging $baseUrl '/VIBE/screening_service/' with 'patients/patient_00005238', you can normally create valid links. Not in my case though, because these folders are outside of my website

A web browser will interpret the merged strings

'/VIBE/screening_service/patients/patient_00005238/'

as

'http://localhost:8080//VIBE/screening_service/patients/patient_00005238/'.

In my case I wanted just the crumb path ( like 'patients/patient_00005238' ), which I add to the data attribute of the div of the crumb. I define a Javascript click event and will use the data attribute to reconstruct the real path I need.

Well all this resulted in this function, which might be useful to somebody.

Call it like this

$folder = 'C:\wamp64\www\VIBE\screening_service\public\patients\patient_00005238\screening 20210608_1827';

$baseFolder = 'C:\wamp64\www\VIBE\screening_service\\';
$baseUrl = '/VIBE/screening_service/';

$breadCrumbs = getBreadCrumbs($folder, $baseFolder, $baseUrl, 'crumbs', '&nbsp;&#x203A;&nbsp;', true); 

Note that $baseUrl maps to $baseFolder on the web server.

function getBreadCrumbs(string $folder, string $baseFolder, string $baseUrl, string $cssClassName = '', string $separator = '&nbsp;&#x203A;&nbsp;', bool $returnLinks = true): string
{
    // Start working with the file system folder structure
    
    // Remove the base folder part we do not want to be part of our crumbs 
    $url = str_replace($baseFolder, '', $folder);
    
    // Replace Windows directroy seperators (backward slashes) with forward slashes
    $url = str_replace('\\', DIRECTORY_SEPERATOR, $url);
    
    // Get the crumbs array from this URL 
    $crumbs = array_filter(explode('/', $url));
    
    // How many crumbs have we?
    $crumbCount = count($crumbs);
    
    // We use the CSS class name for styling our crumbs, if it is not empty 
    $cssClass = empty($cssClassName) ? '' : sprintf(' class="%s"', $cssClassName);
    
    // Start building our crumbs trail (a DIV element and add the (optional CSS class) 
    $trail = sprintf('<div%s>', $cssClass) . PHP_EOL;
    
    // Do we want links? If yes, we have to start them with the $baseUrl
    $crumbUrl = $returnLinks ? rtrim($baseUrl, '/') . '/' : '';    
    
    // Iterate through the crumbs
    foreach($crumbs as $i => $crumb)
    {
        // We create a separator, except for the last crumb
        $sep = $i < $crumbCount-1 ? $separator : '';
        
        // Add the crumb to our crumbs trail
        $crumbUrl .= $crumb . '/';
    
        // Do we want links? If yes, create the link part in our HTML
        $html = $returnLinks ? sprintf('<a href="%s">%s</a>', $crumbUrl, $crumb) : $crumb;
        
        // Wrap our link in a DIV element and add a data attribute with the crumb URL (which can be used in Javascript)   
        $html = sprintf('<div data-crumb="%s">%s</div>', $crumbUrl, $html);
        
        // Add the HTML to our crumbs trail
        $trail .=  $html . $sep . PHP_EOL;       
    }

    // End building our crumbs trail        
    $trail .= '</div>' . PHP_EOL;

    return $trail;
}
Tva answered 17/8, 2023 at 12:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.