получить сообщение() против глобального $post или $GLOBAL['сообщение']


Я пишу плагин виджета и мне нужен доступ к информации о публикации.

Я видел людей, использующих 3 разных подхода:

global $post;
if ( isset( $GLOBALS['post'] ) ) $post = $GLOBALS['post'];
$post = get_post();

Этот пост объясняет разницу между первыми двумя решениями. Не могли бы вы подтвердить, что вызов get_post() без аргументов делает то же самое (для только для чтения целей)?

Также, что касается if ( isset( $GLOBALS['post'] ) ): Я думаю, это означает, что post может быть неопределенным. Не мог бы кто-нибудь объяснить, в каком контексте?

В моем случае это виджет на страницах (не публикация). Итак, можно ли с уверенностью предположить, что код виджета, выполняемый после цикла post, в таких случаях всегда определяется как содержимое страницы?

Author: Community, 2016-02-16

1 answers

По сути, для всех технических целей,

get_post() == $post == $GLOBALS['post']

Как @tosho уже объяснял в связанном посте , $post === $GLOBALS['post'], так что я не буду вдаваться в это.

Что нас интересует, так это то, как get_post() одно и то же. Для этого нам нужно будет взглянуть на исходный код . Как вы можете видеть, мы получаем наш ответ в первых двух строках функции, когда мы ничего не передаем get_post()

if ( empty( $post ) && isset( $GLOBALS['post'] ) )
    $post = $GLOBALS['post'];

Что касается if ( isset( $GLOBALS['post'] ) ): Я предполагаю, что это означает, что сообщение может быть не определено.

Да, может, и это зависит от контекста. Кроме того, как и любой глобальный, он также может быть отключен, преднамеренно или неосознанно, что может иметь катастрофические последствия. Именно это делает глобалы такой отвратительной злой вещью для создания и использования. Неосознанное использование глобальных переменных в качестве локальных переменных является причиной номер один (IMO) для неожиданных, не отлаживаемых сбоев кода.

Глобальный параметр $post задается WP_Query::the_post(), но он может быть изменен любым пользовательским кодом, поэтому никогда не полагайтесь на это, особенно вне цикла.

Можно ли с уверенностью предположить, что код виджета выполняется после цикла

НИКОГДА НИКОГДА ничего не предполагайте. Это самая опасная вещь, которую вы когда-либо могли сделать при написании кода. Просто предполагая, что что-то приводит к ужасным ошибкам, лазейкам в системе безопасности, возможно, утечке очень личной информации, которая может привести вас в тюрьму и т. Д. И т. Д. Относитесь ко всему, что вы кодируете, таким образом, чтобы безопасно обрабатывать определенную вещь или поведение, если что-то потерпите неудачу, и всегда используйте код с установкой на то, что ваш код потерпит неудачу, и он будет взломан.

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

Если это настоящая страница (, созданная в разделе "Внутренние страницы" ), то вы можете использовать get_queried_object() для получения текущего объекта страницы. Он намного надежнее, чем глобальный $post. Вам следует не торопиться и прочитать этот ответ, @gmazzap на мой вопрос здесь

РЕДАКТИРОВАТЬ - Лучшая альтернатива get_queried_object()

Из вашего комментария к моему ответу

Я понимаю, что $post может быть изменен до того, как я получу к нему доступ. Но разве это не верно и для $wp_query (изменено с помощью "пользовательских" или "вторичных" запросов)? Если да, то не следует ли мне проверить is_main_query(), прежде чем полагаться на get_queried_object()? Я предполагаю, что основной запрос основан на запрошенном URL-адресе, верно? И если is_main_query() является ложным, что я могу использовать тогда?

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

Верно, что запрашиваемый объект полагается на целостность основного объекта запроса, что делает get_queried_object() уязвимым. В общем, get_queried_object() все еще намного надежнее, чем $post потому что любой пользовательский запрос, использующий the_post() или setup_postdata( $post ), устанавливает глобальный $post в текущую запись в текущем цикле. Забыв сбросить пользовательский запрос с помощью wp_reset_postdata(), вы получите неверный объект post внутри $post.

Что касается get_queried_object(), если кто-то все еще использует query_posts, то им решать, хотят ли они страдать от последствий.

Мне нравится идея, что вы действительно хотели бы и действительно ищете более надежные альтернативы $post И get_queried_object(), это совершенно очевидно из вашего комментария. Ваш комментарий на самом деле вызвал то, над чем я работал некоторое время назад и совершенно забыл, я думаю, что больше всего, включая меня, забывают об одном очень важном глобальном, который никогда не изменяется (, за исключением фильтров и действий внутри WP_Query самого ), и этот глобальный $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] содержит фактический основной объект запроса. $GLOBALS['wp_query'] ( АКА $wp_query) является всего лишь копией $GLOBALS['wp_the_query'].

Давайте быстро посмотрим, где это установлено. В текущей версии (Wordpress 4.4.2), вы найдете следующий код в строках 291 -304 в `wp-settings.php

/**
 * WordPress Query object
 * @global WP_Query $wp_the_query
 * @since 2.0.0
 */
$GLOBALS['wp_the_query'] = new WP_Query();
/**
 * Holds the reference to @see $wp_the_query
 * Use this global for WordPress queries
 * @global WP_Query $wp_query
 * @since 1.5.0
 */
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

Я не знал, когда был WordPress, но, скорее всего, это было сделано для размещения query_posts, потому что если вы посмотрите на wp_reset_query(), который вы должны использовать после query_posts, он сбрасывает $wp_query обратно в $GLOBALS['wp_the_query'].

Все это означает, что, даже если мы нарушим основной объект запроса ($wp_query), у нас все еще есть полностью сохраненная копия в $GLOBALS['wp_the_query'].

Со всеми имея это в виду, если вам действительно нужен надежный способ получения текущего запрашиваемого объекта на 99,99%, это будет $GLOBALS['wp_the_query']->get_queried_object(). Это был бы самый надежный способ без необходимости повторно выполнять основной запрос самостоятельно.

Прежде чем я закончу, вы также говорили о проверке is_main_query() (, которая, по сути, проверяет, равен ли текущий экземпляр WP_Query $GLOBALS['wp_the_query']). В подобном случае это на самом деле не сработало бы, так как оно просто возвращает логическое значение.

ЗАВЕРШЕНИЕ - завершение вверх

Чтобы надежно получить текущий запрашиваемый объект на одной странице публикации или, если на то пошло, на любой отдельной странице и страницах архива, используйте запрашиваемый объект из $GLOBALS['wp_the_query'] глобального

$GLOBALS['wp_the_query']->get_queried_object()
 8
Author: Pieter Goosen, 2017-04-13 12:37:50