Welcome Guest, Not a member yet? Register   Sign In
trailing slash problem [Solved]
#1

[eluser]fchristant[/eluser]
hi,

I'm having somewhat of a complex URL problem. Let's start with the use case, this URL:

mydomain.com/user/19/gallery

...will display a list of images uploaded by user 19. The urls for the images on the page are calculated relative to the current URL (I'm not using things like "site_url"). Since there are tons of links on such a page, this keeps my HTML quite a bit shorter. A typical image URL on the page would be:

image/143

This is working fine, however, if I append a slash to the gallery page:

mydomain.com/user/19/gallery/

...things start to go wrong, the relative links now have the wrong URL:

user/image/143

...which breaks. Obviously I need to get rid of the "user/" part.

I am using URI routing, although I don't think that's the problem. Here's an example rule:

$route['image/(:any)'] = "image/view/$1";

My base URL is configured correctly, I'm sure of that (it has a trailing slash).

Now for the final part, the way I am calculating "how relative" the current URL is from the base_url:

Code:
$segments = $this->uri->total_segments();
$path = '';
switch ($segments) {
   case 1: $path = './'; break;
   case 2: $path = '../'; break;
   case 3: $path = '../../'; break;
   case 4: $path = '../../../'; break;
   default: $path = '';
}
$this->basepath = $path;

I know, I really should write that in a loop someday. Anyway, $this->basepath is what I prepend before all relative links on my views, like so:

Code:
$this->basepath . 'image/' . $row['image_id']

Here's what's going wrong: when there is a trailing slash in the URL, it is not counted as an extra segment, whilst in my scenario it should because of the calculation of the nesting. I tried to detect if the current URL has a trailing slash using current_url, but that doesn't work, it seems to return a URL of which the trailing slash is removed. Counting the URI segments does not work either, the trailing slash is not counted.

I'm hoping to solve this in a simple way in CI. In the URI manual I see there are special "r" functions for when one uses URI routing but I do not understand them, all they do is add a slash, even when there isn't one in the actual URL. Is there something I should do in the routing table? Or should I mess around with .htaccess files?

So many buttons to push :-)

Thanks in advance for any help!
#2

[eluser]fchristant[/eluser]
Ok, I'll hereby answer my own question. I managed to get it to work using the method below:

Code:
function initbasepath() {
        
// this function calculates how deep the current URI is compared to the base URI
// and returns a path from the current URI towards the base path
// the result can be used to create relative links that work no matter how
// deep the current URI is.
        
// the current URL
$uri = $this->uri->uri_string();

// check if the current URL ends with a slash
$trailingslash = substr($uri,strlen($uri)-1,1)== '/' ? true : false;
// count the number of segments in the URL, depending on the trailing slash
$segments = ($trailingslash) ? $this->uri->total_segments() + 1 : this->uri->total_segments() ;
// calculate path towards base URL based on #segments
$path = '';
if ($segments==1) {
   $path='./';
} else {
   for ($i=0;$i<$segments-1;$i++) {
      $path .= '../';
   }
}
        
// set the basepath parameter, this can be used on all views to prepend links
$this->basepath = $path;
}

This method is part of my base controller, which extends all my controllers. The function is quite useful. I can simply prepend $this->basepath to all links in my views, it will always have the correct relative path to the base url, no matter how deep the nesting of the current URL and no matter the trailing slash or not.

There is obviously nothing wrogn with using CI's base_url() either, it's just that I wanted to use relative links, not absolute ones. This also saves quite a lot of HTML chars and thus bandwidth.
#3

[eluser]Colin Williams[/eluser]
Why do you insist on a relative path? There are functions like base_path() to guide you along, and you can always create config items when you need to

Code:
<image src="&lt;?= config_item('image_path') . $image->filename ?&gt;" alt="" />

(used <image> tag because the forum filter gobbles up < i m g > tags)

So, take your pick: A simple configuration item; A 12-line function
#4

[eluser]fchristant[/eluser]
Colin,

Your suggestions only work when you want absolute URLs, not relative ones. I am insisting on relative links because they bring much shorter HTML to the table, i.e. ../image/12 instead of http://www.mydomain.com/image/12.

I figure most CI users would not care about such an optimization but I do since scalability for the project I am working on is important. Bandwidth equals costs. Since a single page can quite easily result in about a hundred links, I can cut out a few Kb per request. A small saving, but not when you multiply that with an insane amount of requests.
#5

[eluser]Colin Williams[/eluser]
Your config could hold something like "/images/" or "/". You don't need the whole domain in there.
#6

[eluser]helmutbjorg[/eluser]
Quite right. My base url only contains "/". Which is useful also for your 'scalability' issues when it comes time to work with multiple mirrors of the same site.
#7

[eluser]fchristant[/eluser]
Thanks for the suggestions guys, but I still don't see it working:

- When I would put '/' in my config it will not work because I am using a deployment path that is multiple levels deep. '/' will then resolve to the nesting that is one level too high.

- will '/' work correctly for both kinds of urls, ones with a trailing slash and ones without?

I do understand where you are getting at though, I'm going to try putting something like '/myappdir/' in my config.
#8

[eluser]Colin Williams[/eluser]
Any path beginning with a "/" will resolve back to the domain (unless tomorrow all browsers decide to handle it differently Smile)

Code:
"/" == "http://www.example.com/"
"/dir" == "http://www.example.com/dir"
"/dir/file.ext" == "http://www.example.com/dir/file.ext"
etc..
#9

[eluser]fchristant[/eluser]
Thanks Colin,

I am aware of what '/' does, and now see how my solution is perhaps a bit over the top. The only reason that remains to have such a basepath function is that you can easily move pages across directories and play with URI routing without your links getting broken.

Once an application is stable though, that should not really happen anyway, and the fixed basepath is way better, which is what I will use Smile




Theme © iAndrew 2016 - Forum software by © MyBB