programing

함수 자동 로더

powerit 2023. 10. 5. 23:35
반응형

함수 자동 로더

는 될 수 것을 .__autoload()기능. 하는 것은 기술뿐만 것을 알게 .그리고 오토로더를 사용하는 것은 기술뿐만 아니라 패턴이라는 것을 알게 되었습니다.

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

그렇다면 기능 오토로더를 만드는 것이 가능한가요?

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

  1. 모든 함수를 네임스페이스 클래스로 래핑합니다(상황에 적합함).예를 들어, 당신은 다음과 같은 기능을 가지고 있다고 가정해 보겠습니다.string_get_letters. 당신은 그것을 다음과 같은 클래스에 추가할 수 있습니다.StringFunctions정적 함수로서그래서 전화 대신에string_get_letters(), 네가 전화할걸StringFunctions::get_letters() 은.__autoload그 이름들은 수업시간을 바꿔놓았습니다.

  2. 모든 기능을 사전 로드합니다.수업을 이용하시니 기능이 그렇게 많지 않으시면 되니 미리 탑재해 두시기 바랍니다.

  3. 기능을 사용하기 전에 로드합니다.각각의 파일에서,require_once해당 파일에 사용될 함수 파일입니다.

  4. 처음부터 기능을 사용하지 마십시오.만약 당신이 OOP 코드를 개발하고 있다면(어차피 당신은 그런 것처럼 보이는), 기능에 대한 필요성이 전혀 없어야 합니다.필요한 모든 기능(또는 다중)을 OOO 방식으로 구축할 수 있으며 기능에 대한 필요성을 피할 수 있습니다.

개인적으로, 당신의 정확한 필요성과 당신의 코드베이스의 질과 크기에 따라 1, 2, 4 중 하나를 제안하고 싶습니다.

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

이렇게 하면 실제로 자동 로더에 required_once가 생성되지만, 이를 처리할 필요가 없기 때문에 실제 자동 로딩처럼 느껴집니다.
귀찮지 않은 로딩입니다.

Assetic에서 가져온 예제:

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

얼마 전에 치명적인 오류를 발견한 추한 해킹에 대한 내용을 읽고 누락된 기능을 포함하여 실행하려고 했지만, 저는 그 길을 가지 않을 것입니다.

있는 가장 은 입니다.__call() 마법의 방법은 일종의 a.__autoload()함수가 아닌 메소드의 경우.클래스를 호출하고 각각의 다른 기능을 개별적으로 요구할 수 있는 여유가 있다면 필요에 충분할 것입니다.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()함수는 ./경로/기능/기능로드합니다.php에 정의되어 있습니다.

통상적으로 PECL 확장 기능이 있습니다.

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

수업뿐만 아니라 기능도 자동으로 불러오기로 되어 있습니다.하지만 현재 PHP 인터프리터에서는 아직 작동하지 않습니다.

(대안 옵션은 네임스피드 대응물을 로드하고 실행하는 스터브 함수를 생성하는 것입니다.)

그런 말이 있습니다.오토로딩은 보편적으로 좋은 방법으로 간주되지 않습니다.그것은 지나치게 계층 구조가 분열되고 사물의 행복을 야기합니다.그리고 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 에서 사용했습니다.

클래스를 사용하고 __invoke. The__invokemethod는 스크립트가 클래스를 함수로 호출할 때 호출됩니다.저는 종종 다음과 같은 일을 합니다.

<?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 (! 함수_ exists('printr') {
/**** @param mixed $expression*/기능프린터{각각(func_get_args () $v) {(is_ scalar($v)) {echo $v. "\n";} 기타 {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);
  }
}

함수와 상수를 자동으로 로드할 수는 없지만 jesseschalken/자동 로드 생성기 같은 것을 사용하면 자동으로 로드할 수 없는 파일을 자동으로 감지하여 열심히 로드할 수 있습니다.

모든 함수 파일을 하나의 파일에 포함시킨 다음 포함

// 1
db_fct.

// 2
phutil_fct.

//함수에서.php는 다른 모든 파일을 포함합니다.

<?php

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

함수를 포함합니다.기능이 필요할때마다 php.

제가 생각해낸 해결책.내가 생각해낼 수 있는 한 가벼운.

class functions {

  public static function __callstatic($function, $arguments) {

    if (!function_exists($function)) {
      $file = strtok($function, '_') .'.php';
      include '/path/to/functions/'.$file;
    }

    return call_user_func_array($function, $arguments);
  }
}

전화로 이용하기functions::foo_bar($anything).

저는 수업의 오토로딩을 유리하게 사용하려고 노력합니다.따라서 클래스가 자동으로 로드되면 클래스 파일이 실행됩니다.그래서 나는 아무것도 하지 않는 '부트'라는 정적인 방법으로 클래스를 만듭니다.이 메서드를 호출하면 클래스가 자동으로 로드되므로 해당 파일의 모든 함수가 전역 범위에서 정의됩니다.더욱 흥미로운 점은 클래스의 네임스페이스에 함수가 정의되어 충돌이 발생하지 않는다는 것입니다.

예를 들어,

<?PHP

namespace Functions;
// functions are defined in this file

class GlobalFunctions{
  public static function boot(){};
}

function foo(){ // code... }
?>

// the client file
<?php
  
  // VS Code automatically does this.
  use Functions\GlobalFunctions;
  use function Functions\foo; 

  // I usually put this in the bootstrap file
  GlobalFunctions::boot();


  
  // call foo() from the Functions namespace
  foo();
?>

이거 먹어봐요.

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

언급URL : https://stackoverflow.com/questions/4737199/autoloader-for-functions

반응형