In PHP, let's say I have three classes:
database.php
item.php
user.php
Both classes item and user have the statement include("database.php"); in order to connect to the database and perform queries.
Say, I have a page where I want to show user info and item info. I would have to type
include("item.php");
include("user.php");
But this, of course, gives me an error because I include the database class twice. I know I could use include_once("database.php"); in the item and user classes, but I've read read in various threads it's better not to use the _once-versions of include and require.
What is the best practice to avoid the usage of "_once" in PHP code when you need to include a database class on multiple places?
I would have thought the best solution would be not to do include calls in your main code at all. Instead, autoload your files, so they are only included when they are needed.
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.php';
});
Now, if your code gets to something like new database(); and the database class isn't loaded, this function will include classes/database.php. If the class is used again in future, the class will already be loaded, so the autoloader won't be used again.
See the documentation for spl_autoload_register for more information.
You can include database in main script, from where other scripts are being included, however usage of include_once and require_once is normal and there is no any critical performance issue.
I am not sure about your basic fear of *_once, but ...
include("database.php");
include("item.php");
include("user.php");
One way is to call it as you need and remove the include line from the classes.
Related
i have fetal error message say :
Fatal error: Cannot redeclare class Database in C:\wamp\www\pets_new\lib\database.php on line 3
require_once("lib/message.php");
require_once("lib/user.php");
and all connect to database class
Class message
<?php
require('database.php');
class Message{
Class user :
<?php
require('database.php');
class User{
You include 2 files in a single "run". Think of it like this: All the included files are put together by PHP to create one big script. Every include or require fetches a file, and pastes its content in that one big script.
The two files you are including, both require the same file, which declares the Database class. This means that the big script that PHP generates looks like this:
class Message
{}
class Database
{}//required by message.php
class User
{}
class Database
{}//required by user.php
As you can see class Database is declared twice, hence the error.
For now, a quick fix can be replacing the require('database.php'); statements with:
require_once 'database.php';
Which checks if that particular file hasn't been included/required before. If it has been included/required before, PHP won't require it again.
A more definitive and, IMHO, better solution would be to register an autoloader function/class method, and let that code take care of business.
More on how to register an autoloader can be found in the docs. If you go down this route, you'd probably want to take a look at the coding standards concerning class names and namespaces here. If you conform to those standards, you don't have to write your own autoloader, and can simply use the universal class loader from Symfony2, or any other framework that subscribes to the PHP-FIG standards (like CodeIgnitor, Zend, Cake... you name it)
Try like this , while declaring class
if( !class_exists('database') ) {
require('database.php');
}
This means that you've already declared the class Database, the second time it's loaded (where ever the copy is), it's causing the error. We cannot see your content of the two files you've quoted. However, I'm sure if you look in both of them you'll find at least two creations of the class Database. One needs to be removed.
I use this simple autoloader code:
function __autoload( $class_name ) { include 'class.' . $class_name . '.php'; }
and I make this call new SDB();
SDB actually inherits from SDBOne which I never include...yet the auto-loader loads it.
This means it knows to load modules nested / included in other modules.
So from the looks of it I never need to require or include anything if I use the auto-loader.
However, if I use a stand alone module where there is no auto-loader, I then need to include the class it inherits from.
Should I use
require,
require_once,
include,
include_once.
I would guess to go with require_once because I want an error not a warning...plus when I use the code with the autoloader I don't want it loaded twice.
Basically I have 2 types of use for SDB : one with the autoloader present and one with out.
Reference
http://php.net/manual/en/language.oop5.autoload.php
You are correct, require_once would be the correct way to include a parent class or dependent class in one file. That way if its included multiple times, the require_once prevents errors that would arise from redeclaring a class.
The autoloader is autoloading SDBOne automatically because it needs that class defined before it can extend SDB from it. The same thing is happening to autoload the parent class on demand as happens when you try to load the inherited class.
Also, you should consider switching to spl_autoload_register so that your code will work well with other code that may use an autoloader. The SPL autoloader supports multiple autoloaders and creates a stack in the order they are registered. This way if the first autoloader doesn't satisfy the requirement, it keeps trying subsequently registered autoloaders until the class is loaded or cannot be found.
Another note on preventing errors, you may want to change your autoload function as follows:
function __autoload( $class_name ) {
$file = 'class.' . $class_name . '.php';
if (file_exists($file)) {
include $file;
}
}
Because if the class being autoloaded doesn't exist, you will get errors about including a non-existent file. This is especially important when using spl_autoload_register; you don't want your autoloader to emit unnecessary warnings about missing files if another autoloader will be ultimately responsible for loading the class in question.
Hope that helps.
I have a list of files, wherein a file is inherting another file ion the same directory. I want to include all files of a directory, how do I do it in the order of inheritance so that I dont get any errors
Instead of calculating dependencies yourself, you might as well use auto loading using spl_autoload_register().
This way your dependencies get worked out as required. A bit like "Just-In-Time" loading :)
If your file/s have certain dependencies on other files, make sure you include the "parent" file/s first.
For example, you have a class A in a file A.php:
<?php
class A {
// .. statements
}
And you have a class B that extends A named B.php:
<?php
require_once( "A.php" );
class B extends A {
// .. statements
}
The idea is to "include"/"require" the needed files first prior to using any functions/classes/statement in that file. In PHP 5, you can use the auto-loading functions that would "automatically" add/include the file you need without the constant need of typing require functions.
You COULD use a parser to chek for dependecies but this would be a awfull lot of work and a real performance killer.
You could sort the files and prefix them with numbers
001.init.php
002.db_connect.php
003.pre_filters.php
But if you sort them manually it is rather pointles to rely on the file names.
If you have class inheritance you can combine a autoloader and require once.
Register an custom autoloader to require fles using require_once and and include all your files with a loop. If you need a class from the 8th file in your 4th file the autoloader will load the 8th file ahead of time and when your inlude loop reaches the 8th file nothing will happen because require_once will not include the file again.
But as you might already have realized:
Including files which are depending on each other in a random order from the file system is NOT a good idead.
This question already has answers here:
PHP include best practices question
(10 answers)
Closed 9 years ago.
What is the best practice for including PHP files?
Is it best to include a include.php file that includes all of the project PHP files?
Or to include it in those files that need them
Right now, my project has several include files in my index.php file. Does including all of my php files in the index.php make it less efficient?
Lastly, Where should one include the session check PHP file? in all of the PHP files?
EDIT 2016
Well, 5 years since I replied this. I am still alive. A lot has changed.
Now I use autoloaders to include my files. Here is official info for autoloaders with examples.
Basically, the idea is to have a proper folder structure (PSR-4 standards for instance) and having a class within each file. This way you can use autoloaders and PHP will load your files automatically.
OLD ANSWER
Usually, I have a config file like this:
define(root, $_SERVER['DOCUMENT_ROOT']);
.... // other variables that are used a lot
include (root . '/class/database.php');
.... // other includes that are mostly called from each file, like a db class, or user class, functions etc etc...
if (defined('development'))
{
// turn error reporting on
}
else
{
// turn it off
}
etc etc... You got the point of config.
And I include the config.php on each file. I forgot how to do it right now, but apache can do the automatic include for you. Therefore, you can say to apache to include your config file by default.
Then, I have controller classes, which call the views. There in each function I call the view.
someController.php
function index() { include root . '/views/view_index.php'; }
finally, from the view, if I need to include the header and footer view I do it like this:
view_index.php
<?include root . '/view/shared/header.php';?>
<div class="bla bla bla">bla bla bla</div>
<?include root . '/view/shared/footer.php';?>
I always use include in this structure rather than include_once since the latter requires extra check. I mean, since I am pretty sure that I include files only once, I don't need to use include_once. This way, you also know which include is where. For instance, you know that crucial files like db.php, or functions.php are located in config.php. Or you know that include views are located in controllers. That's pretty useful for me, I hope that helps you, too.
Using the include.php file is a very good practice according to me, as it is very helpful in changing the included files in big projects. If the project is small then including individual files is not a problem. But it becomes a problem to manage them as the project grows big.
For the session check file it is better to attach them individually as the requirement to check session on different pages might differ.
Including files individually or including them all in a single file and then including that makes much of the difference to the performance. As ultimately all the files are going to be included. It only becomes easy to manage them if single file is used to handle them.
I don't assume you are using object oriented programming but in case you do here might be a good answer.
In php you can define a function called the autoloader, if you try to create an object of a class that has not been defined the autoloader is called. You can then use the class name to figure out where the file containing that class is stored to include it at the last moment. Here is an example..
<?php
function on_load($class)
{
if(file_exists(require_once('classes/'.$class.'.php')))
{
require_once('classes/'.$class.'.php');
}
else
{
throw new Exception('Class not found: '.$class.' in classes/');
}
}
spl_autoload_register('on_load'); // tell php to call your on_load function if the class was not defined
If you're working on a big project you might want to group your files like this
/classes/database/MySQL.php
/classes/database/PDO.php // I'm just listing random stuff
/classes/Core.php // Whatever
/classes/datastructure/HashMap.php
You can then use a special naming convention to find the right directory
class Database_MySQL{} // look in <root_dir>/database/ for MySQL.php
class Core // look in <root_dir>/ for Core.php
class Database_Driver_Adapter_Useless_MysqlAdapterThingy {} // look in <root_dir>/Database/Driver/... blabla
Or you can use the php 5.3 way and define your classes like this
<?php
namespace database\driver\adapter\useless;
use database\driver\adapter\MysqlAdapter; // Now you have to tell PHP which version of MysqlAdapter class you want to use, even if there is just one
class MysqlAdapterThingy extends MysqlAdapter {}
Now you have to use the 'use' keyword in every file you need that class. The cool thing is that the namespace is automatically added to the class-name for your autoload function so you can do something like this
function on_load($class)
{ require_once('root/' . str_replace('\\', '/' $class)); }
If you want to learn more try googeling PHP auto-loading there is tons of information on this subject. But then again. From the format of you question I do not assume you're using OOP so this answer is just for the people who found this question on google.
Edit
I would also like to add the following:
// Only include the file once even if you place this statement multiple times
require_once('bla.php');
include_once('bla.php');
require('bla.php'); // Error if file doesn't exist, php will not continue
inlcude('bla.php'); // Warning if file doesn't exist, but php will continue
Using include or require without _once means that file will get included every time the statement is executed
Use include for template or user generated files, use require_once for classes
Just think easy, and think about load as less as possible and don't include something unnecessary.
So for your PHP files. if you include same php files on different pages just create 1 PHP file with this files in it.
If you use a PHP file in 1 page or 2 only, just include them seperate.
I hope i helped you with it ;)
Include files independently, use require_once() function instead of include, as require_once allow only one inclusion of file...
I have a user authentication system that I am currently writing. Problem is, I don't want to have to include class x,y,z,etc for every page that I want to use that class for. For example, here is the index page:
///////// I would like to not have to include all these files everytime////////
include_once '../privateFiles/includes/config/config.php';
include_once CLASSES.'\GeneratePage.php';
include_once DB.'\Db.php';
include_once HELPERS.'\HelperLibraryUser.php'; //calls on user class
//////////////////////////////////////////////////////////////////////////////
$html = new GeneratePage();
$helper = new HelperLibraryUser("username","password","email");
$html->addHeader('Home Page','');
$html->addBody('homePage',
'<p>This is the main body of the page</p>'.
$helper->getUserEmail().'<br/>'.
$helper->doesUserExists());
$html->addFooter("Copyright goes here");
echo $html->getPage();
As you can see, there are a few files that I need to include on every page, and the more classes I add, the more files I will have to include. How do I avoid this?
You can define an autoload function, e.g.:
function __autoload($f) { require_once "/pathtoclassdirectory/$f.php"; }
This way, when php encounters a reference to a class it doesn't know about, it automatically looks for a file with the same name as that class and loads it.
You could obviously add some logic here if you need to put different classes in different directories...
Make a file called common.php and put these include statements as well as any other functions/code that you need in every file (such as database connection code, etc) in this file. Then at the top of each file simply do this:
<?
require_once('common.php');
This will include all your files without having to include them seperately.
It is highly recommended not to use the __autoload() function any more as this feature has been DEPRECATED as of PHP 7.2.0. Relying on this feature is highly discouraged.. Now the spl_autoload_register() function is what you should consider.
<?php
function my_autoloader($class) {
include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.class.php';
});
?>