views:

329

answers:

5

I'm moving a PHP site from development to a production server and testing the new database connection. I have a config.php page that has only this (but with real data):

<?php
    // Database Constants
    defined('DB_SERVER') ? null : define('DB_SERVER', 'xxx.xxx.xxx');
    defined('DB_PORT')   ? null : define('DB_PORT', 'yyy');
    defined('DB_USER')   ? null : define('DB_USER', 'zzz');
    defined('DB_PASS')   ? null : define('DB_PASS', 'abcdefg');
    defined('DB_NAME')   ? null : define('DB_NAME', 'lmnop');
?>

Then I have initialize.php which holds all of my define() constants, and calls all of my classes.

<?php
   // Define core paths

   // DIRECTORY_SEPARATOR is a PHP pre-defined constant
   // (\ for Windows, / for Unix)
   defined('DS') ? null : define('DS', DIRECTORY_SEPARATOR);

   defined('SITE_ROOT')     ? null : define('SITE_ROOT', 'http://...etc');
   defined('LIB_PATH')  ? null : define('LIB_PATH', SITE_ROOT.'/_includes');

   // load config file first
   require_once(LIB_PATH."/config.php");

   etc...
?>

So far, so good. (I'm using URLs and not DIR paths on purpose, btw.)

But when I create a test.php page to run a query, I'm getting an error that DB_SERVER is not found. I can echo something in config.php and it will appear at the top of the page on test.php, so it's calling the config.php file. And here's the real crazy kicker:

When I copy everything from config.php and paste it into initialize.php, don't change a thing, and then comment out the config.php file... the query works. For some reason it just won't let me pull those variable definitions in from config.php.

Does anyone have any idea why?

+2  A: 

inludes (and require) operate on file system paths, not on urls:

define('SITE_ROOT', 'http://...etc')

is wrong. there should be paths, or your LIB_PATH needs to be defined differently. As manual explains you could make it to operate on url as well, but I doubt you do so.

SilentGhost
why the downvote?
SilentGhost
+1. And the reason it looks like its working is because the echo appears at the top of the page and including the page via url is including the rendered output of the echo.
Andre Miller
That's not true, they operate on any path and his define is not wrong. It´s just that the result is not what he expected because he's including processed php (nothing in this case) instead of code.
jeroen
and what's the difference with *wrong* in this case, jeroen?
SilentGhost
A: 

This can never work: require_once() and all other php-include calls only work on local files. (update: this is not really true)

Edit after reading the comment that says it actually is possible to include something using a url: You want to include the actual code frome the file. If you include something from a url like you are doing now you are probably including the result of running that file instead of the actual php-content.

So it looks like you can resolve your issue in 2 ways:

  • Include using a local path (easiest option -- you can edit your question to explain why it might not be a good option for you)
  • Make the script echo the php content you want to include everywhere (I'd advice against this, because anyone who calls your config url will get the configuration data in plain text.)
Simon Groenewolt
Not quite true. The behavior is different, but it is possible. From the documentation: If "URL fopen wrappers" are enabled in PHP (which they are in the default configuration), you can specify the file to be included using a URL.
Andre Miller
yes, Andre: read further *If the target server interprets the target file as PHP code, variables may be passed to the included file using a URL request string as used with HTTP GET. This is not strictly speaking the same thing as including the file and having it inherit the parent file's variable scope; the script is actually being run on the remote server and the result is then being included into the local script. *
SilentGhost
Yes, thats why I said the behavior is different. I was saying that the statement "require_once() and all other php-include calls only work on local files" is not quite true. PS: The downvote is not mine.
Andre Miller
Thanks for the comments - I've updated my answer.
Simon Groenewolt
+1  A: 

You need to have allow_url_fopen or allow_url_include (as since PHP 5.2) enabled to use URLs for include.

But that’s not a good idea. You should only allow files from your own file system you have the control over. Otherwise it could happen that malicious code is injected and executed on your system from that remote file you included.

Gumbo
It would be nice to get a comment for why this answer got voted down.
Gumbo
+3  A: 

You can't include() from a URL, as what this does is to attempt to run the generated code, which in this case, would be just a blank file. You need to use a local path. To get the directory of the current file, for example:

define('LOCALPATH', dirname(__FILE__));
Ryan McCue
Thanks, Ryan. I knew I was missing something really basic. When I moved this from my local dev server up to the production server, I switched to URLs because my University webhosting wasn't cooperating with telling me the pathname.But this is exactly right. And I guess I can use realpath() to extract the pathname for myself, right? Thanks again!
Jason Rhodes
A: 

You can include files from urls, but you have to realize what is happening.

The web-server will process the php file you are including as an url so the only thing you actually include is the output of the url-included php file.

Which - in your case - is nothing until you echo something.

jeroen