We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 3749
    • 24,544 Posts
    For people like me who came from C++ or other languages that take a rational approach to "include" and "require" statements, I thought I’d put up this tip about a generic way to use php includes in MODx that will work on both your localhost and a remote site without editing.

    In MODx, the current working directory is usually the base directory (where index.php lives). Complicating this, is the fact the php, unlike C+++, uses the cwd of the including file rather than the included file. As a result, it’s hard sometimes to know how to include a file in a nested include, especially if the included file is in another directory.

    It’s easy to get confused about $modx->config[’base_path’] and all its relatives and I often have things break when I move from localhost (Windows/Xampp) to a remote site (*nix).

    This will generally work to include a file on any server if you know the relative path from the file you’re currently in to the file you want to include or require:

    $path = realpath(dirname(__FILE__)."/relative/path/to/included/file.inc.php");
    include $path;


    If the file to include is in the same directory as the file you’re editing, it’s just:

    $path = realpath(dirname(__FILE__)."/file.inc.php");
    include $path;


    If you like tighter code, you can use:

    include realpath(dirname(__FILE__)."/file.inc.php");

    I often separate them at first in case I want to echo $path to see if it looks right.

    Note that there are two underscore characters before and after "FILE."

    If you’re still having trouble after doing this, look for a www translation where yoursite.com gets converted to www.yoursite.com (or vice versa) either in .htaccess or by your hosting service.

    Hope this saves people some of the trouble I went through to discover it.


    Bob



      Did I help you? Buy me a beer
      Get my Book: MODX:The Official Guide
      MODX info for everyone: http://bobsguides.com/modx.html
      My MODX Extras
      Bob's Guides is now hosted at A2 MODX Hosting
      • 25663 MODX Staff
      • 12,272 Posts
      That’s a great bit of advice ... thank you!
        Ryan Thrash, MODX Co-Founder
        Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
        • 7231
        • 4,205 Posts
        Bookmarked for future reference. Thanks for the tips. grin
          [font=Verdana]Shane Sponagle | [wiki] Snippet Call Anatomy | MODx Developer Blog | [nettuts] Working With a Content Management Framework: MODx

          Something is happening here, but you don't know what it is.
          Do you, Mr. Jones? - [bob dylan]
          • 22303 MODX Staff
          • 10,725 Posts
          For MODx components, I always use MODX_BASE_PATH or $modx->config[’base_path’] to include php files, regardless of where it is located. This is the only absolute way to know for sure your paths will be portable across both PHP versions and all environments.

          Out of curiousity, since essentially MODX_BASE_PATH does the work of realpath(dirname(__FILE__)) anyway, except to a known, specific location (the root of the site), how is this less confusing than just include(MODX_BASE_PATH . ’full/path/to/include’) ? And how is MODX_BASE_PATH confusing in the first place?

          Additionally, how is this affected by www vs. non-www? These are filesystem paths, not URL’s...
            • 3749
            • 24,544 Posts
            Quote from: OpenGeek at Nov 30, 2007, 10:00 AM


            Out of curiousity, since essentially MODX_BASE_PATH does the work of realpath(dirname(__FILE__)) anyway, except to a known, specific location (the root of the site), how is this less confusing than just include(MODX_BASE_PATH . ’full/path/to/include’) ? And how is MODX_BASE_PATH confusing in the first place?

            Additionally, how is this affected by www vs. non-www? These are filesystem paths, not URL’s...

            Excellent points. The last one especially embarrassed. I’ve used hosts that put the site in a www subdirectory under the root, although now that I think about it, it’s probably an alias/duplicate of the one under public_html so you’re right that this wouldn’t have any effect on filesystem paths.

            I confess that I’ve never used MODX_BASE_PATH and I’ve never seen it used in any of the snippets I’ve examined so I can’t speak to it but I’ve had a number of occasions where $modx->config[’base_path’] either didn’t work for me, or didn’t work when I moved things to the remote site. It may be that I had other problems that contributed to this, but in each case, I spent a fair amount of time trying to diagnose what turned out to be an include or require failure. In some of those cases, I had to include config.inc.php to make the $modx object available and my technique came in handy for that.

            I still think my method might be useful for the common case where the including file and the included file are in the same directory because it doesn’t require you to even know the full path to the file. The full path can be long and uncertain, especially in a subdomain, and it’s easy to make a typo entering it. If you have a number of different sites, it takes time to find or remember what the full path is.

            As for my comment about the confusion of $modx->config[’base_path’] and it’s relatives, I didn’t mean to imply that there was anything wrong with them, just that for people like me who are long-time programmers but relatively new to php and web programming, it can be difficult to figure out which one you want and how to use it. There are plenty of posts on the forum to attest to that.

            I always use MODX_BASE_PATH or $modx->config[’base_path’] to include php files, regardless of where it is located. This is the only absolute way to know for sure your paths will be portable across both PHP versions and all environments.

            Are there conditions under which my tip won’t work? I haven’t heard of or encountered any, but you’ve worked on many more platforms than I have.

            I’ll be glad to remove my post (or ask that this thread be removed) if you think it will do more harm than good.

            Bob
              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting
              • 7231
              • 4,205 Posts
              I’ll be glad to remove my post (or ask that this thread be removed) if you think it will do more harm than good.
              I don’t see why you would want to remove this thread, it has a genuine discussion about different methods and promotes thinking wink I for one find it interesting.
                [font=Verdana]Shane Sponagle | [wiki] Snippet Call Anatomy | MODx Developer Blog | [nettuts] Working With a Content Management Framework: MODx

                Something is happening here, but you don't know what it is.
                Do you, Mr. Jones? - [bob dylan]
                • 22303 MODX Staff
                • 10,725 Posts
                Absolutely the tip is useful; don’t remove it, you are very right about the proper way to include nested files.

                I just didn’t want some to get confused about the purpose of MODX_BASE_PATH and $modx->config[’base_path’] (these are always the same values BTW), which is to anchor any internal or external includes to a known location on the file path, without hard-coding it. The problems you describe are exactly what these paths are designed to prevent, i.e. encountering any hurdles in portability, so I was also just curious about those issues I guess.

                There are some rare conditions where realpath can fail if you don’t have permission to the entire directory path, due to bugs in certain PHP versions on certain platforms, but they are very rare scenarios (something like PHP 5.0.4 + Linux + open_base_dir restrictions enabled). We’ve used this technique in the new 0.9.7 core extensively, so I’m definitely not arguing against it or coding around it myself, because, as you said, it is a great convenience for embedded files...
                  • 3749
                  • 24,544 Posts
                  Thanks.

                  There’s still one thing about nested includes in MODx that’s a mystery to me.

                  As I understand it, if a snippet includes its own code, the cwd inside that code is the MODx main directory (where index.php lives). Supposedly, for php includes, the included file inherits the cwd of the including file so that makes sense.

                  At some level of nesting, however, the cwd changes to become the cwd of the included file. I have some deeply nested include files in MODx snippets where include "file.php" works again with no path.

                  It seems that this shouldn’t happen but it definitely does. I’m too lazy to investigate when this does and doesn’t happen, but I’d feel more comfortable if I knew.

                  Maybe I’m wrong about the process and the cwd is not inherited but just calculated as the *directory* of the including file rather than the cwd of the including file.

                  Bob
                    Did I help you? Buy me a beer
                    Get my Book: MODX:The Official Guide
                    MODX info for everyone: http://bobsguides.com/modx.html
                    My MODX Extras
                    Bob's Guides is now hosted at A2 MODX Hosting
                    • 3749
                    • 24,544 Posts
                    OK, I think I can answer my own question here.

                    I think that when a php file is accessed via URL instead of as an included file, the current working directory is its own directory (doh! embarrassed).

                    In that case, $modx->config[’base_path’] is an empty string, even if MODx’s config.inc.php file is included in the php file. So using the standard MODx method for including files will fail. Simply using ’include "file.php"’ will work, though, with no path if the file to be included is in the same directory. Relative paths to other files should work as well.

                    Whether $modx->config[’base_path’] should be empty in this situation is a question for greater minds than mine. smiley

                    I’m not so enchanted with my tip above. It took less than a day to encounter an installation where it failed.

                    Bob


                      Did I help you? Buy me a beer
                      Get my Book: MODX:The Official Guide
                      MODX info for everyone: http://bobsguides.com/modx.html
                      My MODX Extras
                      Bob's Guides is now hosted at A2 MODX Hosting
                      • 22303 MODX Staff
                      • 10,725 Posts
                      No, base_path will never be an empty string; it should always mirror MODX_BASE_PATH which is a constant. It will always be the absolute file-system path (not URL) to the installed location of MODx on the server and is not related in any way to the CWD. I always use the absolute path to the file on the server to ensure it works everywhere, as well as to prevent confusing myself if I decide to move a file.

                      The real point of confusion is that CWD could be different based on your server configuration (e.g. mod_php vs. FastCGI, open_base_dir restrictions, etc.), so you shouldn’t depend on it for includes.