문제

내가 사용해야 하는 모든 클래스가 내 스크립트에 액세스할 수 있도록 하기 위해 PHP 스크립트에 너무 많은 파일을 "포함"해야 하는 문제를 처리하는 가장 좋은 방법이 무엇인지 궁금합니다.

현재는 그냥 사용하고 있어요 include_once 내가 직접 액세스하는 클래스를 포함합니다.그 각각은 include_once 액세스하는 클래스.

사용방법을 살펴봤는데 __autoload 기능이 있지만 클래스 파일을 디렉토리 트리에 구성하려는 경우 hat이 제대로 작동하지 않는 것 같습니다.이렇게 하면 원하는 클래스를 찾을 때까지 디렉토리 트리를 탐색하게 될 것 같습니다. 또한 이것이 다른 네임스페이스에서 동일한 이름을 가진 클래스에 어떤 영향을 미치는지 잘 모르겠습니다.

이 문제를 처리하는 더 쉬운 방법이 있습니까?

아니면 PHP가 "기업적인" 다양한 디렉터리에 있을 수 있는 별도의 파일에 있는 다양한 개체가 있는 애플리케이션 유형입니다.

도움이 되었습니까?

해결책

나는 평소에 갖고 있는 애플리케이션 setup.php 모든 핵심 클래스를 포함하는 파일(예:프레임워크 및 관련 라이브러리).내 사용자 정의 클래스는 디렉토리 레이아웃 맵의 지원을 받는 자동 로더를 사용하여 로드됩니다.

새 클래스가 추가될 때마다 모델 클래스를 검색하기 위해 전체 디렉토리 트리를 스캔한 다음 클래스 이름을 키로, 경로를 값으로 사용하여 연관 배열을 작성하는 명령줄 작성기 스크립트를 실행합니다.그런 다음 __autoload 함수는 해당 배열에서 클래스 이름을 조회하고 포함 경로를 가져옵니다.코드는 다음과 같습니다.

autobuild.php

define('MAP', 'var/cache/autoload.map');
error_reporting(E_ALL);
require 'setup.php';
print(buildAutoloaderMap() . " classes mapped\n");

function buildAutoloaderMap() {
    $dirs = array('lib', 'view', 'model');
    $cache = array();
    $n = 0;
    foreach ($dirs as $dir) {
        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $entry) {
            $fn = $entry->getFilename();
            if (!preg_match('/\.class\.php$/', $fn))
                continue;
            $c = str_replace('.class.php', '', $fn);
            if (!class_exists($c)) {
                $cache[$c] = ($pn = $entry->getPathname());
                ++$n;
            }
        }
    }
    ksort($cache);
    file_put_contents(MAP, serialize($cache));
    return $n;
}

자동로드.php

define('MAP', 'var/cache/autoload.map');

function __autoload($className) {
    static $map;
    $map or ($map = unserialize(file_get_contents(MAP)));
    $fn = array_key_exists($className, $map) ? $map[$className] : null;
    if ($fn and file_exists($fn)) {
        include $fn;
        unset($map[$className]);
    }
}

파일 명명 규칙은 [class_name].class.php여야 합니다.디렉토리 클래스를 변경하면 다음에서 검색됩니다. autobuild.php.클래스를 찾을 수 없을 때 자동 로드 기능에서 자동 빌더를 실행할 수도 있지만 이로 인해 프로그램이 무한 루프에 빠질 수 있습니다.

직렬화된 배열은 매우 빠릅니다.

@제이슨마이클:PHP4는 죽었습니다.극복하세요.

다른 팁

spl_autoload_register를 사용하여 여러 자동 로딩 기능을 정의할 수 있습니다.

spl_autoload_register('load_controllers');
spl_autoload_register('load_models');

function load_models($class){
    if( !file_exists("models/$class.php") )
        return false;

    include "models/$class.php";
    return true;
}
function load_controllers($class){
    if( !file_exists("controllers/$class.php") )
        return false;

    include "controllers/$class.php";
    return true;
}

물리적 디렉터리에 매핑되는 구조화된 명명 규칙을 사용하여 프로그래밍 방식으로 클래스 파일의 위치를 ​​확인할 수도 있습니다.이것이 Zend가 수행하는 방식입니다. Zend 프레임워크.그래서 전화할 때 Zend_Loader::loadClass("Zend_Db_Table"); 밑줄로 나누어 클래스 이름을 디렉터리 배열로 분해한 다음 Zend_Loader 클래스가 필요한 파일을 로드합니다.

모든 Zend 모듈과 마찬가지로 로더만 자신의 클래스와 함께 사용할 수 있을 것으로 기대하지만 저는 Zend의 MVC를 사용하는 사이트의 일부로만 사용했습니다.

그러나 모든 종류의 동적 클래스 로딩을 사용할 때 로드 시 성능에 대한 우려가 있었습니다. 예를 들어 다음을 참조하세요. 이 블로그 게시물 Zend_Loader와 클래스 파일의 하드 로딩을 ​​비교합니다.

PHP 포함 경로를 검색해야 하는 성능 저하뿐 아니라 opcode 캐싱도 무효화됩니다.해당 게시물의 댓글에서:

모든 동적 클래스 로더를 사용하는 경우 APC는 단일 요청에 어떤 파일이 로드될지 확신할 수 없기 때문에 해당 파일을 완전히 캐시할 수 없습니다.APC는 파일을 하드 로딩하여 파일 전체를 캐시할 수 있습니다.

__autoload 클래스가 디렉터리 트리 내에서 발견되는 위치를 함수에 알려주는 일관된 명명 규칙이 있는 경우 잘 작동합니다.MVC는 클래스를 모델, 뷰 및 컨트롤러로 쉽게 분할할 수 있기 때문에 이러한 종류의 작업에 특히 적합합니다.

또는 클래스의 파일 위치에 대한 이름의 연관 배열을 유지하고 __autoload 이 배열을 쿼리합니다.

지금까지의 제안 중에서 나는 Kevin의 제안에 부분적으로 동의하지만 그것이 절대적일 필요는 없습니다.__autoload와 함께 사용할 수 있는 몇 가지 다른 옵션이 있습니다.

  1. 모든 클래스 파일을 단일 디렉터리에 넣습니다.클래스 이름을 따서 파일 이름을 지정합니다. 즉, classes/User.php 또는 classes/User.class.php.
  2. 모델을 한 디렉토리에, 컨트롤러를 다른 디렉토리에 넣는 등의 Kevin의 아이디어모든 클래스가 MVC 프레임워크에 잘 맞으면 잘 작동하지만 때로는 상황이 지저분해질 수 있습니다.
  3. 클래스 이름에 디렉터리를 포함합니다.예를 들어 Model_User라는 클래스는 실제로 다음 위치에 있습니다. classes/Model/User.php.__autoload 함수는 파일을 찾기 위해 밑줄을 디렉터리 구분 기호로 변환하는 방법을 알고 있습니다.
  4. 전체 디렉토리 구조를 한 번만 구문 분석하면 됩니다.__autoload 함수에서 또는 정의된 동일한 PHP 파일에서 classes 디렉토리에 어떤 파일이 어디에 있는지 캐시합니다.따라서 로드하려고 하면 User 수업을 들어도 상관없어 classes/User.php 또는 classes/Models/User.php 또는 classes/Utility/User.php.일단 발견되면 User.php 어딘가에 classes 디렉터리에 포함되면 어떤 파일을 포함할지 알 수 있습니다. User 클래스를 자동으로 로드해야 합니다.

@케빈:

나는 여러 로더를 정의할 수 있고 서로 충돌하지 않기 때문에 spl_autoload_register가 __autoload보다 더 나은 대안이라는 점을 지적하려고 했습니다.__autoload 함수도 정의하는 라이브러리를 포함해야 하는 경우 유용합니다.

확실합니까?그만큼 선적 서류 비치 다르게 말한다:

코드에 기존 __autoload 함수가 있는 경우 이 함수는 __autoload 스택에 명시적으로 등록되어야 합니다.이는 spl_autoload_register()가 __autoload 함수에 대한 엔진 캐시를 spl_autoload() 또는 spl_autoload_call()로 효과적으로 대체하기 때문입니다.

=> 모든 라이브러리를 명시적으로 등록해야 합니다. __autoload 또한.하지만 그 외에도 당신 말이 옳습니다. 이 기능이 더 나은 대안입니다.

__autoload 작동하지만 PHP 5에서만 가능합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top