9

(Preliminary note: There are seemingly many variants of this question already here, but they all seem to focus on the filesystem location of the physical PHP files themselves, not the web URL location of things, which is what I'm after.)


INTRO 1:

I have a small "website" with the following physical filesystem structure:

variable.php folder test.php 

(In other words, variable.php in the top-level, and test.php in the folder folder.)

Here are the file contents:

<?php //variable.php $basePath = dirname($_SERVER['SCRIPT_NAME']); ?> <?php //test.php include("../variables.php"); echo $basePath; ?> 

INTRO 2:

When developing this "website" locally, it is on this address:

http://localhost/~noob/test-website 

QUESTION:

The problem is that if I put http://localhost/~noob/test-website/folder/test.php into my browser, it prints out /~noob/test-website/folder/.

I want it to print out /~noob/test-website (the "web location" of variable.php). In other words, I want to have global access from all files, even ones deeper in the filesystem hierarchy, to /~noob/test-website. How do I accomplish this?

I obviously do not want to hardcode this path in. The reason is that when I upload it onto a production server, the location changes to something more sane like http://example.com/ (and I don't want to have to modify this hardcoded path after uploading to the server, hence this question of course).

4
  • Are you doing this for including files, or something else? Commented Oct 14, 2012 at 22:34
  • @ZachRattner I'm doing this to (possibly among other things) properly refer to CSS files within my HTML files. Navigating around with ".." doesn't work too well when you're using mod_rewrite to rewrite URLs. That tends to fool the default mechanism into believing you are in a folder that doesn't really exist (since mod_rewrite can create fake "folders"). Having a global "base" path solves this problem. The only problem is that it's currently hardcoded. I want to remove that annoying hardcoded path and make it general. Commented Oct 14, 2012 at 22:38
  • @NoobOverflow I noticed your bounty; mine and Leigh's answer are slightly different approaches to the same end. If Leigh's answer works for you then great, but otherwise please post the values mentioned in my comment on my answer and I'll adjust accordingly. Commented Oct 18, 2012 at 15:06
  • Just define a base url path variable, which you pass as hardcoded to javascript when generating pages. Or don't pass it to javascript if not doing stuff dynamically after load, and prepend it for each js or css url (also, all js and css urls must start with /). Commented Oct 24, 2012 at 15:07

10 Answers 10

4

The problem here is, that your webserver (and thus PHP) does not know that your testing root directory is being served out of a subdirectory, and in fact neither of them care.

The obvious solution would be to provide a configuraiton script on each server, that has the hardcoded relative root in it. As you already stated, you don't want to do this. (It's not actually a bad thing to provide server-specific configuration files, lots of people do far more absurd things)

In order to get around this fact, a solution will have to hinge on the reference points that are available to it for a specific request. Those reference points are:

  • The filesystem location of variables.php
  • The filesystem location of the script being requested.
  • The filesystem location that is the root that pages are served from

(I know you've emphasised not filesystem - keep reading, we use these to get your value)

With these values, there will be an overlap in the directory structure. This is the value you are after.

Example:

  • Your test site is at: http://localhost/c/
  • Request: http://localhost/c/d/myscript.php
  • variables.php is at: /a/b/c/variables.php
  • myscript.php is at: /c/d/myscript.php includes ../variables.php

As you can see the paths overlap by the /c/ directory.

In your variables.php you can use the following code to calculate that overlap.

$fsRoot = __DIR__; // dirname(__FILE__) for PHP < 5.3 (and shame on you!) $webRoot = str_replace($_SERVER['PHP_SELF'], '', $_SERVER['SCRIPT_FILENAME']); $urlRoot = str_replace($webRoot, '', $fsRoot); 

You should never rely on DOCUMENT_ROOT it can very easily be incorrect, so we're calculating it ourself ($webRoot variable).

This takes the filesystem directory of variables.php which is in your site root, and removes the the filesystem directory that is the base that pages are served from. What remains is everything that was between the actual web root, and your subdirectory web root.

In myscript.php you can do the following.

print $urlRoot . '/filename.js'; 

The output from the example would be /c/filename.js

Sign up to request clarification or add additional context in comments.

Comments

3

Hopefully this will come close (all this should be in variables.php):

// folder containing the requested script $requested = dirname($_SERVER['SCRIPT_FILENAME']); // folder containing variables.php $current = dirname(__FILE__); // relative path from variables.php to the requested script $relative = str_replace($current, '', $requested); // remove relative path from end of script name $pattern = '#' . preg_quote($relative) . '$#'; $basePath = preg_replace($pattern, '', dirname($_SERVER['SCRIPT_NAME'])); 

Note: This looks like it will work for your particular example, but this means that variables.php must always be in a folder either at, or a parent of, the DOCUMENT_ROOT, otherwise the relative path can't be determined using the above.

2 Comments

That didn't work, $basePath ended up being exactly the same as in my question.
If for some reason $pattern didn't match, then it falls back to the same as what you had originally; how about you show us the output of var_dump($current, $requested, $relative, $pattern); so we can debug your scenario.
1

I'm not sure it's gonna solve your problem forever or not, however it works in your example:

$x = explode("/", $_SERVER['SCRIPT_NAME']); echo $_SERVER['SERVER_NAME'] . '/' . $x[1] . '/'; 

If you like the output, you may customize it to fit your needs. :)

Comments

1

It's not entirely foolproof, but the solution used by Kurogo works in most cases.

https://github.com/modolabs/Kurogo-Mobile-Web/blob/release-1.5/lib/Kurogo.php#L797

It's basically comparing the REQUEST_URI and the DOCUMENT_ROOT, and keeps adding folders from the REQUEST_URI to the DOCUMENT_ROOT until it gets a match. Once it finds WEBROOT_DIR (which in your case would probably be a dirname(__FILE__) from the variables.php) by building up from DOCUMENT_ROOT, it saves the existing path as your $urlBase.

This only works for subfolders/symlinks, and doesn't handle things like apache aliasing, so it may not work for your case specifically, but it's at least part of the answer.

Comments

0

I worked in a project where it was necesary to read a directory with a lot of images, with folders within, and it was required to read all the files in a recursive way...

Function:

function ListIn($dir, $prefix = '') { $dir = rtrim($dir, '\\/'); $result = array(); foreach (scandir($dir) as $f) { if ($f !== '.' and $f !== '..') { if (is_dir("$dir/$f")) { $result = array_merge($result, ListIn("$dir/$f", "$prefix$f/")); } else { $ext = substr($prefix.$f, strrpos($prefix.$f, '.') + 1); if(in_array($ext, array("jpg"))){ // echo $prefix.$f."<br>"; $result[] = $prefix.$f; } } } } return $result; } 

Way of use:

$path='images/mytest'; $images = (ListIn($path)); foreach($images as $image){ $image=explode("/",$image); echo $image=$image[2]; } 

As you can see, every single image becomes an array, and you can access to the first elements of that array, in order to extract the directory you want... In this case it was located at the second index of the array, depending on the deepness of your file structure...

I hope this can help you out!

Comments

0

I obviously do not want to hardcode this path in. The reason is that when I upload it onto a production server, the location changes to something more sane like http://example.com/ (and I don't want to have to modify this hardcoded path after uploading to the server, hence this question of course).

You can hardcode paths, just make it relative to the homepage.

For example, http://localhost/~noob/test-website/ and http://example.com are the same thing. so only worry about things underneath that .

Comments

0

(Preliminary note: There are seemingly many variants of this question already here, but they all seem to focus on the filesystem location of the physical PHP files themselves, not the web URL location of things, which is what I'm after.)

[HR][/HR]INTRO 1:

I have a small "website" with the following physical filesystem structure:

variable.phpfolder test.php(In other words, variable.php in the top-level, and test.php in the folder folder.) Here are the file contents:

[HR][/HR]INTRO 2:

When developing this "website" locally, it is on this address:

http://localhost/~noob/test-website[HR][/HR]QUESTION:

The problem is that if I put

localhost/~noob/test-website/folder/test.php into my browser, it prints out /~noob/test-website/folder/.

I want it to print out /~noob/test-website (the "web location" of variable.php). In other words, I want to have global access from all files, even ones deeper in the filesystem hierarchy, to /~noob/test-website. How do I accomplish this?

I obviously do not want to hardcode this path in. The reason is that when I upload it onto a production server, the location changes to something more sane like http://example.com/ (and I don't want to have to modify this hardcoded path after uploading to the server, hence this question of course).

Comments

0

You can estimate the correct answer based on your knowledge of your specific folder and web structure, but that is far from a general solution. But I would recommend you to use a boostrap file that is the entry point for each "page". There you can setup you $basePath variable and other needed values.

Another thing you could do is inject the base path to your $_SERVER array from Apache (if that is what you are using. It would then be available to your entire application.

For a pointer on how to accomplish this you can look here.

Or have a config file containing the base path for a given server.

Comments

-1

I think, you're searching the docroot (form outside) - it can be found in $_SERVER['DOCUMENT_ROOT'] (in the filesystem) & compare with __DIR__ (or dirname(__FILE__) for earlier PHP)

Comments

-1

Use this function :-

#This function will return the current script name function get_script_name() { $uri_array = explode('/',$_SERVER['SCRIPT_NAME']); $script_name = end($uri_array); return $script_name; } #call The function $script_name = get_script_name(); echo $script_name; 

1 Comment

This function will return the name of the current script file only

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.