Hi All!

I am slightly annoyed by PHPs inclusion behavior namely resolving relative paths when multiple files are involved in the following manner:


//contents of /c.php

<?php

echo 'Hello from /c.php';

?>

//contents of /a/a.php

<?php

include '../c.php';

?>

//contents of /a/b/b.php

<?php

include '../a.php';

?>

if I call a.php, include directive succeds (as it should) in including c.php. However if I call b.php, c.php cannot be found upon including from a.php (a.php itself is found). Am I missing something ? How can I even have a chance of developing shared scripts when resolving relative paths depends on the originating script and not solely on the include directive ? I mean, if a.php itself suceeds calling c.php, then no matter what calls a.php, a.php should work, otherwise a.php is useless non-reusable file ?

please help, i dont have anywhere else to go 😉

    When you start including one file within another file, yes I can understand your frustration.

    My suggestion is to plan ahead and view your development as a framework. By doing so, you force yourself to layout your directory structure and force yourself to build reusable code you can leverage.

    For example, on my physical disk I lay it out as follows:

    Common class routines

    /MyFramework
    /MyFramework/Db
    /MyFramework/TimeDate
    /MyFramework/Xml
    /MyFramework/XmlRpc

    Blog application

    /Blog
    /Blog/Images
    /Blog/Errors
    /Blog/Theme

    Portal application

    /Portal
    /Portal/Images
    /Portal/Errors
    /PortalTheme

    etc.

    I store all this on the document root of my webserver. Then, to get at the files, I simply issue the following and build a path from that location:

    $_SERVER["DOCUMENT_ROOT"];

    To avoid putting in too many hard coded directory locations inside my source, I create a global.php file and include it in every .PHP file.

    Global.php

    $docRoot = $_SERVER["DOCUMENT_ROOT"];

    define(MYFRAMEWORK, $docRoot . "/MyFramework");
    define(BLOG, $docRoot . "/Blog");
    define(PORTAL, $docRoot . "/Portal");

    If you later move the directories, you can simply change the define instead of updating all your source code files in global.php.

    You can also put in this global.php file includes/requires that are needed everywhere. For example, I have an object framework that every class inherits from.

    I include my framework module in Global.php as so:

    Global.php

    $docRoot = $_SERVER["DOCUMENT_ROOT"];

    define(MYFRAMEWORK, $docRoot . "/MyFramework");
    define(BLOG, $docRoot . "/Blog");
    define(PORTAL, $docRoot . "/Portal");

    require_once(MYFRAMEWORK . "/core.php");

    And put it in all my applications like so:

    <?php include("Global.php") ?>

    <html>
    <head><title>Test</title</head>
    <body>
    <?php do some php stuff here ?>
    </body>
    </html>

    Hope this helps.

      This ain't pretty, but it works:

      //   /c/c.php
      echo 'hello from c' . '<br />';
      
      //   /a/a.php
      echo 'hello from a' . '<br />';
      ini_set('include_path', '..;../..');
      include 'c.php';
      
      //   /a/b/b.php
      echo 'hello from b' . '<br />';
      ini_set('include_path', '..;../..');
      include 'a.php';

      At least it avoids absolute paths.

      You'd think that just "include '../c.php'" in a.php would work, but it produces an error.

        Thanks a lot guys, looks like i am not the only one battling with this issue.

        I was developing Cold Fusion before, and I got off it coz it was too expensive and too proprietary of a server. I embraced PHP only to find out this strange developer decision about the include paths.

        I cannot afford rewriting my code, it is a lot of directories, and I already have a shared.php where all the common stuff goes. I need a way to get around the problem by means of minimal changes. For example is there a setting in php.ini or PHP system which reverts the behavior to a more usable ?

        THe reason I was mentioning Cold Fusion was also that if you have a CFINCLUDE (analogue to include) tag in one file, it will always take the file where it appears as base of the path, regardless of where the file itself was included from and such. I kinda miss that 😉

          The way I do it is to specify a few configuration variables in each page, one of which would be the include path to use for includes.

          If you use this variable in shared.php, and include shared.php after defining your configuration variables in the individual scripts, then you would solve the problem.
          But then it would be tedious if you have many existing pages, unless you write a program to do it for you.

            I kinda solved this. What i did, is I made a common.php script where I define all the include_path paths (with set_include_path function). Among them I have the path where shared scripts are, and where the root of my pages are (I am on shared host, and default root is the root of the drive, and there are a lot of other peoples pages there 😉)

            I have to include the common.php in all my scripts now, but since it is only one line which solves a lot of other lines, i am happy about it.

            Now all i have to do (after including common.php) is include f.e. 'articles/article1.php' and whatever origin, it will work, because PHP will also look upon this path as a relative one to the specified in set_include_path which is in my case my user home directory.

            Dont know if this is common practice, but it works for me 😉

              What your calling common.php, shared.php, etc. is what I said my global.php is for...

                Thanks kerry 😉

                I wouldn't rely on DOCUMENT_ROOT though, it is an Apache introduced variable. I ve had providers who simply dont have it because they run PHP as a CGI program on IIS 🙁

                And there is no alternative to DOCUMENT_ROOT is it ?

                  Write a Reply...