Автозагрузчик для функций - PullRequest
51 голосов
/ 19 января 2011

На прошлой неделе я узнал, что классы могут быть включены в ваш проект, написав функцию __autoload(). Затем я узнал, что использование автозагрузчика - это не только техника, но и шаблон.

Теперь я использую автозагрузчик в своем проекте, и я нашел его очень очень полезным. Мне было интересно, можно ли сделать то же самое с функциями. Может быть очень полезно забыть о включении правильного файла PHP с функциями внутри него.

Итак, возможно ли создать автозагрузчик функции?

Ответы [ 11 ]

57 голосов
/ 19 января 2011

Нет функции автозагрузчика для функций.У вас есть четыре реалистичных решения:

  1. Оберните все функции в классы пространства имен (соответствующий контекст).Допустим, у вас есть функция с именем string_get_letters.Вы можете добавить это к классу с именем StringFunctions в качестве статической функции.Поэтому вместо того, чтобы звонить string_get_letters(), вы бы позвонили StringFunctions::get_letters().Затем вы должны __autoload эти классы пространства имен.

  2. Предварительная загрузка всех функций.Поскольку вы используете классы, у вас не должно быть такого количества многих функций, поэтому просто предварительно загрузите их.

  3. Загрузите функции перед их использованием.В каждом файле require_once файлы функций, которые будут использоваться в этом файле.

  4. Во-первых, не используйте функции.Если вы разрабатываете ООП-код (который, как вам кажется, в любом случае), функций вообще не должно быть.Все, для чего вам нужна функция (или несколько), вы могли бы создать ОО-метод и избежать необходимости в функциях.

Лично я бы предложил 1, 2 или 4в зависимости от ваших потребностей, качества и размера вашей кодовой базы ...

32 голосов
/ 29 июля 2013

Если вы используете Composer в своем проекте, вы можете добавить директиву files в раздел автозагрузки.

Это фактически сгенерирует require_once в автозагрузчике, но это похоже на настоящую автозагрузку, потому что вам не нужно об этом заботиться.
Это не ленивая загрузка, хотя.

Пример взят из Assetic :

"autoload": {
        "psr-0": { "Assetic": "src/" },
        "files": [ "src/functions.php" ]
    }
15 голосов
/ 19 января 2011

Некоторое время назад я читал что-то об уродливом хакере, который поймал фатальные ошибки и попытался включить и выполнить отсутствующие функции, но я определенно не пошел бы по этому пути.есть __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);

Это вызовет функцию functionToLoad(), определенную в ./path/to/functions/functionToLoad.php.

7 голосов
/ 19 января 2011

Ну, как обычно, для этого есть расширение PECL:

(через: http://phk.tekwire.net/joomla/support/doc/automap.htm)

Он должен автоматически загружать функции и классы. Что, однако, пока не работает с текущим интерпретатором PHP.

(Между прочим, альтернативная опция - генерировать функции-заглушки, которые загружают и запускают копии пространства имен).

Как говорится. Автозагрузка не всегда считается хорошей практикой. Это приводит к чрезмерно раздробленной иерархии классов и объектному счастью. И настоящая причина, по которой PHP имеет автозагрузку, заключается в том, что системы управления включением и зависимостями являются незрелыми.

2 голосов
/ 15 марта 2014
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

1 голос
/ 25 сентября 2018

Я использую класс и __ 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())
1 голос
/ 28 ноября 2017

new Functions \ 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();
        }
    }
}
0 голосов
/ 21 октября 2016

Включить все файлы функций в один файл, а затем включить его

// Файл 1
db_fct.php

// Файл 2
util_fct.php

// В functions.php включаются все остальные файлы

<?php

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

Включают functions.php всякий раз, когда вам нужны функции ..

0 голосов
/ 29 июля 2015

Хотя вы не можете автоматически загружать функции и константы, вы можете использовать что-то вроде jesseschalken / autoload-generator , которое будет автоматически определять, какие файлы содержат вещи, которые не могут быть автоматически загружены, и загружать их с нетерпением.

0 голосов
/ 20 мая 2015

попробуйте

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