Jump to content

include - a mystery to me


Go to solution Solved by Jacques1,

Recommended Posts

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.

 

 

 

 

 

 

Link to comment
https://forums.phpfreaks.com/topic/303084-include-a-mystery-to-me/
Share on other sites

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 by benanamen
  • Solution

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 “..”.

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.

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 by benanamen

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 by fatkatie

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).

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.

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';
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.