require_once at the beginning or when really needed? - php

Where should I put require_once statements, and why?
Always on the beginning of a
file, before the class,
In the actual method when the
file is really needed
It depends
?
Most frameworks put includes at the beginning and do not care if the file is really needed.
Using autoloader is the other case here.
Edit:
Surely, we all agree, that the autoloader is the way to go. But that is the 'other case' I was not
asking here. (BTW, Zend Framework Application uses autoloader, and the files are still hard-required, and placed at the beginning).
I just wanted to know, why do programmers include required files at the beginning of the file, even when they likely will not be used at all (e.g. Exception files).

Autoloading is a much better practice, as it will only load what is needed. Obviously, you also need to include the file which defines the __autoload function, so you're going to have some somewhere.
I usually have a single file called "includes.php" which then defines the __autoload and includes all the non-class files (such as function libraries, configuration files, etc). This file is loaded at the start of each page.

I'd say 3. It depends. If you're dealing with a lot of code, it may be worth loading the include file on request only, as loading code will take time to do, and eat up memory. On the other hand, this makes maintenance much harder, especially if you have dependencies. If you load includes "on demand", you may want to use a wrapper function so you can keep track of what module is loaded where.
I think the autoloader mechanism really is the way to go - of course, the application's design needs to be heavily object oriented for that to work.

Related

Disabling include_path in PHP

I'm looking for a way to disable PHP's use of include_path in a project.
Background
Perhaps you're surprised: Why would I want to prevent the use of such a useful feature?
Unfortunately, while I'd consider the answer simple, it's not simple to accurately describe:
In brief, include_path is (obviously) package-/library-blind.
More specifically, it's possible to put two different versions of a library into two folders, both of which are in include_path, and ending up with executed code that is a mixture of both. Consider the following setting:
include_path=/some/server/path/lib:
/var/www/apache/htdocs/yourApplication/library
Now imagine the canonical location for a library you want to use is in /some/server/path/lib and your build process places it there, but a developer is trying to patch a part of it and erroneously syncing the library to /var/www/apache/htdocs/yourApplication/library. Now imagine this happens:
/some/server/path/lib/moduleYouWant
'--> A.php (old version)
/var/www/apache/htdocs/yourApplication/
'--> SomeFile.php (uses B.php from module; previously used A.php)
/var/www/apache/htdocs/yourApplication/library/moduleYouWant
'--> A.php (new version)
'--> B.php (new file; uses A.php from module)
Suddenly, your application will mysteriously use or autoload (if your autoloader puts include_path to use, which most framework-supplied autoloaders do, as far as I'm aware) only half of the changes you made - the new B.php but the old A.php.
You may, of course, object to the setup I've described on grounds that it should never happen for other reasons. That's fair. I'm likely to agree, even. The above scenario is a backwards-incompatible change, for example, and that's not very nice.
Nonetheless, so far I've seen it happen twice in the wild (in a sufficiently complex project, with chroots muddying the water) and it's eaten up countless confused debugging hours... and I don't want to have that issue again. Not in this sort of constellation - or any other.
I don't want PHP magically trying to find my files. I want PHP to demand I be specific about which files to load.
Why I don't need include_path
With __DIR__ (or dirname(__FILE__) in older PHP versions), semantically 'relative' paths are easy to construct. And if I need live- and test-server distinctions, constants defining absolute locations are my friend.
So... I want non-absolute paths supplied to include() (and related functions) to fail.
This stackoverflow question from 2011 tells me that I can't blank include_path. Is there perhaps some other way I can disable the feature? My Googlefu is weak, but nonetheless I have a creeping suspicion the answer is 'no (unless you patch PHP itself)'.
If someone knows of a way I can put a stop to this other than by code convention agreement (or the related "please don't use include() but this custom function I wrote"), I'd love to know. :)
You indicate that the root of the problem is that you have developers writing bad relative includes where they should use be using absolute includes or autoloading.
The solution to this is not technical but cultural. You can enforce correct behavior by adding a pre-commit-hook to your versioning-system that tries to detect erroneous includes (either relative includes, or just all includes) and block the commit.
Just use the following:
set_include_path("./");
then when you need to include file outside the current folder you have to specify the fully qualified relative or absolute path

Multiple PHP classes in one file

I have multiple PHP classes with approximately 20 functions each all in one PHP file. Will the server store every class and every function in memory once I include this file?
Or will it only load the class and its functions once I instantiate like so?:
$ajax = new ajax();
Or will the server only cache the functions that I specifically call?:
$ajax->make_request();
I'm wondering if it is OK to have so many classes and functions housed in one single PHP file or if I should put in some type of logic that includes only the classes and functions that are required for the job.
I think you are a bit confused about how PHP works.
Every request the PHP parser, parses the requested file, e.g. index.php
If index.php include's another file, PHP will the parse that file.
Once a PHP file is parsed, it is stored in memory with "byte codes" (an almost machine language), during that request.
Regardless of how many functions or classes are in a file, it will all be stored in memory for that request.
There are extensions like APC that cache these parsed byte codes in memory between requests, but they need to be added on to PHP.
It is however better (in terms of memory usage) to use auto loading for your classes.
http://php.net/manual/en/language.oop5.autoload.php
PSR0 is a good set of guidelines for autoloading classes:
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
The logic you need is called "Autoloading",
this is the process to include magicaly the class Ajax when the php executable hit a new Ajax(); instruction.
This way, there is never useless classes loaded in memory.
Look at PSR-0 and this good ClassLoader component.
(If you only have 20 classes on your project, you don't need to add an autoloader - the profit will be very low).
No, server by default will not cache anything unless it is set up to cache stuff with use of APC or similar extensions. So if your code uses all these classes then it would be perhaps better to put them in one file to reduce I/O. But if you do not use, separate the code into logical classes, put into separate file and use autoloading.

Scanning directory for php files, and include them in the current script

Would it be a good idea to include extensions for a script this way?
for eg. using glob to get a list of php files from a certain directory, and do a require_once for each file.
this would run each time the page is generated. would it be bad for performance?
It would be bad for two reasons:
If someone sticks evil.php in your directory it could be included and executed.
glob is not the most efficient, nor is including via a relative path.
Perhaps look into using autoloading.
You might consider using __autoload() instead.
It isn't particularly good practise: you're including files irrespective of whether you need them or not. Nor can you control the order of including/requiring to handle any dependencies between the files. If these are PHP class files, then using an autoloader would be a better option.

Will including unnecessary php files slow down website?

The question might prompt some people to say a definitive YES or NO almost immediately, but please read on...
I have a simple website where there are 30 php pages (each has some php server side code + HTML/CSS etc...). No complicated hierarchy, nothing. Just 30 pages.
I also have a set of purely back-end php files - the ones that have code for saving stuff to database, doing authentication, sending emails, processing orders and the like. These will be reused by those 30 content-pages.
I have a master php file to which I send a parameter. This specifies which one of those 30 files is needed and it includes the appropriate content-page. But each one of those may require a variable number of back-end files to be included. For example one content page may require nothing from back-end, while another might need the database code, while something else might need the emailer, database and the authentication code etc...
I guess whatever back-end page is required, can be included in the appropriate content page, but one small change in the path and I have to edit tens of files. It will be too cumbersome to check which content page is requested (switch-case type of thing) and include the appropriate back-end files, in the master php file. Again, I have to make many changes if a single path changes.
Being lazy, I included ALL back-end files inthe master file so that no content page can request something that is not included.
First question - is this a good practice? if it is done by anyone at all.
Second, will there be a performance problem or any kind of problem due to me including all the back-end files regardless of whether they are needed?
EDIT
The website gets anywhere between 3000 - 4000 visits a day.
You should benchmark. Time the execution of the same page with different includes. But I guess it won't make much difference with 30 files.
But you can save yourself the time and just enable APC in the php.ini (it is a PECL extension, so you need to install it). It will cache the parsed content of your files, which will speed things up significantly.
BTW: There is nothing wrong with laziness, it's even a virtue ;)
If your site is object-oriented I'd recommend using auto-loading (http://php.net/manual/en/language.oop5.autoload.php).
This uses a magic method (__autoload) to look for a class when needed (it's lazy, just like you!), so if a particular page doesn't need all the classes, it doesn't have to get them!
Again, though, this depends on if it is object-oriented or not...
It will slow down your site, though probably not by a noticable amount. It doesn't seem like a healthy way to organize your application, though; I'd rethink it. Try to separate the application logic (eg. most of the server-side code) from the presentation layer (eg. the HTML/CSS).
it's not a bad practice if the files are small and contains just definition and settings.
if they actually run code, or extremely large, it will cause a performance issue.
now - if your site has 3 visitors an hour - who cares, if you have 30000... that's another issue, and you need to work harder to minimize that.
You can migitate some of the disadvantages of PHP code-compiling by using XCache. This PHP module will cache the PHP-opcode which reduces compile time and performance.
Considering the size of your website; if you haven't noticed a slowdown, why try to fix it?
When it comes to larger sites, the first thing you should do is install APC. Even though your current method of including files might not benefit as much from APC as it could, APC will still do an amazing job speeding stuff up.
If response-speed is still problematic, you should consider including all your files. APC will keep a cached version of your sourcefiles in memory, but can only do this well if there are no conditional includes.
Only when your PHP application is at a size where memory exhaustion is a big risk (note that for most large-scale websites Memory is not the bottleneck) you might want to conditionally include parts of your application.
Rasmus Lerdorf (the man behind PHP) agrees: http://pooteeweet.org/blog/538
As others have said, it shouldn't slow things down much, but it's not 'ideal'.
If the main issue is that you're too lazy to go changing the paths for all the included files (if the path ever needs to be updated in the future). Then you can use a constant to define the path in your main file, and use the constant any time you need to include/require a file.
define('PATH_TO_FILES', '/var/www/html/mysite/includes/go/in/here/');
require_once PATH_TO_FILES.'database.php';
require_once PATH_TO_FILES.'sessions.php';
require_once PATH_TO_FILES.'otherstuff.php';
That way if the path changes, you only need to modify one line of code.
It will indeed slow down your website. Most because of the relative slow loading and processing of PHP. The more code you'd like to include, the slower the application will get.
I live by "include as little as possible, as much as necessary" so i usually just include my config and session handling for everything and then each page includes just what they need using an include path defined in the config include, so for path changes you still just need to change one file.
If you include everything the slowdown won't be noticeable until you get a lot of page hits (several hits per second) so in your case just including everything might be ok.

How to create a fast PHP library?

For our online game, we have written tons of PHP classes and functions grouped by theme in files and then folders. In the end, we have now all our backend code (logic & DB access layers) in a set of files that we call libs and we include our libs in our GUI (web pages, presentation layer) using include_once('pathtolib/file.inc').
The problem is that we have been lazy with inclusions and most include statements are made inside our libs file resulting that from each webpage, each time we include any libs file, we actually load the entire libs, file by file.
This has a significant impact on the performance. Therefore What would be the best solution ?
Remove all include statements from the libs file and only call the necessary one from the web pages ?
Do something else ?
Server uses a classic LAMP stack (PHP5).
EDIT: We have a mix of simple functions (legacy reason and the majority of the code) and classes. So autoload will not be enough.
Manage all includes manually, only where needed
Set your include_path to only where it has to be, the default is something like .:/usr/lib/pear/:/usr/lib/php, point it only at where it has to be, php.net/set_include_path
Don't use autoload, it's slow and makes APC and equivalent caches jobs a lot harder
You can turn off the "stat"-operation in APC, but then you have to clear the cache manually every time you update the files
If you've done your programming in an object-oriented way, you can make use of the autoload function, which will load classes from their source files on-demand as you call them.
Edit: I noticed that someone downvoted both answers that referred to autoloading. Are we wrong? Is the overhead of the __autoload function too high to use it for performance purposes? If there is something I'm not realizing about this technique, I'd be really interested to know what it is.
If you want to get really hard-core, do some static analysis, and figure out exactly what libraries are needed when, and only include those.
If you use include and not include_once, then there is a bit of a speed savings there as well.
All that said, Matt's answer about the Zend Optimizer is right on the money. If you want, try the Advanced PHP Cache (APC), which is an opcode cache, and free. It should be in the PECL repository.
You could use spl_autoload_register() or __autoload() to create whatever rules you need for including the files that you need for classes, however autoload introduces its own performance overheads. You'll need to make sure whatever you use is prepended to all gui pages using a php.ini setting or an apache config.
For your files with generic functions, I would suggest that you wrap them in a utility class and do a simple find and replace to replace all your function() calls with util::function(), which would then enable you to autoload these functions (again, there is an overhead introduced to calling a method rather than a global function).
Essentially the best thing to do is go back through your code and pay off your design debt by fixing the include issues. This will give you the most performance benefit, and it will allow you to make the most of optimisers like eAccelerator, Zend Platform and APC
Here is a sample method for loading stuff dynamically
public static function loadClass($class)
{
if (class_exists($class, false) ||
interface_exists($class, false))
{
return;
}
$file = YOUR_LIB_ROOT.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file))
{
include_once $file;
if (!class_exists($class, false) &&
!interface_exists($class, false))
{
throw new Exception('File '.$file.' was loaded but class '.$class.' was not found');
}
}
}
What your looking for is Automap PECL extension.
It basically allows for auto loading with only a small overhead of loading a pre-computed map file. You can also sub divide the map file if you know a specific directory will only pull from certain PHP files.
You can read more about it here.
It's been a while since I used php, but shouldn't the Zend Optimizer or Cache help in this case? Does php still load & compile every included file again for every request?
I'm not sure if autoloading is the answer. If these files are included, they are probably needed in the class including it, so they will still be autoloaded anyway.
Use a byte code cache (ideally APC) so that PHP doesn't need to parse the libraries on each page load. Be aware that using autoload will negate the benefits of using a byte code cache (you can read more about this here).
Use a profiler. If you try to optimise without having measures, you're working blind.

Categories