I'm a c# developer, so I'm used to simply compiling a library and including it within a project for use. I haven't really figured out the best way to load different objects within a PHP application. I don't want to keep using require. What is a good approach to take?
If you're using PHP 5.x, you probably want autoloading.
You don't need to keep using require. You can require_once() which will only parse the file if it has not already been loaded.
Also in PHP, since the includes happen at runtime you are free to require_once() in the middle of a conditional if it is appropriate.
// Only load Class.php if we really need it.
if ($somecondition) {
// we'll be needing Class.php
require_once("Class.php");
$c = new Class();
}
else // we absolutely won't need Class.php
I was C# developer in the past and I can tell you that you need to think bit different if you want to write PHP sites. You need to keep in mind that every unnecessary include will increase extra expenses of resources, and your script will work slower. So think twice before add unnecessary includes.
Back to your question you can use include, require, autoload or even phar. Probably PHAR is more close to C# libraries, you can include one PHAR libraries with a number of classes.
Put this in your config file( or any file included in all pages )
function __autoload($class_name) {
require_once "Classes" . $class_name . '.php';
}
Put every class in seperate file with its name.
replace "Classes" with your classes folder.
You can autoload classes. See:
http://us3.php.net/autoload
From that page:
<?php
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
Note that you can use spl_autoload_register() if you don't want to use the single magic __autoload function.
The autoloader will solve all your problems.
Autoloader, as others mentioned.
If you want to go step further... look at the way how Kohana (for example) solved the problem.
This question is the first Stack Overflow result from searching "php how to load classes" and other answers which provide examples for autoloading suggest the use of __autoload(). Please note that use of __autoload() is deprecated as of PHP 7.2 and its use is discouraged. Using spl_autoload_register is suggested instead.
The example snippet below is from the documentation page:
spl_autoload_register(function ($class_name) {
include 'classes/' . $class_name . '.php';
});
Related
Without using include_once or any include/require how can I reference functions declared in other php files in the current directory? Just like we use fopen.
Including contents of php files which contain code not in functions can be a clutter. It'd be better if function usage is linked automatically to its definition.
I've also checked How to include() all PHP files from a directory? which requires some code to do it.
I'm not able to find answer of this anywhere in internet may be because of too common search terms for this problem.
The most logical approach would be to use OOP and autoloading.
That way you would only load the classes that you actually use.
Otherwise the accepted answer from the question you linked to, is the way to go.
You can use glob to traverse the directory and then include them:
$phpfiles = glob('mydir/*.php');
foreach($phpfiles as $file)
do_something_with_the_file($file) // why not include_once $file ?
As you are referencing functions in other files, you cannot use the autoloader because the autoloader operates on classes. Autoloading classes would be a much better solution.
If you're keen on using classes and OO vs Procedural, this will include a file by the same name as the class that's being called, and will not include class files in the directory that are not needed.
Called from the root directory of the site/application.
define( "APP_PATH", dirname( __FILE__ ) ."/" );
function my_autoloader($class)
{
include 'core/classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
Assuming you keep all your classes in a similar directory structure:
site/core/classes
You get the idea.
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
I come across an application using this method to include all class files by using this code
foreach(glob("class/*.php") as $file)
{
include_once "$file";
}
It actually works, but do not know this way to include all files at once would cause any problems later? Is this method to include many files at once recommended?
Thanks
I think autoloading would be better.
Check out here http://php.net/manual/en/language.oop5.autoload.php
One simple example from the document could be tweaked to suit your case
<?php
function __autoload($class_name) {
include 'class/'. $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
This will create a lot of unnecessary overhead if any of the classes aren't used. Each file will have to be parsed which will be unnecessarily time consuming. I agree with #Liangliang Zheng 100% in that you should use __autoload. As for the suggestion of #lbu and your original solution, it is recommended to not use the _once versions, they are more costly than just using include and require.
I've just started to build my very own MVC framework. Feel's kind of nice to know everything from the ground up and only get the stuff that's really necessary for my app.
I come from a codeIgniter background which helped me to get into the MVC perspective of seeing things. In codeigniter, to include a file, codeIgniters very own load class is used.
This load class, when loading a file, checks if a file have previously been included, and if not includes it, which ensures that a file isn't included twice.
However this method of including files has the downside of making it impossible (?) to run tests on my files or take advantage of PHPdoc in my IDE, which I need.
Clearly, I can use the normal include & require functions in PHP forwards and backwards across my application, where a certain library would be needed, but it clearly won´t be good to possible include the same file twice...
So - what's a good solution to use in my own PHP5 MVC framework to include files?
I'm doing a similar thing to you, and I'm using autoload.
Just put this in index.php:
function __autoload($class_name) {
include $class_name . '.php';
}
or include whatever logic you need to check multiple directories.
Edit: Here's my (slightly flaky) code for checking an alternate path. It could be done a lot more cleanly if you were going to need to check multiple paths.
function __autoload($class_name) {
$path = INC_PATH . strtolower($class_name) . '.php';
if (!file_exists($path)) {
$path = MODELS_PATH . strtolower($class_name) . '.php';
}
require $path;
}
just use include_once and require_once . while CI has a load class, you're by no means required to use it.
use include_once/ require_once but the best solution would be working with a autoloader
http://php.net/manual/de/language.oop5.autoload.php
what IDE do you use?
Generally php has the built in include_once which as the name says includes the file, but only once.
Or you can use autoloading which most IDEs support (though some need a bit of a hint - depends on what IDE are you using).
So I have an idea, but I'm thinking I need to run it by StackOverflow before I do something stupid.
I want to have an associative array of class names => filepaths. If PHP ever runs into a fatal error where the class is not defined, it will check if the key exists in my array and then require_once the class. This will prevent unnecessary bulk loading of classes that may never be used.
Bad idea?
How about trying PHP's built in autoloading.
Autoloading is the right way to do it, but spl_autoload_register is a cleaner way than __autoload, because it allows multiple autoloaders. Function __autoload also AFAIK stops working when spl_autoload_register is called, unless __autoload is also registered.
You can write your own autoload or use an existing one. For example, Zend Framework has an autoloader that uses conventions (Foo_Bar is in Foo/Bar.php). Nette Framework has RobotLoader, that indexes your classes and uses the index when neccessary. However, unless you use other things from the framework, it is probably too large.
see: http://www.php.net/manual/en/function.spl-autoload-register.php
If you are on PHP5, you can use __autoload().
makes your code a bit more manageable , although performance-wise, it's a bad choice. But I wouldn't worry it unless I'm building a Facebook.
What you are trying to do is already handled by the php __autoload function. You can read all about it here: http://php.net/manual/en/language.oop5.autoload.php
So, not a bad idea at all ;)
you should use autoloading with specified clas name structure, here is an example
the class names should should be only alpha and _ case-insensitive.
Lets take this directory structure and files
/classes/class.php
/classes/input/input.php
/classes/output/output.php
/classes/regex/regex.php
/classes/interface/parser/interface_parser.php
/classes/parser/parser.php
/classes/parser/xml/parser_xml.php
/classes/parser/html/parser_html.php
having the structure like this is good as it encourages you to code better when it comes to OOP.
Now if we take a look at the /classes/parser/html/html_parser.php file:
class Parser_Html extends Parser implements Interface_Parser
{
//looks nice in here
}
usually you would have to make sure the interface and the extended class is loaded, but these get autoloaded as well if they have not already.
creating the auto load system for this is not that complex, its just 1 function.
function __autoload($name)
{
//Classes
$parts = explode('_',strtolower($name));
$path = '/classes/';
foreach($parts as $p)
{
$path .= $p;
}
$path .= '/' . $name . '.php';
if(file_exists($path))
{
require_once $path;
}
}
so instead of including the class file first just run the class initiation.
$HtmlParser = new Parser_Html();
as the file has not been include the __autoload is run with a param of the class name, the autoload then looks in the directory that's relevant to the class name to try and load it.
also as your using the extend keyword in the class file shown above the class that is to be the parent gets run threw trhe autoloader aswell so you do not need to pre-load interfaces and classes etc.
Hope this helps you.
Note:
All code provided is untested and written for informational purposes, I would recommend you research the techniques more in detail before any implementation is done.