简体   繁体   English

绝对与相对路径

[英]Absolute vs. relative paths

If I use absolute paths, I can't move the whole directory to a new location. 如果我使用绝对路径,我无法将整个目录移动到新位置。 If I use relative paths, I can't move individual files to new locations. 如果我使用相对路径,我无法将单个文件移动到新位置。

What's the solution here? 这里有什么解决方案? Do you set up a config file that holds the root path and go from there? 你是否设置了一个包含根路径的配置文件并从那里开始? Or do you have a rule like: Never move files around? 或者你有一个规则:永远不要移动文件?

I've seen in some projects that people use dirname( FILE ). 我在一些项目中看到人们使用dirname( FILE )。 What is the point of that, I mean, why not simply leave it out since the dirname is relative anyway (depending on where the file sits)? 有意义的是,我的意思是,为什么不简单地将它留下来,因为dirname无论如何都是相对的(取决于文件所在的位置)?

you should use a config file that will be included in each file first line, for example your app look like this 你应该使用一个配置文件,它将包含在每个文件的第一行,例如你的应用程序看起来像这样

root / App / Plugins root / App /插件

inside your root dir : app-config.php 你的root目录里面: app-config.php

if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

now, suppose you have to include a plugin file, so 现在,假设你必须包含一个插件文件,所以

inside your Plugin dir : my-plugin.php 在你的插件目录里面: my-plugin.php

require_once '../../app-config.php';

now everything below this line can use ABSPATH 现在这行以下的所有内容都可以使用ABSPATH

example do you want to load an image 例如,您要加载图像吗?

<img src='".ABSPATH."Public/images/demo.png' alt=''/>

now, the thing is more simple if your app is designed to automatically load some files like 现在,如果您的应用程序旨在自动加载某些文件,那么事情会更简单

plugin-widget-1.php

so that everything inside this file or any other file loaded by the my-plugin.php file can use the ABSPATH without include each time the app-config.php file. 因此,每次app-config.php文件时,此文件中的所有内容或my-plugin.php文件加载的任何其他文件都可以使用ABSPATH而不包含。

with this in mind you can have all the short-hand you want into the app-config.php example 考虑到这一点,你可以在app-config.php示例中获得所需的所有简写

define('UPLOAD_PATH', ABSPATH. 'Public/uploads/');
define('IMAGES_PATH', ABSPATH. 'Public/images/');
define('HELPERS_PATH', ABSPATH. 'App/helpers/');
...

so, now that you have all defined, if you need to move a file, let's say one folder forward example: 所以,既然已经全部定义了,如果需要移动文件,让我们说一个文件夹转发示例:

root / App / Plugins / Utils root / App /插件/实用程序

just inlucde require_once '../../../app-config.php'; 只是inlucde require_once '../../../app-config.php'; app-config.php require_once '../../../app-config.php';

obviously i suppose that you are not changing paths each time =) anyway if you need to do so is always more simple to change one file inclusion instead of hundreds. 显然我认为你不是每次都改变路径=)无论如何你需要这样做总是更简单地改变一个文件包含而不是数百。

hope this make sense to you =) 希望这对你有意义=)

I've seen in some projects that people use dirname(FILE). 我在一些项目中看到人们使用dirname(FILE)。 What is the point of that, I mean, why not simply leave it out since the dirname is relative anyway (depending on where the file sits)? 有意义的是,我的意思是,为什么不简单地将它留下来,因为dirname无论如何都是相对的(取决于文件所在的位置)?

It's relative to the include path, anyway. 无论如何,这都与包含路径有关。 The dirname( __FILE__ ) (or just __DIR__ in PHP >= 5.3) is there so you can run the file from every location. dirname( __FILE__ ) __DIR__ dirname( __FILE__ ) (或者只是PHP> = 5.3中的__DIR__ )就在那里,所以你可以从每个位置运行该文件。 In case you're using relative paths, the value "." 如果您使用相对路径,则值为“。”。 may change. 可能会改变。 See: 看到:

berry@berry-pc:~% cat so.php berry @ berry-pc:〜% cat so.php

<?php
var_dump( realpath( '.' ) );
var_dump( realpath( __DIR__ ) );

berry@berry-pc:~% php so.php berry @ berry-pc:〜% php so.php

string(11) "/home/berry"
string(11) "/home/berry"

berry@berry-pc:~% cd foo berry @ berry-pc:〜% cd foo

berry@berry-pc:~/foo% php ../so.php berry @ berry-pc:〜/ foo% php ../so.php

string(15) "/home/berry/foo"
string(11) "/home/berry"

So, it is relative, but it's relative to the current working directory, not to the directory the file is located in. That's why you'll want to use __DIR__ for this. 因此,它是相对的,但它相对于当前的工作目录,而不是文件所在的目录。这就是为什么你要为此使用__DIR__ And by the way; 顺便说一下; yes, I don't move files around an awful lot. 是的,我不会移动文件很多。 If I do though, I'll have to update every call to that file, although I don't require or include an awful lot anymore, since I'm using an Autoloader . 如果我这样做,我将不得不更新对该文件的每次调用,虽然我不再需要或包含很多,因为我正在使用自动加载器

As for the other files I'm referring to (such as template files), I set the path manually, but once . 至于我所指的其他文件(例如模板文件),我手动设置路径,但是一次 I then refer to $path . '/filename.php'; 然后我引用$path . '/filename.php'; $path . '/filename.php'; , so it's easier to change later. ,所以以后更容易更改。

I always use absolute paths, but I also start any custom PHP project with a bootstrap file where I define the most commonly used paths as constants, based on values extracted from $_SERVER . 我总是使用绝对路径,但我也启动任何带有引导文件的自定义PHP项目,其中我根据从$_SERVER提取的值将最常用的路径定义为常量。

This is how I define my root paths : 这是我定义根路径的方式:

define("LOCAL_PATH_ROOT", $_SERVER["DOCUMENT_ROOT"]);
define("HTTP_PATH_ROOT", isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : (isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : '_UNKNOWN_'));

The path LOCAL_PATH_ROOT is the document root. 路径LOCAL_PATH_ROOT是文档根。 The path HTTP_PATH_ROOT is the equivalent when accessing the same path via HTTP. 当通过HTTP访问相同路径时,路径HTTP_PATH_ROOT是等效的。

At that point, converting any local path to an HTTP path can be done with the following code : 此时,可以使用以下代码将任何本地路径转换为HTTP路径:

str_replace(LOCAL_PATH_ROOT, RELATIVE_PATH_ROOT, $my_path)

If you want to ensure compatibility with Windows based servers, you'll need to replace the directory seperator with a URL seperator as well : 如果要确保与基于Windows的服务器兼容,则还需要使用URL分隔符替换目录分隔符:

str_replace(LOCAL_PATH_ROOT, RELATIVE_PATH_ROOT, str_replace(DIRECTORY_SEPARATOR, '/', $my_path))

Here's the full bootstrap code that I'm using for the PHP PowerTools boilerplate : 这是我用于PHP PowerTools样板的完整引导代码:

defined('LOCAL_PATH_BOOTSTRAP') || define("LOCAL_PATH_BOOTSTRAP", __DIR__);

// -----------------------------------------------------------------------
// DEFINE SEPERATOR ALIASES
// -----------------------------------------------------------------------
define("URL_SEPARATOR", '/');
define("DS", DIRECTORY_SEPARATOR);
define("PS", PATH_SEPARATOR);
define("US", URL_SEPARATOR);

// -----------------------------------------------------------------------
// DEFINE ROOT PATHS
// -----------------------------------------------------------------------
define("RELATIVE_PATH_ROOT", '');
define("LOCAL_PATH_ROOT", $_SERVER["DOCUMENT_ROOT"]);
define("HTTP_PATH_ROOT",
        isset($_SERVER["HTTP_HOST"]) ?
        $_SERVER["HTTP_HOST"] : (
        isset($_SERVER["SERVER_NAME"]) ?
        $_SERVER["SERVER_NAME"] : '_UNKNOWN_'));

// -----------------------------------------------------------------------
// DEFINE RELATIVE PATHS
// -----------------------------------------------------------------------
define("RELATIVE_PATH_BASE",
        str_replace(LOCAL_PATH_ROOT, RELATIVE_PATH_ROOT, getcwd()));
define("RELATIVE_PATH_APP", dirname(RELATIVE_PATH_BASE));
define("RELATIVE_PATH_LIBRARY", RELATIVE_PATH_APP . DS . 'vendor');
define("RELATIVE_PATH_HELPERS", RELATIVE_PATH_BASE);
define("RELATIVE_PATH_TEMPLATE", RELATIVE_PATH_BASE . DS . 'templates');
define("RELATIVE_PATH_CONFIG", RELATIVE_PATH_BASE . DS . 'config');
define("RELATIVE_PATH_PAGES", RELATIVE_PATH_BASE . DS . 'pages');
define("RELATIVE_PATH_ASSET", RELATIVE_PATH_BASE . DS . 'assets');
define("RELATIVE_PATH_ASSET_IMG", RELATIVE_PATH_ASSET . DS . 'img');
define("RELATIVE_PATH_ASSET_CSS", RELATIVE_PATH_ASSET . DS . 'css');
define("RELATIVE_PATH_ASSET_JS", RELATIVE_PATH_ASSET . DS . 'js');

// -----------------------------------------------------------------------
// DEFINE LOCAL PATHS
// -----------------------------------------------------------------------
define("LOCAL_PATH_BASE", LOCAL_PATH_ROOT . RELATIVE_PATH_BASE);
define("LOCAL_PATH_APP", LOCAL_PATH_ROOT . RELATIVE_PATH_APP);
define("LOCAL_PATH_LIBRARY", LOCAL_PATH_ROOT . RELATIVE_PATH_LIBRARY);
define("LOCAL_PATH_HELPERS", LOCAL_PATH_ROOT . RELATIVE_PATH_HELPERS);
define("LOCAL_PATH_TEMPLATE", LOCAL_PATH_ROOT . RELATIVE_PATH_TEMPLATE);
define("LOCAL_PATH_CONFIG", LOCAL_PATH_ROOT . RELATIVE_PATH_CONFIG);
define("LOCAL_PATH_PAGES", LOCAL_PATH_ROOT . RELATIVE_PATH_PAGES);
define("LOCAL_PATH_ASSET", LOCAL_PATH_ROOT . RELATIVE_PATH_ASSET);
define("LOCAL_PATH_ASSET_IMG", LOCAL_PATH_ROOT . RELATIVE_PATH_ASSET_IMG);
define("LOCAL_PATH_ASSET_CSS", LOCAL_PATH_ROOT . RELATIVE_PATH_ASSET_CSS);
define("LOCAL_PATH_ASSET_JS", LOCAL_PATH_ROOT . RELATIVE_PATH_ASSET_JS);

// -----------------------------------------------------------------------
// DEFINE URL PATHS
// -----------------------------------------------------------------------
if (US === DS) { // needed for compatibility with windows
    define("HTTP_PATH_BASE", HTTP_PATH_ROOT . RELATIVE_PATH_BASE);
    define("HTTP_PATH_APP", HTTP_PATH_ROOT . RELATIVE_PATH_APP);
    define("HTTP_PATH_LIBRARY", false);
    define("HTTP_PATH_HELPERS", false);
    define("HTTP_PATH_TEMPLATE", false);
    define("HTTP_PATH_CONFIG", false);
    define("HTTP_PATH_PAGES", false);
    define("HTTP_PATH_ASSET", HTTP_PATH_ROOT . RELATIVE_PATH_ASSET);
    define("HTTP_PATH_ASSET_IMG", HTTP_PATH_ROOT . RELATIVE_PATH_ASSET_IMG);
    define("HTTP_PATH_ASSET_CSS", HTTP_PATH_ROOT . RELATIVE_PATH_ASSET_CSS);
    define("HTTP_PATH_ASSET_JS", HTTP_PATH_ROOT . RELATIVE_PATH_ASSET_JS);
} else {
    define("HTTP_PATH_BASE", HTTP_PATH_ROOT .
            str_replace(DS, US, RELATIVE_PATH_BASE));
    define("HTTP_PATH_APP", HTTP_PATH_ROOT .
            str_replace(DS, US, RELATIVE_PATH_APP));
    define("HTTP_PATH_LIBRARY", false);
    define("HTTP_PATH_HELPERS", false);
    define("HTTP_PATH_TEMPLATE", false);
    define("HTTP_PATH_CONFIG", false);
    define("HTTP_PATH_PAGES", false);
    define("HTTP_PATH_ASSET", HTTP_PATH_ROOT .
            str_replace(DS, US, RELATIVE_PATH_ASSET));
    define("HTTP_PATH_ASSET_IMG", HTTP_PATH_ROOT .
            str_replace(DS, US, RELATIVE_PATH_ASSET_IMG));
    define("HTTP_PATH_ASSET_CSS", HTTP_PATH_ROOT .
            str_replace(DS, US, RELATIVE_PATH_ASSET_CSS));
    define("HTTP_PATH_ASSET_JS", HTTP_PATH_ROOT .
            str_replace(DS, US, RELATIVE_PATH_ASSET_JS));
}

// -----------------------------------------------------------------------
// DEFINE REQUEST PARAMETERS
// -----------------------------------------------------------------------
define("REQUEST_QUERY",
        isset($_SERVER["QUERY_STRING"]) && $_SERVER["QUERY_STRING"] != '' ?
        $_SERVER["QUERY_STRING"] : false);
define("REQUEST_METHOD",
        isset($_SERVER["REQUEST_METHOD"]) ?
        strtoupper($_SERVER["REQUEST_METHOD"]) : false);
define("REQUEST_STATUS",
        isset($_SERVER["REDIRECT_STATUS"]) ?
        $_SERVER["REDIRECT_STATUS"] : false);
define("REQUEST_PROTOCOL",
        isset($_SERVER["HTTP_ORIGIN"]) ?
        substr($_SERVER["HTTP_ORIGIN"], 0,
        strpos($_SERVER["HTTP_ORIGIN"], '://') + 3) : 'http://');
define("REQUEST_PATH",
        isset($_SERVER["REQUEST_URI"]) ?
        str_replace(RELATIVE_PATH_BASE, '',
        $_SERVER["REQUEST_URI"]) : '_UNKNOWN_');
define("REQUEST_PATH_STRIP_QUERY",
        REQUEST_QUERY ?
        str_replace('?' . REQUEST_QUERY, '', REQUEST_PATH) : REQUEST_PATH);

// -----------------------------------------------------------------------
// DEFINE SITE PARAMETERS
// -----------------------------------------------------------------------
define("PRODUCTION", false);
define("PAGE_PATH_DEFAULT", US . 'index');
define("PAGE_PATH",
        (REQUEST_PATH_STRIP_QUERY === US) ?
        PAGE_PATH_DEFAULT : REQUEST_PATH_STRIP_QUERY);

If you add the above code to your own project, outputting all user constants at this point (which can do with get_defined_constants(true) should give a result that looks somewhat like this : 如果将上面的代码添加到您自己的项目中,此时输出所有用户常量(可以使用get_defined_constants(true)应该给出一个看起来像这样的结果:

array (
  'LOCAL_PATH_BOOTSTRAP' => '/var/www/libraries/backend/Data/examples',
  'URL_SEPARATOR' => '/',
  'DS' => '/',
  'PS' => ':',
  'US' => '/',
  'RELATIVE_PATH_ROOT' => '',
  'LOCAL_PATH_ROOT' => '/var/www',
  'HTTP_PATH_ROOT' => 'localhost:8888',
  'RELATIVE_PATH_BASE' => '/libraries/backend/Data/examples',
  'RELATIVE_PATH_APP' => '/libraries/backend/Data',
  'RELATIVE_PATH_LIBRARY' => '/libraries/backend/Data/vendor',
  'RELATIVE_PATH_HELPERS' => '/libraries/backend/Data/examples',
  'RELATIVE_PATH_TEMPLATE' => '/libraries/backend/Data/examples/templates',
  'RELATIVE_PATH_CONFIG' => '/libraries/backend/Data/examples/config',
  'RELATIVE_PATH_PAGES' => '/libraries/backend/Data/examples/pages',
  'RELATIVE_PATH_ASSET' => '/libraries/backend/Data/examples/assets',
  'RELATIVE_PATH_ASSET_IMG' => '/libraries/backend/Data/examples/assets/img',
  'RELATIVE_PATH_ASSET_CSS' => '/libraries/backend/Data/examples/assets/css',
  'RELATIVE_PATH_ASSET_JS' => '/libraries/backend/Data/examples/assets/js',
  'LOCAL_PATH_BASE' => '/var/www/libraries/backend/Data/examples',
  'LOCAL_PATH_APP' => '/var/www/libraries/backend/Data',
  'LOCAL_PATH_LIBRARY' => '/var/www/libraries/backend/Data/vendor',
  'LOCAL_PATH_HELPERS' => '/var/www/libraries/backend/Data/examples',
  'LOCAL_PATH_TEMPLATE' => '/var/www/libraries/backend/Data/examples/templates',
  'LOCAL_PATH_CONFIG' => '/var/www/libraries/backend/Data/examples/config',
  'LOCAL_PATH_PAGES' => '/var/www/libraries/backend/Data/examples/pages',
  'LOCAL_PATH_ASSET' => '/var/www/libraries/backend/Data/examples/assets',
  'LOCAL_PATH_ASSET_IMG' => '/var/www/libraries/backend/Data/examples/assets/img',
  'LOCAL_PATH_ASSET_CSS' => '/var/www/libraries/backend/Data/examples/assets/css',
  'LOCAL_PATH_ASSET_JS' => '/var/www/libraries/backend/Data/examples/assets/js',
  'HTTP_PATH_BASE' => 'localhost:8888/libraries/backend/Data/examples',
  'HTTP_PATH_APP' => 'localhost:8888/libraries/backend/Data',
  'HTTP_PATH_LIBRARY' => false,
  'HTTP_PATH_HELPERS' => false,
  'HTTP_PATH_TEMPLATE' => false,
  'HTTP_PATH_CONFIG' => false,
  'HTTP_PATH_PAGES' => false,
  'HTTP_PATH_ASSET' => 'localhost:8888/libraries/backend/Data/examples/assets',
  'HTTP_PATH_ASSET_IMG' => 'localhost:8888/libraries/backend/Data/examples/assets/img',
  'HTTP_PATH_ASSET_CSS' => 'localhost:8888/libraries/backend/Data/examples/assets/css',
  'HTTP_PATH_ASSET_JS' => 'localhost:8888/libraries/backend/Data/examples/assets/js',
  'REQUEST_QUERY' => false,
  'REQUEST_METHOD' => 'GET',
  'REQUEST_STATUS' => false,
  'REQUEST_PROTOCOL' => 'http://',
  'REQUEST_PATH' => '/',
  'REQUEST_PATH_STRIP_QUERY' => '/',
  'PRODUCTION' => false,
  'PAGE_PATH_DEFAULT' => '/index',
  'PAGE_PATH' => '/index',
)

Depends on your usage, define a constant to hold application path is one of the common practice 取决于您的用法,定义一个常量来保存应用程序路径是常见的做法之一

Don't use variable as it might get override somewhere in your application and can break your application 不要使用变量,因为它可能会在应用程序的某处覆盖并可能破坏您的应用程序

Is even better to combine with symlink (symbolic to create branches) 与符号链接结合更好(符号创建分支)

application dirs
===============================
/home/latest         -> symlink
/home/testing        -> symlink
/home/20111202000000 -> latest development version
/home/20111201000000 -> yesterday stable release

So, you can symbolic link 所以,你可以象征性的链接
/home/testing -> /home/20111202000000 while keeping the stable version, / home / testing - > / home / 20111202000000在保持稳定版本的同时,
/home/latest -> /home/20111201000000 / home / latest - > / home / 20111201000000

With this, you don't have to risk to break your production site while doing some testing/development, and, you can easily shift your development directory 有了这个,您在进行一些测试/开发时不必冒险破坏您的生产站点,并且您可以轻松地转移您的开发目录

Absolute paths are better from a performance point of view when using an opcode cache or lots of require/include statement (although its only noticeable when you start to include hundreds of files, as might happen when using a framework like Zend/Symfony/etc). 在使用操作码缓存或许多require / include语句时,从性能的角度来看绝对路径更好(尽管当你开始包含数百个文件时它们才会引人注意,就像使用Zend / Symfony /等框架时那样) 。

With a relative path the opcode cache and php must work out the files realpath each time before it can work out if it already knows about the file and if it needs to load it again. 使用相对路径,操作码缓存和php必须在每次运行之前计算出文件realpath,如果它已经知道该文件并且是否需要再次加载它。 PHP internally maintains a hashmap of files to file locations which is very quick as long it doesn't have to do the above calculation each time. PHP内部维护文件到文件位置的哈希映射,只要不必每次都执行上述计算,它就非常快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM