Include expression is not resolved, $_SERVER['DOCUMENT_ROOT']

All through my php files I use the following:
require_once($_SERVER['DOCUMENT_ROOT'] . '../classes/order/SizeManager.php');

However phpstorm cannot understand the structure, what am I doing wrong? Is $_SERVER['DOCUMENT_ROOT'] not supported?

I have this structure:
/var/www/html/project/classes
/var/www/html/project/public (web domain)

I have setup /var/www/html/project as a new project, shared via mounted drive. How can I set $_SERVER['DOCUMENT_ROOT'] as /var/www/html/project/public?

7 comments
Comment actions Permalink

Hi Jesper,

Yes, include/require resolution does not support arrays when resolving full path of included file. Please watch this ticket: http://youtrack.jetbrains.net/issue/WI-3321?projectKey=WI .. and maybe this one: http://youtrack.jetbrains.net/issue/WI-3780?projectKey=WI


If you wish you can disable this inspection in File | Settings | Inspections | PHP | General | Unresolved include

1
Comment actions Permalink

Thanks for your answer. I figured out that I could use the following:

/** @define "$documentRoot" "Z:\html\project\public" */
$documentRoot = $_SERVER['DOCUMENT_ROOT'];
require_once($documentRoot  . '../classes/order/SizeManager.php');

Where Z is my mounted folder. Is there any downside to this approach? What else is the proper way to include files in php and have files auto included in phpstorm?

1
Comment actions Permalink

Hi Jesper,

What else is the proper way to include files in php and have files auto included in phpstorm?

It depends how you coded and structured your project. For example, you can use constructions like dirname(__FILE__) or __DIR__ (PHP 5.3.x only).

If you have single-point entry (like I do) where all major requests go trough index.php which then routes it to a specific page/view (almost all modern frameworks use this sort of approach) then you can look at the example below.

Assuming we have this folder structure:

PROJECT_ROOT
|-- classes
|-- templates

|-- httpdocs (web site root -- where index.php and other js/css/images are located)
|-- var (app logs, caches, temp, upload and other folders)
...

index.php

<?php
define('DIR_WEB', dirname(__FILE__)); // this points to httpdocs, which is website root; will be the same as __DIR__ for this file
define('DIR_ROOT', dirname(dirname(__FILE__))); // this points to project root folder; will be the same as dirname(__DIR__) for this file


...
// loading framework files, initialisations etc
...

// routing to the requested page/view

somefile.php

<?php
include DIR_ROOT . '/classes/order/SizeManager.php';
...

Because index.php is executed on every request (as all requests go trough it), you will always have DIR_ROOT constant defined and will always have the same value which you can use as a part of your include/require statements.


Another approach (which can be used together with any other approach) is to use autoloader functionality which almost eliminates usage of include/require for classes/interfaces (but you may need to name your classes in a specific way or implement some sort of mapping so that autoloader can find them).

1
Comment actions Permalink

I really like your ideas. My current project uses several pages that are not linked together but I'm going to move towards a more router-based system. My new system is completely ajax based so one single-point entry would be best.

1
Comment actions Permalink

I know this is off-topic, but I would like your input Andriy, if you don't mind. We've tried going to a single point of entry system, and I've found it lacking. Every attempt I've seen either breaks the Back button, prohibits use of Bookmarks for the user, or makes it difficult to use complicated URL string manipulation on top of this (and we need all three.)

I wrote the framework we use. Right now, what I'm migrating us to is a single point of entry for the actual front-end:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<?php
require_once "library/common.php";

$sApplicationClass = Applications::$aAllFieldsByID[Applications::GetIDByPageQueryString()]["class_name"];

if(!$sApplicationClass) header("location: /home.php");
?>
<head>
<?php  call_user_func(array($sApplicationClass, "Init")); ?>
</head>
<body>
<?php  call_user_func(array($sApplicationClass, "BodyUI")); ?>
<?php TopLinks() ?>
</body>
</html>


And then every application actually has it's own "page", in a sub-folder, that simply looks like this:

<?php  require_once "../front_end.php"; ?>

Neither of these pages has to be altered, as the applications themselves are all classes and are loaded via a MySQL table that stores page = classname for each one.

What are your thoughts on the single-point of entry (not my hybrid, or you can comment on that if you want), and my indicated drawbacks?

1
Comment actions Permalink

Hi Keith,

Sorry for a late response.

We've tried going to a single point of entry system, and I've found it lacking. Every attempt I've seen either breaks the Back button, prohibits use of Bookmarks for the user, or makes it difficult to use complicated URL string manipulation on top of this (and we need all three.)

Have not met anything like that in any of the sites where I was involved. Maybe we are talking about different "single point of entry" concepts here? What I mean here under "single entry point" is when you have urls like "yoursite.com/privacy-policy" and "yoursite.com/products/adobe-dreamweaver-cs5-windows-p1234",  using url rewrite rule(s) of some kind instead of rewriting url to load individual page/entry point (like "/privacy-policy.php" & "/view-product.php?id=1234") you route these requests to go trough single file (for example, index.php) which can load all very-important include files and will route the request further (many approaches here). This allows to place all php files (except entry-point one) in folder inaccessible from the web (outside website root or in protected folder). Because urls are different, there is no way that this will affect Back button, Bookmarking or URL manipulations.

Maybe under "single point of entry system" you are referring to a sites like Grooveshark or Prostopleer, where you pretty much have single url, heavy ajaxed interface and all navigation is done on client side (using JavaScript) by rebuilding page body via individual ajax requests. If such navigation is implemented properly, user still can use all "important things" (Grooveshark does it all): Back button, Bookmarking current page/position (url manipulation will be part of navigation).

As for the example you have provided -- I cannot make 100% decision having this little info, but so far I see no reason why such templating approach (for web pages) should cause the negative effects you have mentioned. This approach will not be good for non-html output (xml file (sitemap, some product feed, data for some diagramming flash script etc), image, excel/csv export, file download/pdf generation etc) but I guess you already using something different for such cases.

1
Comment actions Permalink

I had thought that URL re-write was not available for IIS, but I just looked and I was mistaken, but yes, I know that is one way to maintain all of those criteria that I was referring to.

Thanks.

1

Please sign in to leave a comment.