Understanding class required and exist - php

I download a framework and code and I have a question regarding require and include vs class_exists.
In the code I download, I see:
require_once('class.php');
As well as:
if(class_exists('class') == false) { require('class.php'); }
I get require_once means only 1 time and class exists check if the class exists.
My question is: is the second better than the first one? and why?

this condition:
if(class_exists('class') == false) { require('class.php'); }
prevent the require_once to be called.
require_once can be slow if you have a lot of files you include in your project (specially frameworks) because they have to scan the code to make sure the file is not included twice or more. so if you have over 25 file you include and they are nested, require_once will have to check all of them.

As discussed in other answers there are are semantic differences between the two variants. Also in a shared hosting scenario where the hosting provider isn't offering PHP Opcode caching (APC or equiv), all code files need to be read in and compiled once per request. Here the main killer isn't the compile time itself (~0.5M PHP statements / sec on a modern core) but the I/O overhead of collecting the PHP files if not pre-cached in the file-system cache (10s of I/Os / sec).
In this scenario if an application requires a core of say a dozen modules for 90% of queries then it makes sense caching a bundle of these into a single bulkload file. If this type of solution is adopted then placing a class_exists('class') guard around the require of the class file makes it bomb-proof.
Also a caution: If you use an __autoload() function to do JiT class loading, be aware that class_exists('fred') will trigger the autoload of fred. If you want a weak probe then you need to use the predicate !in_array( 'fred', get_declared_classes() ) instead.

The second one would provide more protection from importing the class twice. The first one imports the class file once, but if the class has been imported from another file for some reason the second will pick up that the class has already been declared earlier and not require the classfile.

require_once() only includes a file once.
class_exists() checks whether your class exists.
You can define a class in multiple files and require_once() will not care. Your second chunk will.

Related

PHP loading all classes on every page

I'm building a website and are getting more and more classes to load. Currently I'm including every class in index.php and I also have a ajax handler where every class is included, so I basically include all my PHP files at ajax calls and on every page on the website.
Is this bad practice?
I've tried searching a bit around an have seen that there is a function called spl_autoload_register. By reading a little about it, my understanding is that it tries to include the files defined if a class is not found. But, how is that different from require_once or include_once.
Lets say I have the class underneath in a file and then use require_once('myclass.php');
class Myclass {
function myMethod {
//some code here
}
}
But, the class is not in use before I initialize it with $class = new Myclass; So what is now the difference from running
function my_autoloader($class) {
require_once('classes/' . $class . '.php');
}
spl_autoload_register('my_autoloader');
I would still have to initialize it with $class = new Myclass; when I want to use it. Are there some performance gains from either of them or is it more a preference thing?
And one more question. Should PHP be minifyed like its done with JS and CSS or is this pointless with PHP?
In 2018 the best way to work with autoloading is Composer - build for easy work and performance optimization.
4. Steps to Load Your Classes Fast and Clean
Download composer (for start even right to your project, it's up to you)
Create composer.json and tell him directories or files to load classes from:
{
"autoload": {
"classmap": "/src"
}
}
Using most open and friendly classmap option.
Rebuild cache by CLI command:
composer.phar dump
Include it in index.php
require_once __DIR__ . '/vendor/autoload.php';
And you're ready to go!
The code will technically run faster if you don't load every file on every page, but this will largely go away if you configure "OpCache", which loads all the compiled class definitions into shared memory. And at some point, you may end up with a page that needs 90% of your code loaded to do its job anyway. (This is also relevant to your question about minification - PHP is compiled on the server, so minification doesn't really help anyone.)
The other advantage with autoloading though is maintenance - when you define a new class, you don't have to add it to some master-list of includes, make sure it loads after its parent class but before its child classes, etc. Instead, you place the class definition in a meaningfully named file and directory (great for humans finding it too!) and the autoloader will find it when it's needed.
I did extensive measurements on TYPO3 (PHP) including hundreds of class files on a machine with SSD. I created a script including all available classes. Class reading was not a very expensive part compared to other issues.
I would focus on this optimisation, once all more important questions are addressed.

php re-evaluate included files

I read about the class autoloading in PHP, but till now I didn't understand why we should use __autoload() method?
I read that
PHP doesn't use
this method becuase it has the handy little include functions,
include_once and require_once, that prevent you from loading the same
file more than once, but unlike a compiled language, PHP re-evaluates
these expressions over and over during the evaluation period each time
a file containing one or more of these expressions is loaded into the
runtime in this site why we should use autoloading,
but I don't understand what is the meaning of PHP re-evaluates in the above statement!!
why require-once don't solve the problem of loading php file more than once?
The original article is more clear when you read it more widely (see below) :
It simply says that __autoload() is smarter than include_once() because the function include_once() has to be coded explicitly when the class may be required, and also because this function needs to be processed each time it appears in order to know if the file given in argument is already loaded or not.
The other function __autoload(), on the contrary, can be called only once for several classes you may need. And then PHP tryes to load the corresponding source file only when a class definition is missing.
We can sum up this argumentation by saying: you need one include_once() for each Class/Function source, while only one __autoload() may be enough for a set of Class source having the same location rule.
Snippet of the article:
Why you should use an autoload function in PHP
The loading of classes is something that managed languages like Java
and C# don't need to worry about, class loaders are built into the
compiler.
[...]
PHP doesn't use this method becuase it has the handy little include functions, include_once and require_once, that prevent you
from loading the same file more than once, but unlike a compiled
language, PHP re-evaluates these expressions over and over during the
evaluation period each time a file containing one or more of these
expressions is loaded into the runtime. That is where the Standard PHP
Library (SPL), introduced in PHP 5, and the wonderful little _autoload
function come in to enhance the speed and uniformity of your PHP code.
__autoload is a magic function, that you define, that enables PHP to let you know when it doesn't have a class loaded, but that class
needs to be loaded.
The include_once statement itself is reevaluated whenever encountered.
for ($i = 0; $i < 100; $i++) {
include_once 'foo.php';
new Foo;
}
This will evaluate ("run") the include_once 100 times. That can be something of a slowdown. On the other hand:
for ($i = 0; $i < 100; $i++) {
new Foo;
}
When using autoloading, the logic for file inclusion will only be triggered once, the first time the class is needed.
but till now I didn't understand why we should use it
When you have structured and organized your work, because of the organization it results that you have many similar class files. The simpler example is an mvc, but not only, any custom structure will result in similar files containing a class, then because of the similarity you put them in the same folder and also you use a common file naming convention for example you can have a controller and a model directory.. check example file: employeeModel.php, statisticsModel.php, indexController.php, errorController.php
Well you can take advantage of this fact, check this customized autoload function:
/*** function to include model and view classes ***/
function __autoload($class_name)
{if(__DEBUG) eval(__DEBUG_EVAL);
/*** Load a model class ***/
$mfile=__SITE_PATH .'model/'.$class_name.'.php';//echo 'model file'.NL;v($file);
if (file_exists($mfile)){
include ($mfile);
if(__DEBUG) //store debug info before include
eval('error_log("autoload Success file exists: ".$mfile.NL);');
return true;
}
/*** Load a view class ***/
$cfile=__SITE_PATH .'view/'.'/'.substr($class_name,0,-4).'/'.$class_name.'.php';//v($file);
if (file_exists($cfile)){
include ($cfile);
if(__DEBUG) //store debug info before include
eval('error_log("autoload Success file exists: ".$cfile.NL);');
return true;
}
return false;
}
It also has a few lines for debugging that can easily be removed later. Because of similarity in things it can decide it self what to include and also to report errors when occur. Without this autoload function you would have to care that class files are availoable before use. Also this function will allow to include a file once, if you check carefully it does not use include_once, this means that autoload fires only when the file has not been seen before, in contrary to simple file inclusion which is fired every time the code is executed as very correctly decese notice it.
Conclusion Autload = fires once per file, automates things, so you execute a class directly without caring to include it.
Autoloading means if you need some classes to be included automatically in the scripts like
require_once ("class.user.php");
require_once ("class.module.php");
To avoid such code for each script you can use Autoloading functionality of php

Including child class requires parent class included first

I have asked a similar question to this one already but I think it was badly worded and confusing so hopefully I can make it a bit clearer.
I am programming in a native Linux file system.
I have a class of HelpTopic:
class HelpTopic extends Help{}
And a class of Help:
class Help{}
Now I go to include HelpTopic:
include('HelpTopic.php');
And even though I do not instantiate HelpTopic with new HelpTopic() PHP (in a Linux file system) still reads the class signature and tries to load Help with HelpTopic.
I do not get this behaviour from a cifs file system shared from a Windows System.
My best guess is that there is some oddity with Linux that causes PHP to react this way but not sure what.
Does anyone have any ideas or solutions to this problem?
EDIT:
I have added my loading function to show what I am doing:
public static function import($cName, $cPath = null){
if(substr($cName, -2) == "/*"){
$d_name = ROOT.'/'.substr($cName, 0, -2);
$d_files = getDirectoryFileList($d_name, array("\.php")); // Currently only accepts .php
foreach($d_files as $file){
glue::import(substr($file, 0, strrpos($file, '.')), substr($cName, 0, -2).'/'.$file);
}
}else{
if(!$cPath) $cPath = self::$_classMapper[$cName];
if(!isset(self::$_classLoaded[$cName])){
self::$_classLoaded[$cName] = true;
if($cPath[0] == "/" || preg_match("/^application/i", $cPath) > 0 || preg_match("/^glue/i", $cPath) > 0){
return include ROOT.'/'.$cPath;
}else{
return include $cPath;
}
}
return true;
}
}
I call this by doing glue::inmport('application/models/*'); and it goes through including all the models in my app. Thing is PHP on a linux based file system (not on cifs) is trying to load the parents of my classes without instantiation.
This is a pretty base function that exists in most frameworks (in fact most of this code is based off of yiis version) so I am confused why others have not run into this problem.
And even though I do not instantiate HelpTopic with new HelpTopic() PHP still reads the class signature and tries to load Help with HelpTopic.
Correct.
In order to know how to properly define a class, PHP needs to resolve any parent classes (all the way up) and any interfaces. This is done when the class is defined, not when the class is used.
You should probably review the PHP documentation on inheritance, which includes a note explaining this behavior:
Unless autoloading is used, then classes must be defined before they are used. If a class extends another, then the parent class must be declared before the child class structure. This rule applies to class that inherit other classes and interfaces.
There are two ways to resolve this problem.
First, add a require_once at the top of the file that defines the child class that includes the file defining the parent class. This is the most simple and straight-forward way, unless you have an autoloader.
The second way is to defione an autoloader. This is also covered in the documentation.
The ... thing ... you're using there is not an autoloader. In fact, it's a horrible abomination that you should purge from your codebase. It's a performance sap and you should not be using it. It also happens to be the thing at fault.
We don't have the definition of getDirectoryFileList() here, so I'll assume it uses either glob() or a DirectoryIterator. This is the source of your problem. You're getting the file list in an undefined order. Or, rather, in whatever order the underlying filesystem wants to give to you. On one machine, the filesystem is probably giving you Help.php before HelpTopic.php, while on the other machine, HelpTopic.php is seen first.
At first glance, you might think this is fixable with a simple sort, but it's not. What happens if you create a Zebra class, and then later need to create an AlbinoZebra that inherits from it? No amount of directory sorting is going to satisfy both the "load ASCIIbetical" and the "I need the Zebra to be first" requirements.
Let's also touch on the performance aspect of the problem. On every single request, you're opening a directory and reading the list of files. That's one hell of a lot of stat calls. This is slow. Very slow. Then, one by one, regardless of whether or not you'll need them, you're including the files. This means that PHP has to compile and interpret every single one of them. If you aren't using a bytecode cache, this is going to utterly destroy performance if the number of files there ever grows to a non-trivial number.
A properly constructed autoloader will entirely mitigate this problem. Autoloaders run on demand, meaning that they'll never attempt to include a file before it's actually needed. Good-performing autoloaders will know where the class file lives based on the name alone. In modern PHP, it's accepted practice to name your classes such that they'll be found easily by an autoloader, using either namespaces or underscores -- or both -- to map directory separators. (Meaning namespace \Models; class Help or class Models_Help would live in Models/Help.php)
Unfortunately most examples won't be useful here, as I don't know what kind of weird things your custom framework does. Take a peek at the Zend Framework autoloader, which uses prefix registration to point class prefixes (Model_) at directories.

Does including classes that you don't use have impact on performance?

like
require "class.a.php";
require "class.b.php";
require "class.c.php";
class main{
function main(){
if(condition_is_met(){
$this->something = new A();
}else{
$this->something = new B();
}
}
}
Should the files be included in the condition check with require_once, and not all the time?
The question is not clear. In the current code, I think all of the file(s) will get included, whether you use (declare variable of these classes) them or not. If you wan't to not load the class(es) you will not use, you can use the __autoload() function.
http://php.net/manual/en/language.oop5.autoload.php
PHP has to open the file and parse it so it has some impact. For a few files I wouldn't worry about it but it can get out of hand as your files increase. That's why there's autoload, which allows you to load class files only when needed, without having a long list of requires at the top of your files:
http://php.net/manual/en/language.oop5.autoload.php
Also take a look at spl_autoload_register:
http://www.php.net/manual/en/function.spl-autoload-register.php
The only performance it should effect is the time to parse it, but I think that is preferred over complicated include logic hidden midway inside of your file. Not to mention that if you put the require inside of the if statement it is like you inserted that file's text inside of that if statement, which isn't right (and may not work).
Can anyone tell me if you can declare a class inside of a function/if statement?
Anytime you use include or require, PHP is basically copy/pasting the code from the required file into your code. So no matter where you put it, PHP is still opening the file, reading it and dropping it in there, it won't be affected by an if block. In other words, require is parsed before the code is actually run, so yes, you will take a (very small) performance hit even if require is put in an if block and never run. Keep in mind, this is a very small impact. Lastly if you are worried about it, I would use require_once - this ensures that this parsing does not happen twice, for example if a second required file requires the first file, this redundancy won't amount to a second performance hit.

In PHP Dependency Injection, do I need to "require_once" the php file where the dependency is defined?

Taking Fabien Potencier's example:
class User
{
function __construct($storage)
{
$this->storage = $storage;
}
// ...
}
Assuming the Storage class is defined in a different php file (say, storage.php), do I need to include it in this file where the injection is done via a require_once?
Thanks,
JDelage
You should be putting all your requires and includes at the head of the file - that certainly a style thing, but for one thing it allows you to see by glancing at the source, what other files are need by your PHP file.
There are two cases:
You will only ever use user.php and storage.php from other files (app.php say)
There are cases where you will use user.php and don't want to worry about remembering to require storage.php.
For #1 - you don't need to worry about requires, however there's no significant disadvantage to using require_once at the head of your PHP even if most of the time it'll have already been required.
For #2 - you need to use require_once at the header since you cannot use user.php without storage.php and the final page only knows it needs user.php.
short answer: Use require_once to include all dependencies for the code (to allow it to easily be used by other code)
note: You should only include direct-dependencies for the code. That is: if you have group.php that uses user.php, it should require_once 'user.php', but need not worry about storage.php since it isn't directly used, and user.php implicitly includes it (that being said - no significant performance disadvantage of being thorough if you wish)

Categories