Компилирует ли PHP XPath

Может ли кто-нибудь сказать мне, компилирует ли PHP выражения XPath и когда? Было бы полезно знать как классы simpleXML, так и DOMDocument. Я также хочу знать, где хранится скомпилированный XPath.

Я не знаю ответа, но полагаю, что это будет «то, что делает libxml2», поскольку на этом построены все XML-функциональные возможности PHP. Таким образом, домашняя страница libxml, вероятно, является хорошей отправной точкой для исследования.

IMSoP 22.05.2018 11:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
1
90
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Все функции PHP XML построены на основе библиотека libxml2, поэтому часть ответа будет зависеть от того, как эта библиотека работает, а часть - от того, как именно PHP ее использует.

Начиная с SimpleXML, мы можем найти реализацию SimpleXMLElement->xpath() в ext / simplexml / simplexml.c. Пропустив некоторые внутренние операции, проверку типов параметров и т. д., Первая интересная строка, которую мы находим, такова:

if (!sxe->xpath) {
    sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
}

Таким образом, повторяющиеся выражения XPath на одном и том же SimpleXMLElement будут использовать один и тот же «контекст XPath», но не будут использоваться другими экземплярами. Далее мы находим, где это используется:

retval = xmlXPathEval((xmlChar *)query, sxe->xpath);

Итак, PHP вызывает функцию libxml xmlXPathEval, которая просто берет строку и контекст и немедленно их оценивает. Руководство по libxml для xmlXPathEval` говорит:

Evaluate the XPath Location Path in the given context.

Returns: the xmlXPathObjectPtr resulting from the evaluation or NULL. the caller has to free the object.

И действительно, PHP освобождает этот результат в конце метода:

xmlXPathFreeObject(retval);

Итак, по крайней мере, в SimpleXML нет отдельного шага компиляции, и между вызовами метода ничего не сохраняется.

Версия DOM немного сложнее, потому что в ней есть видимый пользователю объект, представляющий контекст XPath, который определен в /ext/dom/xpath.c. Во-первых, как и следовало ожидать, конструктор устанавливает контекст:

PHP_METHOD(domxpath, __construct)
{
    # ...
    ctx = xmlXPathNewContext(docp);

Затем он творит чудеса, чтобы повторно использовать этот контекст, где это возможно, но мы еще не скомпилировали XPath, это просто контекст, то есть «текущий узел», с которым нужно сравнивать выражения. В определениях как для ->eval(), так и для ->query() используется одна и та же реализация C, php_xpath_eval. Это проверяет правильность некоторого внутреннего состояния, а затем вызывает:

xpathobjp = xmlXPathEvalExpression((xmlChar *) expr, ctxp);

Это другая функция, поэтому мы можем поищи это в libxml:

Function: xmlXPathEvalExpression Alias for xmlXPathEval().

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

xmlXPathFreeObject(xpathobjp);

Итак, как и раньше: нет явной компиляции, и единственное, что хранится между вызовами, - это «контекст», с которым будут выполняться выражения XPath.

Получается libxml поддерживает какой-то кеш, если включить через xmlXPathContextSetCache:

Creates/frees an object cache on the XPath context. If activates XPath objects (xmlXPathObject) will be cached internally to be reused. @options: 0: This will set the XPath object caching: @value: This will set the maximum number of XPath objects to be cached per slot There are 5 slots for: node-set, string, number, boolean, and misc objects. Use <0 for the default number (100). Other values for @options have currently no effect.

В случае SimpleXML этот кеш в любом случае бесполезен, поскольку контекст отбрасывается после использования; для DOM это было бы более уместно, поскольку контекст - и, следовательно, кеш - будет существовать до тех пор, пока объект PHP DOMXPath.

Мы можем покопаться в реализации xmlXpathNewContext, чтобы увидеть, включен или отключен этот кеш по умолчанию:

#ifdef XP_DEFAULT_CACHE_ON
    if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
    xmlXPathFreeContext(ret);
    return(NULL);
    }
#endif

Получается, что это параметр времени компиляции - если для libxml, скомпилированного или загруженного в ваш PHP, этот флаг был установлен при компиляции, я полагаю, что в случае DOM XPath вы будете иметь некоторую степень кэширования, в одном экземпляре DOMXPath`.

Хм, это очень обидно. Спасибо, это отличная детективная работа.

kaan_a 24.05.2018 15:35

@Kaan Меня настораживало, что я просто предположил что-то, поэтому я сделал еще один шаг и добавил, может быть, несколько лучших новостей.

IMSoP 24.05.2018 15:38

Хорошо, так как вы отредактировали свой ответ, это немного менее разочаровывает. Тем не менее, разочарование. Я надеялся, что какой-то скомпилированный код выдержит несколько исполнений. Теперь мне, вероятно, придется изменить свой код, чтобы просто использовать кеш за одно выполнение.

kaan_a 24.05.2018 15:41

Другие вопросы по теме