fatkatie Posted February 2, 2017 Share Posted February 2, 2017 Greetings all. New user. So glad to participate in a group with no badges (I don't need no stink'n ...) I'm building a page and have a requisite number of 'requires' at the beginning of the php code. The paths to the required files are all absolute except for the base global def file. For example. My home development environment is a standard xampp port with php 5.6.24. The apache2 document root is C:\xampp\htdocs. The website files are under this, in a "distribution" directory, so the path to the main index file would be: http://localhost/mninfo/index.php In index.php the required files are defined with a full path, as in require '/xampp/htdocs/mninfo/js/common.js'. Inside index.php, one of the required files itself has a required file. That will be fixed later. But it generated this question. Here is the flow/structure /xampp/htdocs/mninfo/index.php require '/xampp/htdocs/mninfo/includes/thisfile.php ... and inside thisfile.php /xampp/htdocs/mninfo/includes/thifile.php require '../oldstuff.php' The require fails. The error says: [Wed Feb 01 21:57:04.761838 2017] [:error] [pid 5580:tid 1652] [client 127.0.0.1:55060] PHP Fatal error: require_once(): Failed opening required '../oldstuff.php' (include_path='C:\\xampp\\php\\PEAR') in C:\\xampp\\htdocs\\mninfo\\includes\\thisfile.php on line 12 I don't understand why. php says any relative file path will use current directory as the base reference. dotdot should point to the directory above 'includes' If the relative path is removed (file name only). It works. If the complete path is included, it works. Thanks for any help. Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/ Share on other sites More sharing options...
benanamen Posted February 2, 2017 Share Posted February 2, 2017 (edited) You don't need to use the full path. Start from the directory where you are at. I don't know exactly where the file oldstuff resides so I can't show you for sure. When you use ../ from an included file you are going above the main directory mninfo to look for it. I don't think that is where you have it. thisfile.php is effectively where index.php is because you included it to be there. It has "become one" with index.php so it it no different if you added ../oldstuff.php to the index file which in your case takes you to the htdocs folder looking for the file. index.php require './includes/js/common.js'; require './includes/thisfile.php'; require './oldstuff.php';// Assuming this file is in mninfo Also using the full path will not allow you to move your app around without editing the path every time. Edited February 2, 2017 by benanamen Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542207 Share on other sites More sharing options...
Solution Jacques1 Posted February 2, 2017 Solution Share Posted February 2, 2017 The problem with relative paths is that it depends on the environment what the paths are relative to. The current directory could be anything. So do use absolute paths. You can still start with the current script by using the __DIR__ constant: require_once __DIR__.'/../oldstuff.php'; Another option is to define your own constant for the base directory of the application and start from there: <?php define('APPLICATION_DIR', $_SERVER['DOCUMENT_ROOT'].'/mninfo'); <?php require_once APPLICATION_DIR.'/oldstuff.php'; Then you don't have to jump around with “..”. Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542211 Share on other sites More sharing options...
fatkatie Posted February 2, 2017 Author Share Posted February 2, 2017 Thanks guys. Let me restate this and also add a few things. First full paths are used because this site is broken. It's a 5 year build of a half dozen programmers in multiple countries. It's a mess. Full paths are being used for file security as we go thru the system. Full path are constructed with defs defined inside the global_def.php file, which is the first file always listed. It is used to build these absolute paths. Here are the files involved. I guess the above was a bit convoluted. xampp/htdocs/mninfo/index.php xampp/htdocs/mninfo/oldstuff.php xampp/htdocs/mninfo/includes/thisfile.php File index.php: require 'global_defs.php'; require DDEF_INCLUDES . 'thisfile.php'; // DDEF_INCLUDES == '/xampp/htdocs/mninfo/includes/' File thisfile.php: require '../oldstuff.php'; That require should work according to my understanding of the include rules. Why doesn't it. There are reasons that thisfile.php require cannot use global definitions. But besides that, why doesn't it work? This error log doesn't make sense to me. It seems to be saying its using the defined include path. PHP docs say relative paths ignore the predefined includes: [Wed Feb 01 21:57:04.761838 2017] [:error] [pid 5580:tid 1652] [client 127.0.0.1:55060] PHP Fatal error: require_once(): Failed opening required '../oldstuff.php' (include_path='C:\\xampp\\php\\PEAR') in C:\\xampp\\htdocs\\mninfo\\includes\\thisfile.php on line 12 Thanks again for helping. Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542247 Share on other sites More sharing options...
benanamen Posted February 2, 2017 Share Posted February 2, 2017 (edited) I explained the problem to you. Because you included thisfile.php in index, it is no different than if you moved thisfile.php out of the includes folder and placed it in the mninfo folder like so xampp/htdocs/mninfo/thisfile.php So the ../ in thisfile.php actually points to xampp/htdocs/ if you want to to point to the mninfo folder, remove one of the dots like so File thisfile.php: require './oldstuff.php'; Edited February 2, 2017 by benanamen Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542248 Share on other sites More sharing options...
fatkatie Posted February 2, 2017 Author Share Posted February 2, 2017 (edited) Oh... I see. Sorry. I can be a little dense. So the base of a relative path inside an included file is the base of the file from which it is included. It is not the directory, necessarily, in which the file with the relative reference resides. I'm not sure, but I think this is treated different in other languages where the directory in which the file resides defines the base of a relative reference. I'll have to check that out. (It might be a processing order thing, where included files are processed first in their environment, thier directory, then 'included' into the master) That practically means that any relative reference can be bogus depending upon where the file is required or used. It sure means that buried includes with relative paths are a disaster. Big change in awareness here. Thanks. Edited February 2, 2017 by fatkatie Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542251 Share on other sites More sharing options...
Jacques1 Posted February 2, 2017 Share Posted February 2, 2017 Like I said, relative paths can be relative to anything. When running PHP in a web server context, the working directory should be the directory of the script which has been triggered by the server -- or not. When running PHP in CLI mode, the working directory depends on the parent shell. If you want to be sure that your paths are always resolved correctly, use __DIR__ (if, for some strange reason, you cannot use your own constants). Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542253 Share on other sites More sharing options...
kicken Posted February 2, 2017 Share Posted February 2, 2017 Basically you just have a fundamental mis-understanding of what the current directory means I think. Every process has a concept known as it's current working directory (see getcwd) which is what relative paths are based around, this is a fundamental concept of processes and not something PHP specific. What exactly this is set to cannot be relied upon because it depends upon how the process was launched. In the context of a web server running PHP scripts the current directory is generally set to the directory containing the initial script. In CLI mode it is whatever directory you were in when you ran the script. In other contexts it may be something entirely different. Your script or some library you're using could change it at any time to whatever value it wants. Generally what I do is have one common configuration file, say common.inc.php that is included either with a relative path or by relying on the configured include_path. Within this file I define useful path constants using __DIR__ as the base which is defined by PHP to be the directory the currently executing file is located in. Those constants can then be used throughout the rest of the code to get paths to various files or directories. Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542254 Share on other sites More sharing options...
Jacques1 Posted February 2, 2017 Share Posted February 2, 2017 Isn't that exactly what I've said? That aside: Another way to overcome the chicken-and-egg problem of a custom base directory is to use environment variables. You can make the webserver set the base directory as an environment variable and then use it in any script: <?php require_once $_ENV['MY_APP'].'/path/to/config.php'; Quote Link to comment https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/#findComment-1542255 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.