I have been trying to learn about classes in PHP and part of my learning process has been looking at various libraries and stuff out there. Of course I am left with many questions, here is one of them.
When looking at some libraries, the main file that you call to invoke the library, they call each of the libraries files by invoking them directly by name, for example this is how the PHP chart library does it:
<?php
require_once 'model/ChartConfig.php';
require_once 'model/Point.php';
require_once 'model/DataSet.php';
require_once 'model/XYDataSet.php';
require_once 'model/XYSeriesDataSet.php';
require_once 'view/primitive/Padding.php';
require_once 'view/primitive/Rectangle.php';
require_once 'view/primitive/Primitive.php';
require_once 'view/text/Text.php';
require_once 'view/color/Color.php';
require_once 'view/color/ColorSet.php';
require_once 'view/color/Palette.php';
require_once 'view/axis/Bound.php';
require_once 'view/axis/Axis.php';
require_once 'view/plot/Plot.php';
require_once 'view/caption/Caption.php';
require_once 'view/chart/Chart.php';
require_once 'view/chart/BarChart.php';
require_once 'view/chart/VerticalBarChart.php';
require_once 'view/chart/HorizontalBarChart.php';
require_once 'view/chart/LineChart.php';
require_once 'view/chart/PieChart.php';
?>
However, I look at another library, and they just automate the process by calling each file in the directory using the PHP autoload method like this(From the php manual):
function __autoload($name) {
echo "Want to load $name.\n";
throw new Exception("Unable to load $name.");
}
I was just wondering if there is any advantage or disadvantage to doing it the autoload way?
I don't believe __autoload only has advantages. But there are some indeed.
Pros for __autoload
You don't need to maintain that long list of includes, which can be a pain to keep up tidy (which means there's no forgetting an include)
You only include what you really need: some classes might only be needed in some special scenario, you can avoid it
Pros for the normal way
It's very easy to understand for anybody
Looking at the includes will tell you what kind of things the file is doing
You control the list of classes you're importing (if you don't want a class because it's huge or doesn't work, it will never get included)
There's no complexity in the __autoload function. If your classes are in a complex hierarchy, you just need to type the name, and don't need to write complex code to find the correct file.
Easier to debug: the scope of the code that could be worrying is limited to the includes you did.
It's really a matter of coding style.
I think I would agree most with Cygal but would like to amend the response taking PSR-0 into account. I don't think it makes much sense using autoloading if you don't adhere to that standard.
Pro Autoloading
No need to maintain the include list.
You only include what you really need.
Code remains readable.
You follow a standard adopted by all major PHP frameworks so you can expect that people are familiar with this approach.
Pro old style
The dependencies are easily visible in the header of the code files.
There is no mapping between class names and file paths necessery. If you use autoloading a lot it might be necessary to reduce the time wasted for repeatedly calculating this mapping by using a cache.
To summarize: I don't see any reason to avoid autoloading as long as you follow PSR-0!
Using an autoloader is always advantageous.
You don't need massive collections of includes at the top of every
file
You don't have to worry about forgetting an include
Autoloader
only includes files that are necessary, and as they are needed
Potential drawbacks
Clash between your aotoloader and autoloaders used by libraries you want
Potential drawback can be avoided by registering your autoloader with spl
What Mark said. Also, you can keep your code DRY, if that's important to you.
The advantage if autoloading files is you don't need to worry about loadng the files yourself. And the files only gets loaded when they are needed.
An even better autoload function would be the newer: http://php.net/manual/en/function.spl-autoload-register.php
Related
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.
I would like to ask about php performance when you are about to require hundreds or thousand of files dynamically.
See script below
[Folders]
product (50 files)
user (20 files)
report (91 files)
each folder has a lot files but these files as classes. Example below
class cls_product_01 {
public $db;
function __construct($dbconn){
$this->db = $dbconn;
}
function saveProduct(){
//PS: the saveproduct.ext.php is a normal code (native approach)
require __dir__ .'/product/saveproduct.ext.php';
}
}
I have simple controller that will dynamically call the class based on the ajax params
$newAjaxClass = 'cls_'. $_POST['actionid'];
$newApp = new $newAjaxClass($dbconn);
I would like to require all the ajax file on each folder by looping.
Does this slow down the website since there are a lot of files?
PS: I am rewriting this code due to difficulty in maintaining code from the previous developer.
QUESTIONS: With that approach in mind will the application slows down if I load/required all files from the start this is similar to autoloading but I a bit hesitant if including a lot of files will slow down (eat a lot of ram) in the process. Especially I'll be including maybe about 300 to 400 files combined all folders.
I understand that using _autoload with make this easier since it will load the dependency dynamically. The big question is will using autoload with these a lot of script slows down the app? With that hundred of files how much RAM will the autoload eat?
You can use spl_autoload_register().
spl_autoload_register(function ($class_name) {
include $class_name . '.class.php';
});
http://php.net/manual/en/language.oop5.autoload.php
This is lazy loading and hence it won't include all your files upfront unless they are required.
For an example, if you were to load cls_product_01, calling:
new `cls_product_01();`
will look for the file cls_product_01.class.php and it will be included. However your case seems very cumbersome and I think you seriously need to consider your design again. And also I don't think it's a good idea to include files based on user provided data. [ like $newAjaxClass = 'cls_'. $_POST['actionid'];]
Hope it helps.
Check out autoloading.
http://php.net/__autoload
Basically if you tell it how it'll know where to find the file, given the class name, then you don't need to require them all up front.
I have searched many blogs and websites but I didn't find any perfect answer.
whenever I use composer I have to include the autoload.php file and then for each class to autoload I have to use that class with the namespace.now I want to know what is the advantage of this composer where I can easily include the class file by include_once or require_once rather than using both autoload.php and the class file individually.
when I use composer I have to write these code:
include_once("vendor/autoload.php");
use namespace/derectoryname/classname;
whenever I include manually than
include_once("classname.php");
can anyone clear these?
First and foremost, composer main advantage is to handle dependencies (and your dependencies' dependencies, and so on). The autoloader is just frosting on the cake.
The question would be better posed as include vs autoloader, and then it gets slightly more interesting.
First, brevity. With one approach you'll end up using two declarations per file: use and include, whereas using the autoloader you'll just need to declare the use statements, and let the autoloader do the dirty work of actually loading the file.
Also, performance. If you include or require your requirement at the top of your file, you will always load that other file. With the autoloader, you'll only do so if you actually try to use the required class. Until you try to instantiate or use any of the required classes, the autoloader wont hit the filesystem and try to find the required class, making it more efficient, and only doing the work when you actually need the work.
As a somewhat crude example:
use Namespace\Package\Service\ServiceProvider
use Namespace\Package\Exception\ServiceProviderException
if (isset($options['service_id'])) {
try {
$service = ServiceProvider::getService($options['service_id']);
}
catch (ServiceProviderException $e) {
// do your exception handling
}
}
else {
// and now for something entirely different
}
With this, the file that declares ServiceProvider is only going to get loaded if you actually meet the requirements, and the file that declares ServiceProviderException only when if you have to catch the exception (although to be fair it would have been included by the autoloader when ServiceProvider needed to throw that exception, and not before).
On top of that, you've got a neater separation of concerns. Your ClassA that needs to use NameSpace\Package\ClassB is not required to know where you are actually storing that file. It's not its job, and shouldn't care about the actual structure of the filesystem, making the code more portable. Someone somewhere else might have a different vendor structure than you and still get use your code easily if it uses an autoloader, instead of hardcoding file paths in your require statements.
This should be more or less enough to show you that autoloading is a much more modern, efficient, and portable way to work than including your requirements manually.
And since you are already using composer to handle your dependencies, which is awesome, you get the autoloader benefits for free!
I have a doubt about the right way/best practice about loading dependent classes in PHP.
I usually put all dependencies in the beginning of each class with a include_once in a way similar to Java imports. Something like:
include_once 'dto/SomeObjectDTO.php;'
include_once 'dao/SomeObjectDAO.php;'
include_once 'util/SomeObjectUtil.php;'
class SomeObjectService{
#class code here
}
This is the best way to load classes? Or maybe load all classes in a Bootstrap.php? Other ways?
Note that I'm talking about loading my own classes, not complex external classes like frameworks.
Like Homer6 said, autoloading is a php's built in dependency loading mechanism.
PHP-FIG proposed a family of PHP coding standards called PSR. PSR-0 deals with class naming and autoloading. Here are some links:
Requirements and an example autoloader
A good article on the subject
Also, keep in mind, that autoloading comes with a price. There is a lot of string work and work with the fs in the proposed default autoloader(you can implement your own faster autoloader, but it is not going to conform to the standard). This makes autoloading slow when you need to load a lot of classes. So if you needed to load 2 classes only, your approach would be faster and more understandable.
Since version 5.3 PHP supports namespaces.
This allows you to have a package and class hierarchy just like you know them from C++ or Java.
Check out those resources to learn more:
http://www.php.net/manual/en/language.namespaces.basics.php
http://php.net/manual/en/language.namespaces.importing.php
PHP's you can register your autoload method. Symfony 2 contains a nice class to do it with.
http://php.net/manual/en/function.spl-autoload-register.php
I've adapted it to work with the library that we've written.
https://github.com/homer6/altumo/blob/master/source/php/loader.php
https://github.com/homer6/altumo/blob/master/source/php/Utils/UniversalClassLoader.php
This adaption allows you to have namespaces that do not require the top level namespace to have the same folder name.
set_include_path(get_include_path()
. PATH_SEPARATOR . 'path1'
. PATH_SEPARATOR . 'path2'
);
// auto load classes:
function autoloadClasses($className) {
require_once $className . '.php';
}
spl_autoload_register('autoloadClasses');
Is it common practice to append use '.class.php' extension for PHP classes?
On PHP.net here: http://php.net/manual/en/function.spl-autoload-register.php there are some examples like this:
// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.class.php';
});
which use a .class.php extension.
Should PHP code be written like this? I've never seen it before, is it something new? This is a kind of new feature in PHP so maybe it is?
EDIT: 'feature' was not a good word! Perhaps I should have asked whether it's some standard or convention.
Thanks.
It's not a feature, it's just a convention that you see come up every now and then. Whether to follow it or not is the choice of you and your team.
My personal opinion is that since the choice is arbitrary and this particular style contradicts with the PSR-0 autoloader specification you should pass because:
PSR-0 is more widely used, so all other things being equal it would be a better convention to follow
following the ".class.php" style means cannot take a PSR-0 compliant autoloader (there are many online) and use it without modifications
This is mostly used to assure its a class file the autoloader targets, you often have other .php files like templates, scripts like bootstrapping or config files that are .php files, but should never be interpreted as classes
It's not a feature as such, it's just a very simple, and practical way to keep your code organized and, more importantly, to avoid issues with autoloading.
Suppose you've got some class called User, and your site has a page, that is generated by a script: User.php. If you need an instance of the User class, the autoloader function will be called, and get User as an argument. When looking for a file simply called User.php, you might include a file, other than the class definition. That's why you can (and should) give class definition a little extra in their names. Then you can write your autoloader to look for [[class name]].class.php, neatly avoiding the User.php file.
That's the bottom line of it. There's -of course- also namespaces to consider, and that most modern way of all to keep your code organized: directories (set_include_path)
It is all for better understanding what this files all about. So, when you see filename.class.php, you know, this file contains Class filename.
There isn't any kind of special language support that gets triggered if you name your classes 'class.php'; it's just a convention, like whether you use spaces or tabs for indentation.
In one of the projects I worked on, classes where named *.inc.php, and templates *.tpl.php.
If I was coding php circa 1999, this would be an excellent convention to follow. You can name files whatever you want, but I recommend just naming them after the classname inside the file, with '.php' appended.
This is more of a personal preferences, but I would actually probably look into the PSR-0 standards which provide a standard way for you to name and namespace your classes to provide better compatibility with other peoples code in the same format.
In the PSR-0 standards PHP files are named after the class and put into folders related to the namespace.
I would recommend adopting this method over the .class.php method mentioned in the PHP.net manual.