Programing

기능 용 오토로더

lottogame 2021. 1. 11. 07:27
반응형

기능 용 오토로더


지난주에 __autoload()함수 를 작성하여 프로젝트에 수업을 포함 할 수 있다는 것을 배웠습니다 . 그런 다음 오토로더를 사용하는 것이 기술 일뿐만 아니라 패턴이라는 것을 배웠습니다.

이제 프로젝트에서 오토로더를 사용하고 있는데 매우 유용하다는 것을 알게되었습니다. 함수로 똑같은 일을 할 수 있는지 궁금합니다. 함수가 포함 된 올바른 PHP 파일을 포함하는 것을 잊는 것은 매우 유용 할 수 있습니다.

그렇다면 함수 자동 로더를 만들 수 있습니까?


기능에 대한 기능 자동 로더는 없습니다. 네 가지 현실적인 솔루션이 있습니다.

  1. 모든 함수를 네임 스페이스 클래스로 래핑합니다 (컨텍스트 적절한). 라는 함수가 있다고 가정 해 봅시다 string_get_letters. StringFunctions이를 정적 함수 라고하는 클래스에 추가 할 수 있습니다 . 따라서 호출하는 대신 string_get_letters(), 당신은 전화 것입니다 StringFunctions::get_letters(). 그런 다음 __autoload네임 스페이스가 지정된 클래스입니다.

  2. 모든 기능을 미리로드합니다. 당신이 클래스를 사용하고 있기 때문에, 당신은하지 말았어야 , 그래서 그냥 사전 부하에게, 그들에게 많은 기능을.

  3. 기능을 사용하기 전에로드하십시오. 각 파일 require_once에서 해당 파일에서 사용될 함수 파일.

  4. 애초에 함수를 사용하지 마십시오. OOP 코드를 개발하는 경우 (어쨌든 그렇게 보임) 함수가 거의 필요하지 않습니다. 함수 (또는 다중)가 필요한 모든 것을 OO 방식으로 빌드하고 함수의 필요성을 피할 수 있습니다.

개인적으로 정확한 필요와 코드베이스의 품질 및 크기에 따라 1, 2 또는 4를 제안합니다.


프로젝트에서 Composer를 사용 하는 경우 자동로드 섹션에 파일 지시문을 추가 할 수 있습니다 .

이것은 실제로 오토로더에서 require_once를 생성하는 것보다는 실제 오토 로딩처럼 느껴집니다. 왜냐하면 당신이 그것을 처리 할 필요가 없기 때문입니다.
그래도 지연 로딩이 아닙니다.

Assetic 에서 가져온 예 :

"autoload": {
        "psr-0": { "Assetic": "src/" },
        "files": [ "src/functions.php" ]
    }

나는 치명적인 오류를 포착하고 누락 된 기능을 포함하고 실행하려고 시도한 추악한 해킹에 대해 얼마 전에 읽었지만 확실히 그 길을 가지 않을 것입니다.

당신이 가지고있는 가장 가까운 것은 __call() 마법의 방법입니다 . 이것은 __autoload()함수가 아니라 일종의 for 메소드입니다. 귀하의 필요에 충분할 수 있습니다. 클래스를 호출 할 여유가 있고 각기 다른 기능이 별도로 필요할 경우. PHP 5.3.0부터 __callStatic().

다음을 사용하는 예 __callStatic():

class Test
{
    public function __callStatic($m, $args)
    {
        if (function_exists($m) !== true)
        {
            if (is_file('./path/to/functions/' . $m . '.php') !== true)
            {
                return false;
            }

            require('./path/to/functions/' . $m . '.php');
        }

        return call_user_func_array($m, $args);
    }
}

Test::functionToLoad(1, 2, 3);

이것은 functionToLoad()./path/to/functions/functionToLoad.php에 정의 된 함수를 호출합니다 .


음, 평소와 같이 PECL 확장이 있습니다.

(통해 : http://phk.tekwire.net/joomla/support/doc/automap.htm )

함수와 클래스를 자동로드해야합니다. 그러나 현재 PHP 인터프리터에서는 아직 작동하지 않습니다.

(대체 옵션 btw는 네임 스페이스가있는 대응 요소를로드하고 실행하는 스텁 함수를 생성하는 것입니다.)

그렇게 말하고 있습니다. 자동 로딩은 보편적으로 좋은 방법으로 간주되지 않습니다. 그것은 지나치게 분열 된 클래스 계층과 객체의 행복으로 이어집니다. 그리고 PHP가 자동 로딩을하는 진짜 이유는 포함과 의존성 관리 시스템이 미숙하기 때문입니다.


namespace MyNamespace;

class Fn {

    private function __construct() {}
    private function __wakeup() {}
    private function __clone() {}

    public static function __callStatic($fn, $args) {
        if (!function_exists($fn)) {
            $fn = "YOUR_FUNCTIONS_NAMESPACE\\$fn";
            require str_replace('\\', '/', $fn) . '.php';
        }
        return call_user_func_array($fn, $args);
    }

}

네임 스페이스를 사용하여 다음 Fn::myFunc()같이 할 수 있습니다. spl_autoload_register(). https://goo.gl/8dMIMj 에서 예제와 함께이 코드를 사용했습니다.


나는 Class와 __invoke를 사용합니다 . __invoke메서드는 스크립트가 클래스를 함수로 호출 할 때 호출됩니다. 나는 종종 다음과 같이한다.

<?php

namespace API\Config;

class Slim {
  function __invoke() {
    return [
      'settings' => [
        'displayErrorDetails' => true,
        'logger' => [
          'name' => 'api',
          'level' => Monolog\Logger\Logger::DEBUG,
          'path' => __DIR__ . '/../../logs/api.log',
        ],
      ]
    ];
  }
}

그런 다음 함수처럼 호출 할 수 있습니다.

$config = API\Config\Slim;
$app = Slim\App($config())

new Functions \ Debug ()는 함수를 루트 네임 스페이스로로드합니다.

네임 스페이스 함수
{

    디버그 클래스
    {
    }
}
네임 스페이스
{

    if (! function_exists ( 'printr')) {

        / **
         *
         * @param 혼합 $ expression
         * /
        함수 printr ()
        {
            foreach (func_get_args () as $ v) {
                if (is_scalar ($ v)) {
                    echo $ v. "\엔";
                } else {
                    print_r ($ v);
                }
            }
            출구();
        }
    }
}

이 토론의 제안을 기반으로 한 다소 복잡한 또 다른 예가 있습니다. 코드는 여기에서도 볼 수 있습니다 : lib / btr.php

<?php
/**
 * A class that is used to autoload library functions.
 *
 * If the function btr::some_function_name() is called, this class
 * will convert it into a call to the function
 * 'BTranslator\some_function_name()'. If such a function is not
 * declared then it will try to load these files (in this order):
 *   - fn/some_function_name.php
 *   - fn/some_function.php
 *   - fn/some.php
 *   - fn/some/function_name.php
 *   - fn/some/function.php
 *   - fn/some/function/name.php
 * The first file that is found will be loaded (with require_once()).
 *
 * For the big functions it makes more sense to declare each one of them in a
 * separate file, and for the small functions it makes more sense to declare
 * several of them in the same file (which is named as the common prefix of
 * these files). If there is a big number of functions, it can be more
 * suitable to organize them in subdirectories.
 *
 * See: http://stackoverflow.com/questions/4737199/autoloader-for-functions
 */
class btr {
  /**
   * Make it TRUE to output debug info on '/tmp/btr.log'.
   */
  const DEBUG = FALSE;

  /**
   * The namespace of the functions.
   */
  const NS = 'BTranslator';

  /**
   * Relative directory where the functions are located.
   */
  const FN = 'fn';

  private function __construct() {}
  private function __wakeup() {}
  private function __clone() {}

  /**
   * Return the full name (with namespace) of the function to be called.
   */
  protected static function function_name($function) {
    return self::NS . '\\' . $function;
  }

  /**
   * Return the full path of the file to be loaded (with require_once).
   */
  protected static function file($fname) {
    return dirname(__FILE__) . '/' . self::FN . '/' . $fname . '.php';
  }

  /**
   * If a function does not exist, try to load it from the proper file.
   */
  public static function __callStatic($function, $args) {
    $btr_function = self::function_name($function);
    if (!function_exists($btr_function)) {
      // Try to load the file that contains the function.
      if (!self::load_search_dirs($function) or !function_exists($btr_function)) {
        $dir = dirname(self::file($fname));
        $dir = str_replace(DRUPAL_ROOT, '', $dir);
        throw new Exception("Function $btr_function could not be found on $dir");
      }
    }
    return call_user_func_array($btr_function, $args);
  }

  /**
   * Try to load files from subdirectories
   * (by replacing '_' with '/' in the function name).
   */
  protected static function load_search_dirs($fname) {
    do {
      self::debug($fname);
      if (file_exists(self::file($fname))) {
        require_once(self::file($fname));
        return TRUE;
      }
      if (self::load_search_files($fname)) {
        return TRUE;
      }
      $fname1 = $fname;
      $fname = preg_replace('#_#', '/', $fname, 1);
    } while ($fname != $fname1);

    return FALSE;
  }

  /**
   * Try to load files from different file names
   * (by removing the part after the last undescore in the functin name).
   */
  protected static function load_search_files($fname) {
    $fname1 = $fname;
    $fname = preg_replace('/_[^_]*$/', '', $fname);
    while ($fname != $fname1) {
      self::debug($fname);
      if (file_exists(self::file($fname))) {
        require_once(self::file($fname));
        return TRUE;
      }
      $fname1 = $fname;
      $fname = preg_replace('/_[^_]*$/', '', $fname);
    }

    return FALSE;
  }

  /**
   * Debug the order in which the files are tried to be loaded.
   */
  public static function debug($fname) {
    if (!self::DEBUG) {
      return;
    }
    $file = self::file($fname);
    $file = str_replace(DRUPAL_ROOT, '', $file);
    self::log($file, 'Autoload');
  }

  /**
   * Output the given parameter to a log file (useful for debugging).
   */
  public static function log($var, $comment ='') {
    $file = '/tmp/btr.log';
    $content = "\n==> $comment: " . print_r($var, true);
    file_put_contents($file, $content, FILE_APPEND);
  }
}

While you can't autoload functions and constants, you can use something like jesseschalken/autoload-generator which will automatically detect what files contain things which can't be autoloaded and load them eagerly.


Include all functions file in one file and then include it

//File 1
db_fct.php

//File 2
util_fct.php

//In a functions.php include all other files

<?php

require_once 'db_fct.php';
require_once 'util_fct.php';
?>

Include functions.php whenever you need functions ..


try this

if ($handle = opendir('functions')) {
    while (false !== ($entry = readdir($handle))) {
        if (strpos($entry, '.php') !== false) {
            include("functions/$entry");
        }
    }
    closedir($handle);
}

ReferenceURL : https://stackoverflow.com/questions/4737199/autoloader-for-functions

반응형