By old habit I've always used require over include. Basicly the two functions are exactly the same - besides require throws an error if the file does not exist and thus stops the script - where include will just throw a warning and continue on with the script as if nothing happened.
Normally when I dynamically include files I use something along the lines of if file_exists then require it. Looking like this:
<?php if (file_exists($file)) {Â require $file; } else { /*error handling*/ } ?>
As far as I know, and please correct me if I'm wrong, this is widely accepted as best practice and the most efficient way to handle it.
But I thought of another approach, which seems to be slightly faster and smarter in my opinion:
<?php if (!include $file) { /* error handling */ } ?>
I have not tested it yet, but it seems logical to me that it should be faster than the file_exists/require combo, as that requires 2 harddrive interactions where the include approach only requires one.
From my tests it works as expected. It inherits the scope that you would expect and variables set in it is accessible.
Is there any reason not to do this?
edit: typo
edit 2: one argument against this could be the E_Warning thrown when it tried to include a file which does not exist. That could be avoided by passing # at include... Like this:
<?php if(!#include $file) { /* error */ } ?>
No, this is not a "best practice".
You'll be including a file in one of three cases:
if you need functionality from it - in other words, if your code would not function in the absence of that file
if your code could use some functionality from that file to provide extra features, but works without it
if your code could be enhanced by the inclusion of that file, but functions no differently without it (an example would be including a native SSL library versus using a pure-PHP one as a fallback; another example would be an "I need one of these libraries" situation, with all but the last falling into this grouping and the last one you try counting as "I need this" and going with the first bullet)
The only time you should use the if-include pattern you show here is in the second or third case, where having the file is nice but not necessary. In the first case, you should absolutely not do this - you should be using require. In the second case, you should strongly consider using include without the if statement. In the third case, you might use a conditional include, but see below.
The general "best practice" for managing includes in a PHP project where you can expect an include statement to ever fail without tanking the program is to define __autoload and have that handle your error correction, file-existence-checking, and so on.
To address your supposition that "it would be faster" to attempt the include and then detect failure: micro-optimization, especially that not backed by an empirical data, is the root of all evil. It doesn't matter whether it might be faster. First, determine whether you have a problem at all. If yes, then determine whether your include statements are significant enough in runtime that they're worth the programmer-hours you'd spend making them marginally better. If yes, then test whether your alternate implementation works properly. If yes, then benchmark both versions and see if the alternate is faster. Only then should you consider deploying it.
Related
I am using PHP Version 7.3.25.
I have started experimenting with PHP Namespaces on the server-side (not least because I use ESModules on the client-side and I fully appreciate the advantages of namespacing) but I have fallen at the first hurdle - it's probably an obvious rookie error, but with no errors displaying it's difficult to guess what mistake I've made.
I have a long page of global functions - included before anything else by every page on the website - which I have prepended with:
namespace mySetup\myFunctions;
On every page on the site, I include this long page of global functions, using:
include $_SERVER['DOCUMENT_ROOT'].'/my-setup/my-functions.php';
getMyPage();
I can't guess what is going wrong now because the result (for every page) is now an entirely blank page with no error.
Although the long page only contains functions (no classes), I wondered if I might need to change the function invocation getMyPage(); to:
\mySetup\myFunctions\getMyPage();
But that also doesn't work. So I'm a little lost, unable to even guess at what basic, low-level consideration is going wrong or which I've missed.
Yes, you either have to prefix the function with its namespace (use the fully qualified name of it) or alias the function before calling it using the use statement (usually right after the namespace declaration - if any - or at the beginning of the file otherwise).
<?php
use mySetup\myFunctions\getMyPage;
...
include $_SERVER['DOCUMENT_ROOT'].'/my-setup/my-functions.php';
getMyPage();
Note that the use ... statement does not import the function per se. It only creates a short alias for it, so you won't have to use the FQN.
The official documentation is pretty useful for learning the basics, but only you have to keep in mind this slight misuse of "importing" keyword.
EDIT: Namespaces can be used for autoloading (auto-importing) of classes (functions not supported), take a look at spl_autoload_register for the basics, then consider using Composer.
EDIT 2: Also the blank page means a fatal error with error reporting / displaying turned off. Check the PHP log, the error will be there.
I am working within an existing PHP program that has an established way that it dynamically loads certain PHP files for rendering HTML, by doing something basically this:
try {
$includeFilePath = realpath($mySubPath);
include $includeFilePath;
} catch (Exception $e) {
//imagine code that handles error
}
Assume that both file to be included and the file containing the above method are read-only and it's not permissible to alter these actual files on disk. However the above method may be overridden by extending the class it is part of. Meanwhile the file that's being included cannot be overridden gracefully because it does not contain classes, just a mix of PHP and HTML instructions (old school "phtml").
Now what I want to do instead is:
try {
$includeFilePath = realpath($mySubPath);
$codeToModify = substr(file_get_contents($includeFilePath),5);
$codeToEval = $this->modifyCode($codeToModify);
eval($codeToExecute);
} catch (Exception $e) {
//imagine code that handles error
}
... where the modifyCode($str) method is defined elsewhere, and basically what it would do is (a) check the existing file against a pre-known hash checksum value to ensure it has not been modified, and (b) inject known safe code into it in order to add additional functionality to the application (it's "known safe" because we also would use a similar hash verification system on it and validate it).
Now my question is, assuming that security risks are not a concern here, is there any functional reason why eval would be problematic?
Note: no files we'd be including have closing html tags, only opening ones. I chose to use substr($str,5) to trim the opening tag as opposed to adding opening and closing tags as I've seen done elsewhere; that ought to work, right?
Explanation:
Since I anticipate a lot of you might wonder, "Why would you want to do that?", the reason is fairly complicated, but I'll try to explain it. The alternative to doing the above would be to include an entirely different file: one that already contains the custom code I want to use on top of the code from the base file. However the custom code I want to use is all additional code not present in the original base file, so we would end up with a fair amount of duplicated code instead of a more elegant solution where only the new code is "injected" into the base code prior to execution. Even still, using a new file that contains both the old and new code would technically work fine for now.
The problem is, though, in the future it's entirely possible that when we upgrade the base program, there will be changes to the original file (the one that's been effectively overridden by using my custom version of it). If that happens, our override would continue to rely on the previous version's code for that file, since the part of it that carried over from the original base system would no longer match up with the new version's normal default code for that file.
So, to address that problem, I want to go with the method of injecting the code using my custom modifyCode($str) method. That method can tell if there's been any updates to the original file (whether due to a hacker or due to system update) and it would be able to then warn the admin to check out why this code has changed, and issue an approval before executing the modified version of the code by updating the checksum with the hash of the new version of the file to be overridden. That way we can safely update the system and know it will fall back on the default behavior of the new version of the system rather than continue to run old code (which risks breaking the system) or adding mods intended for old versions of the code to new versions of the code that they haven't yet been tested on.
I hope that makes sense.
No. Call stack would be changed (error messages, magic constant __FILE__). Relative includes in evaled code could be broken. Two new variables $codeToModify, $codeToEval would appear in evaled code scope. Evaled code would not be cached. Parse error inside evaled code does not interrupt whole script. Eval could be disabled with Suhosin.
I am not an expert in PHP. I am trying to increase the use of include() to make my website code as clean as possible instead of just copying, for example, code of the header in all the pages. I have two questions
1 . Is it good practice to use include() a lot in terms of server requests, speed, ...etc ?
index.php
(bunch of code)
<? include("connect.php") ?>;
(bunch of code)
<? include("header.php") ?>;
(bunch of code)
<? include("footer.php") ?>;
2 . Is it fine also to use nested include's()? example:
header.php
(some code)
<? include("searchFormInput.php") ?>;
now index.php will include header.php, then header.php will include searchFormInput.php as well
is this fine?
Thanks a lot
Yes, including is a common practice.
Yes, including gives you slight performance penalty (very small).
But including gives you readibility gain and thanks to it will be easier to employ DRY rule. Just remember the following:
if the file contains some code that should be executed only once (some setup, class definitions, function definitions etc.), use include_once() (it will have no effect if invoked again on the same filename),
if the file contains some code executed multiple times (eg. some template for a form), use simple include(),
if something is required for your application to work (eg. some security code, some setup etc.), use require() instead of include() or require_once() instead of include_once() - if the file will not be found, PHP will throw fatal error and will stop executing your script,
The principle downside to nesting includes is that you are likely to run into situations when cross-dependencies cause a file to be include more than once. That is easily solved by the use of include_once(), though.
In your example however, with header.php including searchFormInput.php, you probably won't have problems assuming these files both mostly produce HTML output rather than parsing classes and dependencies.
On the other hand, if you had some structure like
connect.php includes config.php
session.php includes config.php
you would need to use include_once('config.php').
include,require will read file and excute codes inside it.
i made some tests on speed of include and file_get_contents
results was include and require is slow in compare
so my advice don't increase numbers of inclusion.
I think you should look at autoload with PHP once. You should not need to care the include of every and each file. Just adjust your autoload and that will take care of all these. You needs to do object oriented programming with this.
It's fine to that in terms of performance and it keeps your code clean and reusable to a certain extent. However, I recommend that you use templates for this kind of code inclusion, where you load all your information into variables and then call them in your template. Consider a template engine http://www.smarty.net/ or maybe a PHP framework or CMS http://drupal.org/ which should make your life easier in the short and long run!
I'm writing a PHP application for the first time (other than toys and exercises), and I'm at a loss to understand why PHP includes both an include and a require construct.
Before you write an answer explaining the differences between the two, let me first say that I do understand the difference - include produces a warning and keeps on going, and require produces a fatal error. My question is: when would you want to include, but not require a file?
Maybe it's a failure of imagination on my part, but there don't seem to be any files in my application that I don't want to scream about if they're not there. Oddly, this doesn't make me want to use require since it seems impossible to properly handle a failed require, so instead I use a helper function along the lines of this (warning: air code):
public static function include($filename) {
if (is_readable($filename)) {
if (!#include($filename)) {
throw new FileNotFoundException("File deleted after readable check");
}
} else {
throw new FileNotFoundException("File missing or unreadable");
}
}
I guess what I'm asking is:
What sorts of files would you really want to optionally include in an application?
Whether or not you want a file to be required or optional, why wouldn't you just handle that in a function like a modified version of the code I wrote above?
I'd use require for loading files essential for the app itself, i.e. require 'database_config.php', require 'core.php'. If this fails, you want it to fail as fast, hard and merciless as possible, since something is obviously wrong with your app installation. In this state it's not even guaranteed that it could handle a thrown exception properly, and require produces a very clear error message without any extra code.
include should be used for things like template files that you want to use when the app is already up and running and can handle its own errors gracefully.
Example:
include 'error_handler.php';
set_error_handler('error_handler');
/* something bad happens */
Warning: 'error_handler.php' not found!
Error: Specified error handler "error_handler" doesn't exist.
At some point you simply rely on basic files, even if it's just your error handler. You'd have to introduce extra code to handle a missing error handler gracefully, and even then the best you could do is output some error and die (unless you want to get into the game of catching errors gracefully even if your error handler doesn't exist). It's best to simply require 'error_handler.php'; you can include and custom handle everything after this if you want to.
What sorts of files would you really
want to optionally include in an
application?
I normally use include with static HTML blocks (header, footer, menu, search box, survey form...) and require with PHP functions or classes. It's unlikely that the footer block will disappear but, well, I suppose it's a nice visual clue when I look at the code.
Whether or not you want a file to be
required or optional, why wouldn't you
just handle that in a function like a
modified version of the code I wrote
above?
The # operator is said to be expensive and, anyway, I think that including an external file is a basic operation that should be covered by basic language. Your code also adds a new dependency: if you store it in a required block your optional blocks will no longer be 100% optional ;-)
It's functionality is so strong that I worry about its stability and performance.
What do you think?
UPDATE
What I'm doing is this:
$old_dir = getcwd();
chdir( dirname($included_file) );
include ( $included_file );
chdir( $old_dir );
Essentially it just does include ( $included_file );,but inside that $included_file it can't find 3.php which is in the same directory as itself is in,so I manually set the cwd and it works.But it would be nice if I find the reason why it can't find.As for why debug_backtrace is needed,it's because 3.php is included by another func,since the relative path doesn't work,it has to use debug_backtrace to get the including file path,finally using the absolute path as mentioned below.
It's not easy to reproduce,as the above code is in the context of a method,and much more..If no one else has met this kinda problem I'd like to just stop here,anyway,the cost is just the 3 extra lines,not a big deal.
debug_backtrace is relatively expensive in my experience, so you should be careful it is not used in loops (e.g. in a custom error handler that catches warnings or notices and performs a backtrace every time).
For any kind of error logging, I think it's pretty invaluable, and because it's going to be called only once, definitely not a performance problem. It is surely always good to include a backtrace in an error report.
I can't see why there would be any specific issues with this function's stability (i.e. calling it causing another crash), I've never heard of any problems. The only "gotcha" I can see is this note in the User Contributed Notes when using objects as function parameters that have no _toString method defined.
Of course, you should never output the results of a backtrace to the end user - that goes without saying.
Well, considering its name, I'm not sure I would use it as a "normal" part of my application -- even though I don't remember having read anything which said that it was either good nor bad.
I don't really know what you mean about "serious usage", but :
If you need that function for your application to work, it migh indicate some problem in your design
This function can be useful in an error-handler, when you want to log how/where an error happened : it will make the log files more useful, when it comes to tracking down the sources of errors
Though, not sure that "error logging" corresponds to your definition of serious usage ?
Ok, from my understanding, the problem is following
You've got a php file, let's call it "main.php". In "main.php" you're including "A.php" from some directory:
# in "main.php"
include '/some/dir/A.php';
A.php, in turn, includes 'B.php', which is in the same directory as A.php
# in "A.php"
include 'B.php';
the problem: since "/some/dir/" (where A and B reside) is not the current for "main.php", php does not see B.php from A.php
the solution: in A.php use an absolute full path to /some/dir. Either hardcode it or obtain it dynamically via dirname(__FILE__)
# in "A.php"
include dirname(__FILE__) .'/B.php';