CodeIgniter Forums
URI class doesn’t recognize #anchors - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forumdisplay.php?fid=23)
+--- Thread: URI class doesn’t recognize #anchors (/showthread.php?tid=10335)



URI class doesn’t recognize #anchors - El Forum - 07-27-2008

[eluser]coolfactor[/eluser]
The URI class doesn't properly recognize/handle anchors in URIs in certain situations.

Here's an illustration using a custom route from an old address, mission.html, to an anchor in CI-powered page, /page/info#mission.

Code:
$route['mission.html'] = 'page/info#mission';

Here's the URI::ruri_string() function:

Code:
function ruri_string()
{
    return '/'.implode('/', $this->rsegment_array()).'/';
}

The ruri_string() function will return "/page/info#mission/", corrupting the anchor reference. Looking at the internal URI::$rsegments array, shows segment 2 being "info#mission".

(One workaround is to precede the hash by a slash, page/info/#mission, but then segment 3 would become "#mission", which is technically incorrect.)

I propose that the URI class parse out the anchor reference to a separate variable, and reapply it as needed. Discussion?


URI class doesn’t recognize #anchors - El Forum - 07-28-2008

[eluser]coolfactor[/eluser]
In my investigation so far, I've narrowed this issue down to Line 260 of the Router::_parse_routes() function:

Code:
$this->_set_request(explode('/', $this->routes[$uri]));

This line executes when there's a literal match to a custom route. It assumes the custom route only contains segments, and ignores the possible existence of anchors.


URI class doesn’t recognize #anchors - El Forum - 07-28-2008

[eluser]coolfactor[/eluser]
My current solution involves intercepting the call to Router::_set_request() with the following:


Code:
function _set_request($segments = array()) {
    if ($seg = array_pop($segments)) {
        $i = strpos($seg, '#');
        if ($i !== FALSE) {
            list($seg, $this->uri->anchor) = explode('#', $seg);
        }
        if ($seg) {
            $segments[] = $seg;
        }
    }
    return parent::_set_request($segments);
}

Basically, it checks to see if "#" exists in the last segment, extracts the anchor name into $this->uri->anchor, restores the last segment without the anchor, and then passes control on to the stock _set_request() function to continue processing.

The code gracefully handles routes with and without a trailing slash:
Code:
/page/info#mission
/page/info/#mission

The URI class would need to be adjusted to utilize the $this->uri->anchor property.