Как получить относительный каталог независимо от того, где он включен в PHP? - PullRequest
13 голосов
/ 19 января 2010

Если это Path_To_DocumentRoot/a/b/c.php, всегда должно быть /a/b.

Я использую это:

dirname($_SERVER["PHP_SELF"])

Но он не будет работать, если он включен другим файлом в другой каталог.

EDIT

Мне нужен относительный путь к корню документа. Используется в веб-приложении.

Я обнаружил, что есть другой вопрос с той же проблемой, но пока нет принятого ответа.

PHP - Преобразовать путь файловой системы в URL

Ответы [ 5 ]

25 голосов
/ 19 января 2010

У вас есть доступ к $_SERVER['SCRIPT_NAME']? Если вы делаете, делаете:

dirname($_SERVER['SCRIPT_NAME']);

Должно работать. В противном случае сделайте это:

В PHP <5.3: </strong>

substr(dirname(__FILE__), strlen($_SERVER['DOCUMENT_ROOT']));

Или PHP> = 5,3:

substr(__DIR__, strlen($_SERVER['DOCUMENT_ROOT']));

Возможно, вам потребуется realpath() и str_replace() все \ до /, чтобы сделать его полностью переносимым, например:

substr(str_replace('\\', '/', realpath(dirname(__FILE__))), strlen(str_replace('\\', '/', realpath($_SERVER['DOCUMENT_ROOT']))));
9 голосов
/ 19 января 2010

PHP <5.3: </p>

dirname(__FILE__)

PHP> = 5.3:

__DIR__

EDIT:

Вот код для получения пути включенного файла относительно пути запуска php-файла:

    $thispath = explode('\\', str_replace('/','\\', dirname(__FILE__)));
    $rootpath = explode('\\', str_replace('/','\\', dirname($_SERVER["SCRIPT_FILENAME"])));
    $relpath = array();
    $dotted = 0;
    for ($i = 0; $i < count($rootpath); $i++) {
        if ($i >= count($thispath)) {
            $dotted++;
        }
        elseif ($thispath[$i] != $rootpath[$i]) {
            $relpath[] = $thispath[$i]; 
            $dotted++;
        }
    }
    print str_repeat('../', $dotted) . implode('/', array_merge($relpath, array_slice($thispath, count($rootpath))));
1 голос
/ 07 июня 2017

Я знаю, что это старый вопрос, но решения, предложенные с использованием DOCUMENT_ROOT, предполагают, что структура веб-папок отражает структуру папок сервера. У меня есть ситуация, когда это не так. Мое решение заключается в следующем. Вы можете выяснить, как адрес сервера сопоставляется с веб-адресом, если у вас есть пример из тех же папок сопоставленной области. Пока корневой php-файл, включающий этот файл, находится в той же отображаемой области, у вас есть пример.

$ _ SERVER ['SCRIPT_FILENAME'] - это адрес сервера этого файла, а $ _SERVER ['PHP_SELF'] - относительная веб-версия. Учитывая эти два, вы можете определить, какая веб-относительная версия вашего файла, по адресу сервера (__FILE__) следующим образом.

function getCurrentFileUrl() {
    $file = __FILE__;
    $script = $_SERVER['SCRIPT_FILENAME'];
    $phpself = $_SERVER['PHP_SELF'];

    // find end of section of $file which is common to $script
    $i = 0;
    while($file[$i] == $script[$i]) {
        $i++;
    }
    // remove end section of $phpself that is the equivalent to the section of $script not included in $file. 
    $phpself = substr($phpself, 0, strlen($phpself)-(strlen($script)-$i));
    // append end section of $file onto result
    $phpself .= substr($file, $i, strlen($file)-$i);

    // complete address 
    return $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_NAME'].$phpself;
}
0 голосов
/ 16 августа 2018

Вот функция общего назначения, чтобы получить относительный путь между двумя путями.

/**
 * Return relative path between two sources
 * @param $from
 * @param $to
 * @param string $separator
 * @return string
 */
function relativePath($from, $to, $separator = DIRECTORY_SEPARATOR)
{
    $from   = str_replace(array('/', '\\'), $separator, $from);
    $to     = str_replace(array('/', '\\'), $separator, $to);

    $arFrom = explode($separator, rtrim($from, $separator));
    $arTo = explode($separator, rtrim($to, $separator));
    while(count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0]))
    {
        array_shift($arFrom);
        array_shift($arTo);
    }

    return str_pad("", count($arFrom) * 3, '..'.$separator).implode($separator, $arTo);
}

Примеры

relativePath('c:\temp\foo\bar', 'c:\temp');              // Result: ../../
relativePath('c:\temp\foo\bar', 'c:\\');                 // Result: ../../../
relativePath('c:\temp\foo\bar', 'c:\temp\foo\bar\lala'); // Result: lala
0 голосов
/ 04 декабря 2015

Я должен был создать что-то, что вам нужно, так вот результат. Задав базовый каталог, вы получите относительный путь к файлу, начиная с базового каталога. Функция довольно быстрая, 100 000 проверок заняли 0,64 с. на моем сервере. И это работает как для каталогов, так и для файлов. Это совместимо с Linux. Даже не пытайтесь это сделать на Windows :)

     /**
     * Return a relative path to a file or directory using base directory. 
     * When you set $base to /website and $path to /website/store/library.php
     * this function will return /store/library.php
     * 
     * Remember: All paths have to start from "/" or "\" this is not Windows compatible.
     * 
     * @param   String   $base   A base path used to construct relative path. For example /website
     * @param   String   $path   A full path to file or directory used to construct relative path. For example /website/store/library.php
     * 
     * @return  String
     */
    function getRelativePath($base, $path) {
        // Detect directory separator
        $separator = substr($base, 0, 1);
        $base = array_slice(explode($separator, rtrim($base,$separator)),1);
        $path = array_slice(explode($separator, rtrim($path,$separator)),1);

        return $separator.implode($separator, array_slice($path, count($base)));
    }

Использование

Вам необходимо получить относительный путь к файлу /var/www/example.com/media/test.jpg Ваш базовый путь /var/www/example.com

Используйте функцию следующим образом:

$relative = getRelativePath('/var/www/example.com','/var/www/example.com/media/test.jpg');

Функция вернет /media/test.jpg.

Если вам нужна только часть /media без файла, используйте ее следующим образом:

$relative = dirname(getRelativePath('/var/www/example.com','/var/www/example.com/media/test.jpg'));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...