php - wordpress get post title



自動加載器的功能 (7)

上週我了解到,通過編寫__autoload()函數可以將類包含在項目中。 然後我了解到使用自動加載器不僅是一種技術,也是一種模式。

現在我在我的項目中使用自動加載器,我發現它非常有用。 我想知道是否可以用功能做同樣的事情。 忘記在其中包含帶有函數的正確PHP文件可能非常有用。

那麼,是否可以創建一個功能自動加載器?

https://code.i-harness.com


具有自動加載功能的新函數\ Debug()將函數加載到根命名空間。

namespace Functions
{

    class Debug
    {
    }
}
namespace
{

    if (! function_exists('printr')) {

        /**
         *
         * @param mixed $expression
         */
        function printr()
        {
            foreach (func_get_args() as $v) {
                if (is_scalar($v)) {
                    echo $v . "\n";
                } else {
                    print_r($v);
                }
            }
            exit();
        }
    }
}

函數沒有函數自動加載器。 你有四個現實的解決方案:

  1. 將所有函數包裝到命名空間類(適當的上下文)中。 所以假設你有一個名為string_get_letters的函數。 您可以將其添加到名為StringFunctions的類作為靜態函數。 因此,不要調用string_get_letters() ,而是調用StringFunctions::get_letters() 。 然後,您將__autoload這些命名空間類。

  2. 預加載所有功能。 由於您正在使用類,因此您不應該使用那麼多函數,因此只需預先加載它們即可。

  3. 在使用之前加載函數。 在每個文件中, require_once將在該文件中使用的函數文件。

  4. 首先不要使用功能。 如果你正在開發OOP代碼(無論如何你似乎都是這樣),根本不需要函數。 你需要一個函數(或多個)的所有東西,你可以以OO方式構建並避免需要函數。

就個人而言,我建議使用1,2或4,具體取決於您的確切需求以及代碼庫的質量和大小......


好吧,像往常一樣,有一個PECL擴展:

(來自: http://phk.tekwire.net/joomla/support/doc/automap.htmhttp://phk.tekwire.net/joomla/support/doc/automap.htm

它應該自動加載函數以及類。 然而,這對當前的PHP解釋器不起作用。

(另一種選擇btw,是生成加載和運行命名空間對應項的存根函數。)

話雖如此。 自動加載並不是普遍認為的好習慣。 它導致階級等級和對象幸福感過度分裂。 PHP具有自動加載的真正原因是因為包含和依賴管理系統不成熟。


如果您在項目中使用Composer,則可以將files指令添加到自動加載部分。

這將實際上在自動加載器中生成require_once,但感覺就像真正的自動加載,因為你不必處理它。
雖然它不是懶惰的裝載。

Assetic獲取的Assetic

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

我讀了一段關於一個醜陋的黑客,它發現了致命的錯誤並試圖包含並執行缺失的函數,但我肯定不會走那條路。

你最接近的是__call() 魔術方法 ,它是方法__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);

這將調用./path/to/functions/functionToLoad.php中定義的functionToLoad()函數。


這是另一個相當複雜的例子,基於本討論中的建議。 代碼也可以在這裡看到: 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://.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);
  }
}

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/8dMIMjhttps://goo.gl/8dMIMj





autoloader