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';
});
?>
Related
I am learning advanced PHP standards and trying to implement new and useful methods. Earlier I was using __autoload just to escape including multiple files on each page, but recently I have seen a tip on __autoload manual
spl_autoload_register() provides a more flexible alternative for
autoloading classes. For this reason, using __autoload() is
discouraged and may be deprecated or removed in the future.
but I really can't figure out how to implement spl_autoload and spl_autoload_register
spl_autoload_register() allows you to register multiple functions (or static methods from your own Autoload class) that PHP will put into a stack/queue and call sequentially when a "new Class" is declared.
So for example:
spl_autoload_register('myAutoloader');
function myAutoloader($className)
{
$path = '/path/to/class/';
include $path.$className.'.php';
}
//-------------------------------------
$myClass = new MyClass();
In the example above, "MyClass" is the name of the class that you are trying to instantiate, PHP passes this name as a string to spl_autoload_register(), which allows you to pick up the variable and use it to "include" the appropriate class/file. As a result you don't specifically need to include that class via an include/require statement...
Just simply call the class you want to instantiate like in the example above, and since you registered a function (via spl_autoload_register()) of your own that will figure out where all your class are located, PHP will use that function.
The benefit of using spl_autoload_register() is that unlike __autoload() you don't need to implement an autoload function in every file that you create. spl_autoload_register() also allows you to register multiple autoload functions to speed up autoloading and make it even easier.
Example:
spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');
class MyAutoloader
{
public static function ClassLoader($className)
{
//your loading logic here
}
public static function LibraryLoader($className)
{
//your loading logic here
}
With regards to spl_autoload, the manual states:
This function is intended to be used as a default implementation for __autoload(). If nothing else is specified and spl_autoload_register() is called without any parameters then this functions will be used for any later call to __autoload().
In more practical terms, if all your files are located in a single directory and your application uses not only .php files, but custom configuration files with .inc extensions for example, then one strategy you could use would be to add your directory containing all files to PHP's include path (via set_include_path()).
And since you require your configuration files as well, you would use spl_autoload_extensions() to list the extensions that you want PHP to look for.
Example:
set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();
Since spl_autoload is the default implementation of the __autoload() magic method, PHP will call spl_autoload when you try and instantiate a new class.
Since PHP 5.3, you can use spl_autoload_register() with namespaces, which means that you can organize your project and autoload your php classes without any require or include and without redefining an __autoload() function.
To demonstrate this behaviour, just create a file called index.php :
<?php
spl_autoload_register();
var_dump(new Main\Application);
Then create a folder named Main located right next to the index.php file. Finally, creates a file called Application.php located into Main and paste the following code into it :
<?php namespace Main;
class Application{}
Here is the way I do use Autoload.
In the given example I wanto to load classes form 3 diferent directories.
function namespaceAutoload($rawClass){
$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);
$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';
foreach ($possiblePaths as $templatePath) {
$path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
if (file_exists($path)) {
require_once "$path";
break;
}
} spl_autoload_register("namespaceAutoload");
I the given example, the PHP will look for the namespace\class in these three directories using these three different filename formats.
Working with OOP in php,
spl_autoload_register() lets you register multiple function, classes, trait etc to your php script.
Heres a use case on /test folder structure
/.htaccess
/index.php
/autoload.php
/controller/test.php
Inside autoload.php file:
spl_autoload_register(function ($classname) {
include_once dirname(__FILE__) . "/" . str_replace("\\", "/", $classname) . '.php';
});
Inside .htaccess
DirectoryIndex index.php
# php_value auto_prepend_file
php_value auto_prepend_file "/xampp/htdocs/test/autoload.php"
Inside controller/test.php
namespace controller;
class test {
public static function sayHello () {
echo "hello";
}
}
Inside index.php
use controller/test;
echo test::sayHello();
The autoload.php can be included or like the example above prepend on all script. It loads the class test and lets you use it directly without having to include the test.php script by pathname.
I got a problem with php and OOP.
I tried to create a object and inside the object I tried to load data from mysql.
My files are build like this.
HTML
|_ php
|__ objects
|_ content
In object folder is the object file "Event". The object created in a script in php folder and the whole script is called from a html file in content.
My Problem is, that i use the object from different locations. And the include_once method wont work.
event.php:
<?php
include_once(ROOT.'php/db.inc.php');
class Pb1_event
{
public $ev1_id;
// do something
}
I also tried it with include_once('./../db.inc.php');.
How should I include it ? Is it a good way to include it in this file or should I include it anywhere else ?
Firstly what I would do is use either __DIR__, or better is $_SERVER['DOCUMENT_ROOT'] for absolute pathing. These are constants that will refer to your server web root. Assuming it refers to the root directory you have given to us, you would do:
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/db.inc.php';
But to gain a better understanding, you should echo it and see how your directory paths. Also, for the "best practices" you should use autoloading, you can read more about it here:
http://php.net/manual/en/language.oop5.autoload.php
Define an autoload function and have it call the file you need, for example, if you need a class called DB your function might look something like this:
function __autoload($class) {
if ($class == 'DB') {
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/db.inc.php';
}
}
Use __FILE__ or __DIR__ magic constants:
include_once(dirname(__FILE__) . '/../db.inc.php');
include_once(__DIR__ . '/../db.inc.php');
My suggestion would be to register an autoloader in the beginning of your scripts using spl_autoload_register():
spl_autoload_register(function ($className) {
include 'path/to/php/objects/' . $className . '.php';
});
When you want to instantiate an object, where ever you are, you just need to do:
$myclass = new MyClass();
The autoloader will load the correct class. All you need to think about is to call the files in "objects" the same as your classes. Example:
class Pb1_event {
}
filename: path/to/php/objects/Pb1_event.php
you can try this for your warning:
include_once($_SERVER["DOCUMENT_ROOT"].'/php/db.inc.php');
Is it possible to include a file using a function in PHP? I've already tried something but the file is not included in the script.
I'm using this function :
function run($entry_point){
if(!empty($entry_point)){
if(file_exists('assets/controllers/'.$entry_point.'.php'))
include 'assets/controllers/'.$entry_point.'.php';
else
include 'assets/controllers/home.php';
}
}
My problem its that with this kind of function the index won't include the $entry_point file.
Index.php code:
session_start();
run($_GET['location']);
Thanks!
First of all: your function works for me. Make sure that the names of the folders are correct and turn on error reporting (error_reporting(E_ALL); ini_set("display_errors", 1);).
There are different ways to include files dynamically into your script.
Common frameworks use stuff like (a bit modified for your case):
function includeScript($path = 'assets/controllers/',$file = 'home'){
require $path . $file . '.php';
}
If you're including classes, consider using an autoloader:
function my_autoloader($class) {
include 'assets/controllers/' . $class . '.php';
}
spl_autoload_register('my_autoloader');
What this would do is, that whenever you want to use a class that is not defined, it would automatically look for a file named like the class in the assets/controllers/ folder. E.g:
// the autoloader would look for assets/controllers/Class1.php
$obj = new Class1();
Autoloader will be the ideal candidate for this. However, your function looks fine to me.
Can you make following amendments to the script ?
Turn on error reporting and also display the errors. Refer to Mark's answer for details.
Add __ DIR __ constant before 'assets. So the line will become :
if(file_exists(__ DIR __.'/assets/controllers/'.$entry_point.'.php'))
include __ DIR __.'/assets/controllers/'.$entry_point.'.php';
else
include __ DIR __.'/assets/controllers/home.php';
P.S. : Please use braces for conditional logic. It makes code more readable.
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.
Let's say I've got two files class.php and page.php
class.php
<?php
class IUarts {
function __construct() {
$this->data = get_data('mydata');
}
}
?>
That's a very rudamentary example, but let's say I want to use:
$vars = new IUarts();
print($vars->data);
in my page.php file; how do I go about doing that? If I do include(LIB.'/class.php'); it yells at me and gives me Fatal error: Cannot redeclare class IUarts in /dir/class.php on line 4
You can use include/include_once or require/require_once
require_once('class.php');
Alternatively, use autoloading
by adding to page.php
<?php
function my_autoloader($class) {
include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
$vars = new IUarts();
print($vars->data);
?>
It also works adding that __autoload function in a lib that you include on every file like utils.php.
There is also this post that has a nice and different approach.
Efficient PHP auto-loading and naming strategies
In this case, it appears that you've already included the file somewhere. But for class files, you should really "include" them using require_once to avoid that sort of thing; it won't include the file if it already has been. (And you should usually use require[_once], not include[_once], the difference being that require will cause a fatal error if the file doesn't exist, instead of just issuing a warning.)
Use include_once instead.
This error means that you have already included this file.
include_once(LIB.'/class.php');
use
require_once(__DIR__.'/_path/_of/_filename.php');
This will also help in importing files in from different folders.
Try extends method to inherit the classes in that file and reuse the functions
Use include("class.classname.php");
And class should use <?php //code ?> not <? //code ?>