zero_ZX Posted August 21, 2013 Share Posted August 21, 2013 (edited) Hi, I'm having issues with included files within included files. This is my project: I browse my portfolio.php and I receive this error: [Wed Aug 21 19:50:01 2013] [error] [client 83.92.74.170] PHP Fatal error: require_once() [<a href='function.require'>function.require</a>]: Failed opening required '/home/thomsen/mikkel/html/portfolio/lang/main.php' (include_path='.:/usr/share/pear/') in /home/thomsen/mikkel/inc/header.php on line 3, referer: http://www.mikkel.thomsen.im/ In my portfolio.php I have: <?PHP require_once("../../inc/header.php"); $title = "Test"; ?> In my header.php I have: <?php require_once("../lang/main.php"); I don't know why it cannot get this file as I move up to my "project", into "lang" and fetch the file, which doesn't exists for some reason. This error is not caused by file permissions. Thanks in advance Edited August 21, 2013 by zero_ZX Quote Link to comment Share on other sites More sharing options...
fastsol Posted August 21, 2013 Share Posted August 21, 2013 Get rid of the ../ for the lang include. The requires/included run from the point the file is including them. So when you include the header it's NOW running from the root, so your include in the header would run from root also. Quote Link to comment Share on other sites More sharing options...
zero_ZX Posted August 21, 2013 Author Share Posted August 21, 2013 (edited) So, depending on where I include the header from, I would need different paths for including the lang file? If so is there any alternative? I will be using different paths multiple times. Edited August 21, 2013 by zero_ZX Quote Link to comment Share on other sites More sharing options...
fastsol Posted August 21, 2013 Share Posted August 21, 2013 Essentially yes I guess. The thing I do so that no matter where you include from it will always look from the root is make a defined var named ROOT that has a value from the getcwd() and then prepend that to the path for the included file. define('ROOT', getcwd()); include(ROOT.'path/to/file'); You can echo out the getcwd() to see what it provides for your site, but it should always point to the absolute root of the server. Quote Link to comment Share on other sites More sharing options...
Solution kicken Posted August 21, 2013 Solution Share Posted August 21, 2013 The rules for how files are located when using include/require are a bit complicated. Basically, it goes though a process something like: - If an absolute path is given, check only that path - If a relative path beginning with ./ or ../ is given, check against the current working directory. - If no path, or a relative path without ./ or ../ is given, check against the include_path entries, then against the working directory, lastly against the calling scripts directory. If the file is not found after all those checks it fails. Note that when it says the calling scripts directory this means the directory of the initial script which was executed, NOT the script containing the include/require directive. In your case, the initial script to be executed was (~ meaning document root) ~/html/portfolio/portfolio.php, that makes the calling scripts directory=~/html/portfolio/. Typically in a web environment, the current working directory is also set to this same value initially. So when you include the header file, php resolves it against the current working directory (~/html/portfolio/) which yields the path ~/inc/header.php. This file exist so PHP uses it. Next, when the header includes the main file, php again resolves that path against the current working directory (~/html/portfolio/) yields the path ~/html/lang/main.php. This file does not exist, so the include fails. Given these rules, you can see that it is typically best to give an absolute path to your include and require directives. One way to do this is as shown above, define a constant value which you then prefix to your paths. Another way is to add a path to the include_path and let PHP resolve names that way. For example if you had: //Where ~ represents your root directory set_include_path(get_include_path().PATH_SEPARATOR.'~'); require_once 'inc/header.php'; then in header.php require_once 'lang/main.php'; things would work out. What I typically do is have a single file somewhere which is always included. That file will define a constant to the root of the site and then add that to the include path. For example, I typically make this file ~/includes/common.inc.php, and it would contain: define('DOCUMENT_ROOT', dirname(__DIR__)); set_include_path(get_include_path().PATH_SEPARATOR.DOCUMENT_ROOT); Each of my scripts will contain a line to include the common.inc.php file (using ../ if necessary, ie require '../../includes/common.inc.php') at the top, all further includes will be relative to that root (ie require 'tcpdf/tcpdf.php') Quote Link to comment Share on other sites More sharing options...
zero_ZX Posted August 21, 2013 Author Share Posted August 21, 2013 Hi kicken, Thanks a lot for you in-depth answer. It really helped me understand the include behind-the-scene - and solved my problem.I ended up using the common.inc as you did. Quote Link to comment Share on other sites More sharing options...
zero_ZX Posted August 22, 2013 Author Share Posted August 22, 2013 (edited) I actually ran into some new issues. It appears that I cannot use the variables that I have now included. From my portolio.php I include the header.php <?PHP require_once("../../inc/common.inc.php"); require_once("inc/header.php"); DisplayHeader(); ?> From the header.php I include the main.php <?php //require_once("../inc/common.inc.php"); require_once("lang/main.php"); /** * Created by JetBrains PhpStorm. * User: Mikkel * Date: 05-08-13 * Time: 12:07 * To change this template use File | Settings | File Templates. */ function DisplayHeader(){ //.... } From the main.php I include a single language file: <?php //session_start(); //header('Cache-control: private'); // IE 6 FIX if(isSet($_GET['lang'])) { $lang = $_GET['lang']; // register the session and set the cookie // $_SESSION['lang'] = $lang; setcookie('lang', $lang, time() + (3600 * 24 * 30)); } //else if(isSet($_SESSION['lang'])) //{ // $lang = $_SESSION['lang']; //} else if(isSet($_COOKIE['lang'])) { $lang = $_COOKIE['lang']; } else { $lang = 'en'; } switch ($lang) { case 'en': $lang_file = 'en.php'; break; case 'da': $lang_file = 'da.php'; break; default: $lang_file = 'en.php'; } require_once ("lang/".$lang_file); ?> In which the variable $lang is set $lang = array(); $lang['PAGE_TITLE'] = 'My website page title'; Yet I receive this message: [Thu Aug 22 13:06:27 2013] [error] [client 83.92.74.170] PHP Notice: Undefined variable: lang in /home/thomsen/mikkel/inc/header.php on line 26, Edited August 22, 2013 by zero_ZX Quote Link to comment Share on other sites More sharing options...
kicken Posted August 22, 2013 Share Posted August 22, 2013 You're error message shows the problem in header.php, but yet you don't show the relevant portion of that file. Based on what you have shown however, I am going to assume you are trying to use that variable from within the DisplayHeader function. If that is the case, you need to read up on variable scope. Quote Link to comment Share on other sites More sharing options...
zero_ZX Posted August 22, 2013 Author Share Posted August 22, 2013 Hi, sorry about that, you made the correct assumption <title> '.$lang['PAGE_TITLE'].'</title> I thought the lang array was actually global as it's not in any function, would I need to declare the $lang variable global? Quote Link to comment 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.