PHP Velho Oeste 2024

클래스 자동로딩

많은 개발자들이 객체지향 어플리케이션을 만들때 클래스 하나당 하나의 php 소스파일을 만들어 클래스를 정의합니다. 스크립트마다 매번 이렇게 많은 클래스를 include 하는것은 꽤 성가신 일입니다.

php 5 에서는 더 이상 그렇게 하지 않아도 됩니다. __autoload() 함수를 정의하면 사용하려는 클래스나 인터페이스가 아직 정의되지 않았을 경우 자동으로 호출됩니다. 이 함수는 PHP가 오류로 실패하기 이전에 적절한 class가 로드 될수 있도록 마지막 기회를 제공합니다.

Tip

spl_autoload_register() 는 클래스 자동로딩에 대한 더욱 유연한 기능을 제공합니다. 이러한 이유로 __autoload() 가 미래에는 완전히 제거되거나, 사용을 지양하게 될지도 모릅니다.

Note:

5.3.0 이전에서는 __autoload 함수 내부에서 발생한 exception은 catch 블럭으로 catch되지 않고, fatal 에러를 야기했습니다. 5.3.0 이상부터는 catch 블럭으로 catch할 수 있게 되었습니다. 하지만 한가지 조건이 있습니다. 사용자정의 exception을 발생시킬때 사용자정의 exception class가 이미 존재해야 합니다. __autoload 함수를 재귀적으로 사용해서 사용자정의 exception class를 로드 시키는것도 한가지 방법이 될수 있습니다.

Note:

CLI에서는 자동로딩을 지원하지 않습니다. interactive mode.

Note:

클래스명을 call_user_func() 에서 사용하는 경우, ../과 같은 위험한 문자가 포함되어 있을 수가 있습니다. 사용자가 입력한 값을 그대로 사용하지 않을것을 권장하며, 아니면 최소한 __autoload() 에서 입력값을 검증해줘야 합니다.

Example #1 자동로딩 예제

이 예제는 MyClass1MyClass2를 각각 MyClass1.phpMyClass2.php로부터 로드를 시도합니다.

<?php
function __autoload($class_name) {
    include 
$class_name '.php';
}

$obj  = new MyClass1();
$obj2 = new MyClass2(); 
?>

Example #2 다른 자동로딩 예제

이 예제는 ITest 인터페이스의 로드를 시도합니다.

<?php

function __autoload($name) {
    
var_dump($name);
}

class 
Foo implements ITest {
}

/*
string(5) "ITest"

Fatal error: Interface 'ITest' not found in ...
*/
?>

Example #3 5.3.0 이후의 자동로딩 예외 핸들링

이 예제는 예외를 발생하고, tray/catch 블럭을 사용하는 모습을 보여줍니다.

<?php
function __autoload($name) {
    echo 
"Want to load $name.\n";
    throw new 
Exception("Unable to load $name.");
}

try {
    
$obj = new NonLoadableClass();
} catch (
Exception $e) {
    echo 
$e->getMessage(), "\n";
}
?>

위 예제의 출력:

Want to load NonLoadableClass.
Unable to load NonLoadableClass.

Example #4 5.3.0 이후의 자동로딩 예외 핸들링 - 사용자정의 exception 을 찾을수 없음

이 예제는 로딩할 수 없는 사용자정의 exception 에 대한 경우를 보여줍니다.

<?php
function __autoload($name) {
    echo 
"Want to load $name.\n";
    throw new 
MissingException("Unable to load $name.");
}

try {
    
$obj = new NonLoadableClass();
} catch (
Exception $e) {
    echo 
$e->getMessage(), "\n";
}
?>

위 예제의 출력:

Want to load NonLoadableClass.
Want to load MissingException.

Fatal error: Class 'MissingException' not found in testMissingException.php on line 4

add a note add a note

User Contributed Notes 6 notes

up
103
jarret dot minkler at gmail dot com
15 years ago
You should not have to use require_once inside the autoloader, as if the class is not found it wouldn't be trying to look for it by using the autoloader.

Just use require(), which will be better on performance as well as it does not have to check if it is unique.
up
57
str at maphpia dot com
7 years ago
This is my autoloader for my PSR-4 clases. I prefer to use composer's autoloader, but this works for legacy projects that can't use composer.

<?php
/**
* Simple autoloader, so we don't need Composer just for this.
*/
class Autoloader
{
    public static function
register()
    {
       
spl_autoload_register(function ($class) {
           
$file = str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
            if (
file_exists($file)) {
                require
$file;
                return
true;
            }
            return
false;
        });
    }
}
Autoloader::register();
up
29
toi]n[enkayt[attaat]gmaal.com
4 years ago
Autoloading plain functions is not supported by PHP at the time of writing. There is however a simple way to trick the autoloader to do this. The only thing that is needed is that the autoloader finds the searched class (or any other autoloadable piece of code) from the files it goes through and the whole file will be included to the runtime.

Let's say you have a namespaced file for functions you wish to autoload. Simply adding a class of the same name to that file with a single constant property is enough to trigger the autoloader to seek for the file. Autoloading can then be triggered by accessing the constant property.

The constant could be replaced by any static property or method or by default constructor. However, I personally find a constant named 'load' elegant and informative. After all this is a workaround. Another thing to keep in mind is that this introduces an unnecessary class to the runtime. The benefit of this is that there is no need to manually include or require files containing functions by path which in turn makes code maintaining easier. Such behaviour makes it easier to alter the project structure since manual includes need not to be fixed. Only the autoloader needs to be able to locate the moved files which can be automated.

A code file containing functions.
/Some/Namespace/Functions.php
<?php
namespace Some\Namespace;

class
Functions { const load = 1; }

function
a () {
}

function
b () {
}
?>

Triggering autoloading of the file containing functions.
main.php
<?php
\Some\Namespace\Functions::load;

a ();
b ();
?>
up
19
Anonymous
14 years ago
It's worth to mention, if your operating system is case-sensitive you need to name your file with same case as in source code eg. MyClass.php instead of myclass.php
up
1
kalkamar at web dot de
15 years ago
Because static classes have no constructor I use this to initialize such classes.
The function init will (if available) be called when you first use the class.
The class must not be included before, otherwise the init-function wont be called as autoloading is not used.

<?php
function __autoload($class_name)
{
    require_once(
CLASSES_PATH.$class_name.'.cls.php');
    if(
method_exists($class_name,'init'))
       
call_user_func(array($class_name,'init'));
    return
true;
}
?>

I use it for example to establish the mysql-connection on demand.

It is also possilbe do add a destructor by adding this lines to the function:
<?php
if(method_exists($class_name,'destruct'))
   
register_shutdown_function(array($class_name,'destruct'));
?>
up
-3
info at atomosmaestoso dot com
1 year ago
Autoloading Classes with  spl_autoload_register() or spl_autoload() is the best and most modern way to securely code for API integration.

It restricts the various attacks that can be faced by using a "polyfill" or framework that is subject to data injection. Low level attacks, polyfill and framework vulnerabilities are some exploitations limited in using the core functionalities of your host programming language.

Your loop-holes and target endpoints are vastly removed to the level of programming experience of the developer - in not exposing the threats espoused to your programming language and its security protocols.

Each event you transfer data from one program to the next reveals another threat and another attack endpoint. When you are production, it is at this point composer and other tools that gather requirements specific secure integration should limit its use, such as PCI-DSS, HIPAA, or GDPR.

The use of a framework or polyfill gives an attacker hints at what point a function will access memory to produce intended results. Visiting the late L1-Cache Terminal Fault - attacks that use machine language to access memory and read what actually is happening will have all the details of what process is taking place and when.

Not to mention, when a product is open-source, the code is editable and easily compiled. Using access to machine level integrations a simply 10 second loss of time to process could well as infer the entire application has experienced an overhaul.

To deter this, and ensure maximum security for piece of mind and money-wise. The embedded resources of a programming language should be utilized at maximal capacity to prevent an overhaul on multiple endpoints. Visiting a system in use is not deletable or easily moved, removed or altered.
To Top