One path, but hide link per page is different

I have a menu like this, its in header.php (I else footer.php):


<div id="menu">
   <ul>                                                                       
       <li class="selected hover"><a href="user/welcome">Home</a></li>
       <li class="hover"><a href="user/about">About</a></li>
       <li class="hover"><a href="user/specials">Specials</a></li>
       <li class="hover"><a href="user/account">Account</a></li>
       <li class="hover"><a href="user/register">Register</a></li>
       <li class="hover"><a href="user/price">Price</a></li>
       <li class="hover"><a href="user/contact">Contact</a></li>
   </ul>
</div> <!-- end .menu -->  

In the home page (index.php), I include header.php and footer.php into one, and menu above works normal. But, when I click About link or other link (sure header.php and footer.php is included), in the about page, hover About, Specials … I receive some hide link (or url) like http://localhost/demo/foods/user/user/about, http://localhost/demo/foods/user/user/specials. I don’t want to them, I want http://localhost/demo/foods/user/about …, css and jquery are not working too. Have anyone know why? Thank you!

It would be better for your links to have a root relative URL so that the links don’t break, because they are relative to the current page location at the moment, so if you hover one of those links on a page that is already in the /uers/ directory, you’ll get the URLs you posted above, which is wrong. Something like this would be better:

<a href=“/demo/foods/user/about”>About</a>

But that will only work if you have a local server environment set up. It will also break things when you put this code online. So when building locally, it’s better to set up your local environment to reflect the online environment by modifying your hosts file.

It’s also ver inefficient to have the “hover” class on each LI like that. It would be better to target those LIs with #menu li instead, and not use the hover class at all.

Can you resolve that problem with CodeIgniter? I see the same problem with CI.

I would presume so, but I don’t know it well enough. You might need to give us some more information about your setup.

I give some information about project without CI, here is my .htaccess:


RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l

RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]

ErrorDocument 404 /view/shared/error/404.php

index.php


<?php
    require_once 'core/loader.php';
    require_once 'core/controller.php';
    
    $loader = new loader($_GET['url']);
    $controller = controller::getInstance($loader->controller, $loader->action);
    
    include "view/user/include/header.php";
    $controller->request();
    $controller->render();
    include "view/user/include/footer.php";
?>

url’s form: localhost/dpfoods/controller_name/method_name?id=
I take controller_name, method_name by explode function and pass them to loader class. The loader class will select controller and then controller will select function.

in index.php (default page, menu above displays normal):
// main menu
Home >> About >> …
Home - localhost/dpfoods/user/welcome
About - localhost/dpfoods/user/about

but in other page, apple details page example:
// main menu
Home >> About >> …
Home - localhost/dpfoods/user/user/welcome
About - localhost/dpfoods/user/user/about

// other menu
Home >> Fruits and vegetables >> apple
if true:
Home - localhost/dpfoods/user/welcome
Fruits and vegetables - localhost/dpfoods/user/category?id-category=4
apple - localhost/dpfoods/user/details?id-product=25
// but all hide links in this menu are the same
localhost/dpfoods/user/details?id-product=25

Structure folder:

This is a problem that has been bugging me for years and I solved it site by site. Now I’ve come up with a generic solution which works on my LAMP server as well as on OSX. I would be interested to know if it works in other environments.

<?php

function offset2root() {

    $phpSelf = explode('/', $_SERVER['PHP_SELF']);
    $scriptFilename = explode('/', $_SERVER['SCRIPT_FILENAME']);
    $root = array_intersect($phpSelf, $scriptFilename);
    $count = count($root);
    $offset = '';
    while ($count-- > 2) {
        $offset .= '../';
    }
    if(empty($offset)) {
        return './';
    } else {
        return $offset;
    }

}

$offset = offset2root();

echo "<a href='{$offset}path/to/file.php'>file.php</a>";

?>

Thanks so much! I’ll try it and post the result later.

My first try didn’t work as expected. I think this one does. :smiley:

<?php

################################################################
#                                                              #
#  depending on how you organize your files you might have to  #
#  adjust the offsets in                                       #
#  $count = count($scriptFilename) - $foundOSX - 3;            #
#  and in                                                      #
#  $count = count($scriptFilename) - $foundLAMP - 2;           #
#                                                              #
################################################################

function offset2root() {

    $scriptFilename = explode('/', $_SERVER['SCRIPT_FILENAME']);
    $foundOSX  = array_search('Sites', $scriptFilename);
    $foundLAMP = array_search('public_html', $scriptFilename);
    if($foundOSX  !== FALSE) {
        $count = count($scriptFilename) - $foundOSX - 3;
    } elseif ($foundLAMP !== FALSE) {
        $count = count($scriptFilename) - $foundLAMP - 2;
    } else {
        return './';
    }

    $offset = '';
    while ($count-- > 0) {
        $offset .= '../';
    }
    if(empty($offset)) {
        return './';
    } else {
        return $offset;
    }

}

$link = offset2root();

echo "<a href='{$link}path/to/file.php'>Menu Item</a>";

?>

Could you tell me how does your code work? At first glance, looks your code, it seems being used to include file. Right now, I knew my problem and I should make absolute link.

Sure! The code calculates the offset between the domain root and the file calling the function.

On a LAMP server the domain html base is at “public_html”:

/home/user/public_html/some_folder/another_folder/script.php

On an OSX Mac the domain html base is at “Sites”:

/127.0.0.1/_user/Sites/some_folder/another_folder/script.php

First the function finds the domain html base: “public_html” or “Sites”

$scriptFilename = explode('/', $_SERVER['SCRIPT_FILENAME']);
$foundOSX  = array_search('Sites', $scriptFilename);
$foundLAMP = array_search('public_html', $scriptFilename);

Next the function calculate the offset between the domain html base and calling script (plus or minus an adjustmet as needed). Either

$foundOSX or $foundLAMP

has the location of the domain html base while

count($scriptFilename)

has the location of the calling script.

If a base is not found the function returns ‘./’ (no offset):

if($foundOSX  !== FALSE) {
    $count = count($scriptFilename) - $foundOSX - 3;
} elseif ($foundLAMP !== FALSE) {
    $count = count($scriptFilename) - $foundLAMP - 2;
} else { 
    return './';
}

If a base is found the function returns the proper number of ‘…/’ to reach the domain html base:

$offset = '';
while ($count-- > 0) {
    $offset .= '../';
}
if(empty($offset)) {
    return './';
} else {
    return $offset;
}

To see it more graphically add the following to the top of the function. It will show the array the function works with:

echo "\\$_SERVER['SCRIPT_FILENAME']= {$_SERVER['SCRIPT_FILENAME']}<br>\
";
$scriptFilename = explode('/', $_SERVER['SCRIPT_FILENAME']);
echo "scriptFilename= \
<pre>\
";
print_r ($scriptFilename);
echo "</pre>\
";

The reason I use the extra offset on the Mac is because I work on multiple domains

/127.0.0.1/_user/Sites/domain-1.com/
/127.0.0.1/_user/Sites/domain-2.com/
/127.0.0.1/_user/Sites/domain-3.com/

making each domain’s base one deeper than "Sites’

@captainccs I work on XAMPP server as well as on Windows 8. Look again my index.php:


<?php 
    require_once 'core/loader.php'; 
    require_once 'core/controller.php'; 
     
    $loader = new loader($_GET['url']); 
    $controller = controller::getInstance($loader->controller, $loader->action); 
     
    include "view/user/include/header.php"; 
    $controller->request(); 
    $controller->render(); 
    include "view/user/include/footer.php"; 
?>

and my url form: localhost/dpfoods/controller_name/method_name?id=. The fisrt thing, header and footer is always putted on index file (see my structure folder), if I remove controller_name in url, it’s mean url’s form: localhost/dpfoods/method_name?id= and have no problem. Contrary, If I don’t remove controller_name and then when I click link about, contact … (not home), css and image path doesn’t work. What’s difference?