14

Does PHP cache include requests? I was wondering how to clean up my code and I thought about using a bit more includes. Consider the following scheme.

[foreach answer] [include answer.tpl.php] [/foreach]

This would require to include answer.tpl.php hundreds of times.

Does it cache? Will it have a worth-considering affect on performance? Is that considered a good practice? Bad?

In response to @Aaron Murray answer

No, that won't work. The mere concept of _once is to prevent including the same file more than once. (to prevent errors caused by e.g. overwriting constant values)

Practical example would look like this:

# index.php
<?php
$array  = array('a', 'b', 'c');

$output = '';

foreach($array as $e)
{
    $output .= require_once 'test.php';
}

echo $output;

# test.php 
<?php
return $e;
Gajus
  • 69,002
  • 70
  • 275
  • 438
  • The file's contents will be cached by the OS file cache, but there'll still be overhead doing stat() calls and the like to see if the file's been changed since the last load. – Marc B Jun 23 '11 at 17:02
  • Not to mention having to parse the file's contents and evaluating all the PHP code in there, if any. – BoltClock Jun 23 '11 at 17:03
  • `require_once` has no return value. It's not a function. – phant0m Jun 23 '11 at 17:08
  • The OS caches the implied file request quite well. PHP itself does not. But that's typically irrelevant since nowadays bytecode caches (APC) are quite widespread. – mario Jun 23 '11 at 17:10
  • @mario: I do use APC. So, if the APC is in use, this kinda means that `include` is cached as well? – Gajus Jun 23 '11 at 17:11
  • That's my understanding yes (not profiling much). In your particular case with `require_once` you will have to look at the settings http://www.php.net/manual/en/apc.configuration.php#ini.apc.include-once-override – mario Jun 23 '11 at 17:14
  • No @mario, `require_once` e.g. is only to explain why `@Aaron Murray` answer is wrong. I am using `require`. – Gajus Jun 23 '11 at 17:17
  • @Guy: I updated my answer with a little example how you can prevent loading the same template all over again. This will actually reduce the burden for your script a bit. – hakre Jun 23 '11 at 17:18
  • @phant0m For the record, `include` constructs _can_ have return values. See examples 4 and 5 and the text preceding them here: http://php.net/include – Wiseguy Jun 23 '11 at 17:31
  • @Guy did my last revision make it more clear why my answer is not wrong? or am I missing something? – Aaron Murray Jun 23 '11 at 17:42

3 Answers3

7

Does PHP cache include requests?

As far as I know, PHP does not cache includes by default. But your underlying filesystem will likely do this. So accessing the same file over and over again as in your example should be quite fast after all.

If you run into actual problems, you would first need to profile the application to find out where the actual bottleneck is. So unless you did not run into any problems yet, I would consider using the include not harmful.

Regarding the good practice, I think this is fairly well explained in this article: When Flat PHP meets Symfony.

Making your code a bit more re-useable

This is no high design here, it's just to show the picture how you can start to make things more modular. You should be able to take the code 1:1 from your include file, just take care all needed template variables are passed into the function (don't use globals for that, it will stand in your way sooner or later):

# in your answer.tpl.php

function answer_template(array $vars) {
    extract($vars);
    ... your template code ...
}

# your script

array  = array('a', 'b', 'c');

$output = '';

require('answer.tpl.php');

foreach($array as $e)
{
    $output .= answer_template(compact('e'));
}

echo $output;
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Thank you for the answer. Though, -1 for a reference link to Symfony and for `afaik`. Writing a code in a lousy way and fixing only when it is broke (or you start to experience resource issues) is generally a bad advice. – Gajus Jun 23 '11 at 17:20
  • @Guy: The linked article shows a general picture. It's not hiding that it's from symfony, nevertheless it's a good read regardless of any kind of framework. Don't judge only because of the title. The second point is, that premature optimization is often the root of problems, not the solution. When looking onto your code I would first think about some design improvements before even speculate about disc I/O. So it was not an advice to ignore problems, but specifically to locate problems properly. – hakre Jun 23 '11 at 17:25
5

Have you considered:

require_once('answer.tpl.php')
or
include_once('answer.tpl.php')

Of course then you could include the 'required' files only in the scripts that you want them included in (only where they are really required).

Edit: Revamped answer:

index.php ->

require_once('answer.php');
echo answer(); // This function can be called from anywhere in the scripts.

answer.php ->

function answer() {
    return '<div>This is the answer</div>';
}

Also on a side note you could use output buffering in your function to capture HTML (slightly cleaner method for separating HTML and php) within your answer.php.

In response to your example above:

index.php

<?php
require_once('test.php');
$array  = array('a', 'b', 'c');
$output = '';
foreach($array as $e)
{
    $output .= test($e);
}
echo $output;

test.php

<?php
    function test($param) {
    return $param;
}
Aaron Murray
  • 1,920
  • 3
  • 22
  • 38
  • 1
    If you only include once what's going to happen to the rest of the iterations? – BoltClock Jun 23 '11 at 17:00
  • The concept of `_once` is to disallow to include the same code more than once. `The require_once() statement is identical to require() except PHP will check if the file has already been included, and if so, not include (require) it again.` from `php.net` – Gajus Jun 23 '11 at 17:01
  • 1
    In the case of templating, you could wrap the output in a function or class and then require_once the file and then call it from multiple locations. for example answer.tpl.php -> `function answer() { echo '
    This is my output
    '; }` and in the script that requires it: `echo answer()` of course you can also add parameter passing to the function/class you create as well.
    – Aaron Murray Jun 23 '11 at 17:05
  • 1
    Thus you could require it once at the top of your calling script and have that function or class available throughout the execution. – Aaron Murray Jun 23 '11 at 17:09
2

This topic came up before, so here are some potential duplicates (not endorsing any; mostly partial answers, but relevant read nevertheless):

Well, none of those answers your question specifically. We had a little performance benchmark somewhere, but I can't find it.

(Personally I often do orginize my code to merge the whole application into a single blob file, then strip whitespace, to avoid multiple file accesses, even if APC is there.)

Community
  • 1
  • 1
mario
  • 144,265
  • 20
  • 237
  • 291