Intereting Posts
wp_publish_post для сохранения черновиков, постоянных ссылок Установите дату истечения срока действия сообщения из Frontend с помощью wp_insert_post Как правильно вставлять данные в пользовательскую таблицу через плагин Как эхо-описание тега на loop-page.php с использованием WPeC 3.8 Проблема с wp_nav_menu, отображающая пользовательскую навигацию Переписывание URL с 3 настраиваемыми мета-полями для добавления на страницы как редактировать пользовательские поля галереи типов из front-end Как разрешить удаление прав на редактирование роли пользователя Добавьте пароли в config.yml для управления несколькими сайтами Использовать has_filter в comment_post Добавление атрибута продукта в постоянную ссылку в WooCommerce Получить идентификатор родительской страницы / меню текущего сообщения Могу ли я помешать авторам изменить шрифт в своем сообщении? Название раздела для меню в настройке темы Как получить список всех перехватчиков текущей темы / плагина?

Использование pre_get_posts на реальных страницах и статических передних страницах

Я провел довольно обширные исследования о том, как использовать pre_get_posts на настоящих страницах и статических передних страницах, и кажется, что нет способа доказательства дурака.

Лучший вариант, который я нашел на сегодняшний день, – это сообщение, сделанное @birgire на Stackoverflow . Я переписал его в демонстрационный класс и сделал код более динамичным

 class PreGeTPostsForPages { /** * @var string|int $pageID * @access protected * @since 1.0.0 */ protected $pageID; /** * @var bool $injectPageIntoLoop * @access protected * @since 1.0.0 */ protected $injectPageIntoLoop; /** * @var array $args * @access protected * @since 1.0.0 */ protected $args; /** * @var int $validatedPageID * @access protected * @since 1.0.0 */ protected $validatedPageID = 0; /** * Constructor * * @param string|int $pageID = NULL * @param bool $injectPageIntoLoop = false * @param array| $args = [] * @since 1.0.0 */ public function __construct( $pageID = NULL, $injectPageIntoLoop = true, $args = [] ) { $this->pageID = $pageID; $this->injectPageIntoLoop = $injectPageIntoLoop; $this->args = $args; } /** * Private method validatePageID() * * Validates the page ID passed * * @since 1.0.0 */ private function validatePageID() { $validatedPageID = filter_var( $this->pageID, FILTER_VALIDATE_INT ); $this->validatedPageID = $validatedPageID; } /** * Public method init() * * This method is used to initialize our pre_get_posts action * * @since 1.0.0 */ public function init() { // Load the correct actions according to the value of $this->keepPageIntegrity add_action( 'pre_get_posts', [$this, 'preGetPosts'] ); } /** * Protected method pageObject() * * Gets the queried object to use that as page object * * @since 1.0.0 */ protected function pageObject() { global $wp_the_query; return $wp_the_query->get_queried_object(); } /** * Public method preGetPosts() * * This is our call back method for the pre_get_posts action. * * The pre_get_posts action will only be used if the page integrity is * not an issue, which means that the page will be altered to work like a * normal archive page. Here you have the option to inject the page object as * first post through the_posts filter when $this->injectPageIntoLoop === true * * @since 1.0.0 */ public function preGetPosts( \WP_Query $q ) { // Make sure that we are on the main query and the desired page if ( is_admin() // Only run this on the front end || !$q->is_main_query() // Only target the main query || !is_page( $this->validatedPageID ) // Run this only on the page specified ) return; // Remove the filter to avoid infinte loops remove_filter( current_filter(), [$this, __METHOD__] ); // METHODS: $this->validatePageID(); $this->pageObject(); $queryArgs = $this->args; // Set default arguments which cannot be changed $queryArgs['pagename'] = NULL; // We have reached this point, lets do what we need to do foreach ( $queryArgs as $key=>$value ) $q->set( filter_var( $key, FILTER_SANITIZE_STRING ), $value // Let WP_Query handle the sanitation of the values accordingly ); // Set $q->is_singular to 0 to get pagination to work $q->is_singular = false; // FILTERS: add_filter( 'the_posts', [$this, 'addPageAsPost'], PHP_INT_MAX ); add_filter( 'template_include', [$this, 'templateInclude'], PHP_INT_MAX ); } /** * Public callback method hooked to 'the_posts' filter * This will inject the queried object into the array of posts * if $this->injectPageIntoLoop === true * * @since 1.0.0 */ public function addPageAsPost( $posts ) { // Inject the page object as a post if $this->injectPageIntoLoop == true if ( true === $this->injectPageIntoLoop ) return array_merge( [$this->pageObject()], $posts ); return $posts; } /** * Public call back method templateInclude() for the template_include filter * * @since 1.0.0 */ public function templateInclude( $template ) { // Remove the filter to avoid infinte loops remove_filter( current_filter(), [$this, __METHOD__] ); // Get the page template saved in db $pageTemplate = get_post_meta( $this->validatedPageID, '_wp_page_template', true ); // Make sure the template exists before we load it, but only if $template is not 'default' if ( 'default' !== $pageTemplate ) { $locateTemplate = locate_template( $pageTemplate ); if ( $locateTemplate ) return $template = $locateTemplate; } /** * If $template returned 'default', or the template is not located for some reason, * we need to get and load the template according to template hierarchy * * @uses get_page_template() */ return $template = get_page_template(); } } $init = new PreGeTPostsForPages( 251, // Page ID false, [ 'posts_per_page' => 3, 'post_type' => 'post' ] ); $init->init(); 

Это хорошо работает и на странице, как и ожидалось, используя мою собственную функцию разбиения на страницы .

ВОПРОСЫ:

Из-за этой функции я теряю целостность страницы, которая заставляет другие функции полагаться на объект страницы, хранящийся в $post . $post до того, как цикл будет установлен на первое сообщение в цикле, а $post будет установлено на последний пост в цикле после цикла, который ожидается. Мне нужно, чтобы $post был установлен на текущий объект страницы, т. Е. На запрашиваемый объект.

Кроме того, сообщение $wp_the_query->post и $wp_query->post содержит первое сообщение в цикле, а не запрашиваемый объект, как на обычной странице

Я использую следующее ( вне моего класса ), чтобы проверить мои глобальные значения до и после цикла

 add_action( 'wp_head', 'printGlobals' ); add_action( 'wp_footer', 'printGlobals' ); function printGlobals() { $global_test = 'QUERIED OBJECT: ' . $GLOBALS['wp_the_query']->queried_object_id . '</br>'; $global_test .= 'WP_THE_QUERY: ' . $GLOBALS['wp_the_query']->post->ID . '</br>'; $global_test .= 'WP_QUERY: ' . $GLOBALS['wp_query']->post->ID . '</br>'; $global_test .= 'POST: ' . $GLOBALS['post']->ID . '</br>'; $global_test .= 'FOUND_POSTS: ' . $GLOBALS['wp_query']->found_posts . '</br>'; $global_test .= 'MAX_NUM_PAGES: ' . $GLOBALS['wp_query']->max_num_pages . '</br>'; ?><pre><?php var_dump( $global_test ); ?></pre><?php } 

ПЕРЕД ЛОПОМ:

Перед циклом проблема частично решена путем установки $injectPageIntoLoop в true, которая вводит объект страницы в качестве первой страницы в цикле. Это очень полезно, если вам нужно показывать информацию о странице до запрошенных сообщений, но если вы этого не хотите, вы ввернуты.

Я могу решить проблему до цикла, напрямую взломав глобальные переменные, что мне не очень нравится. Я подключаю следующий метод к wp внутри моего метода preGetPosts

 public function wp() { $page = get_post( $this->pageID ); $GLOBALS['wp_the_query']->post = $page; $GLOBALS['wp_query'] = $GLOBALS['wp_the_query']; $GLOBALS['post'] = $page; } 

и внутри метода preGetPosts

 add_action( 'wp', [$this, 'wp'] ); 

Из этого, $wp_the_query->post , $wp_query->post и $post все удерживает объект страницы.

ПОСЛЕ ПОТЕРИ

Вот где моя большая проблема, после цикла. После взлома глобалов через крючок и метод wp ,

  • $wp_the_query->post и $wp_query->post возвращаются к первому сообщению в цикле, как и ожидалось

  • $post устанавливается на последнее сообщение в цикле.

Мне нужно, чтобы все три были возвращены к объекту запрашиваемого объекта / текущей страницы.

Я попытался подключить метод wp к действию loop_end , который не работает. get_sidebar метода wp к действию get_sidebar работает, но уже слишком поздно.

 add_action( 'get_sidebar', [$this, 'wp'] ); 

Запуск printGlobals() непосредственно после того, как цикл в шаблоне подтверждает, что по мере того, как $wp_the_query->post и $wp_query->post по-прежнему устанавливаются в первый пост и $post до последнего сообщения.

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

Есть ли подходящий способ решить эту проблему, когда вы запускаете pre_get_posts на странице истинной страницы и статической страницы и сохраняете целостность $wp_the_query->post , $wp_query->post и $post ( с теми, которые установлены на запрошенный объект ) до и после цикла.

РЕДАКТИРОВАТЬ

Кажется, есть путаница в том, что мне нужно и зачем мне это нужно

Что мне нужно

Мне нужно сохранить значения $wp_the_query->post , $wp_query->post и $post через шаблон независимо, и это значение должно быть запрошенным объектом. На этом этапе, с кодом, который я опубликовал, значения этих трех переменных не содержат объект страницы, а скорее пост-объекты сообщений в цикле. Надеюсь, это достаточно ясно.

Я опубликовал код, который вы можете использовать для проверки этих переменных

Зачем мне это нужно

Мне нужен надежный способ добавления сообщений через pre_get_posts к шаблонам страниц и статическим передним страницам без изменения полной функциональности страницы. На этом этапе, когда речь идет о коде, он прерывает функцию breadcrumb и связанную с ней страницу после цикла из-за $post который содержит «неправильный» пост-объект.

Прежде всего, я не хочу напрямую изменять шаблоны страниц. Я хочу иметь возможность добавлять сообщения к шаблону страницы без каких-либо изменений в шаблон

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

ЗАМЕТКА:

Если кто-нибудь сможет разобраться с вопросами в моем вопросе, не стесняйтесь публиковать ответ. Кроме того, если у вас есть какое-либо другое решение, вы также можете отправить ответ.

ЗАВЕРШЕННЫЙ КЛАСС И РЕШЕНИЕ:

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

Используя post-инъекцию, я могу сохранить целостность почты, поэтому $wp_the_query->post , $wp_query->post , $posts и $post остаются постоянными по всему шаблону, все они содержат только текущий объект страницы, с истинными страницами. Таким образом, такие функции, как панировочные сундуки, по-прежнему считают, что текущая страница – это настоящая страница, а не какой-то архив

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

ВОПРОС ПОСЛЕ ИНЪЕКЦИИ

Чтобы выполнить пост-инъекцию, я использовал специальный запрос для возврата сообщений, необходимых для инъекций. Я также использовал свойство $found_pages пользовательского запроса, чтобы настроить основной запрос, чтобы получить разбиение на страницы из основного запроса. Сообщения вводятся в основной запрос посредством действия loop_end .

Чтобы сделать пользовательский запрос доступным и полезным вне класса, я ввел несколько действий.

  • Клочки для разбивки на страницы, чтобы перехватывать функции разбивки на страницы:

    • pregetgostsforgages_before_loop_pagination

    • pregetgostsforgages_after_loop_pagination

  • Пользовательский счетчик, который подсчитывает сообщения в цикле. Эти действия могут использоваться для изменения того, как сообщения отображаются внутри цикла в соответствии с номером сообщения

    • pregetgostsforgages_counter_before_template_part

    • pregetgostsforgages_counter_after_template_part

  • Общий доступ для доступа к объекту запроса и текущему объекту post

    • pregetgostsforgages_current_post_and_object

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

Я также использовал get_template_part() , чтобы загрузить часть шаблона, которая будет использоваться для отображения сообщений. Большинство тем сегодня используют шаблонные части, что делает это очень полезным в классе. Если ваша тема использует content.php , вы можете просто передать content в $templatePart для загрузки content.php .

Если вам нужна поддержка формата post для шаблонных частей, это легко, вы все равно можете просто передать content в $templatePart и просто установить $postFormatSupport в true а content-video.php части шаблона content-video.php будет загружено для сообщения с почтовым форматом video

ГЛАВНЫЙ ЗАПРОС

Следующие изменения были внесены в основной запрос через соответствующие фильтры и действия

  • Для разбивки основного запроса:

    • $found_posts свойства $found_posts запроса инжектора переходит к значению основного объекта запроса через фильтр found_posts

    • Задайте значение переданного пользователем параметра posts_per_page для основного запроса через pre_get_posts

    • $max_num_pages рассчитывается с использованием количества сообщений в $found_posts и posts_per_page . Поскольку is_singular верно на страницах, он запрещает установку LIMIT . Просто установка is_singular в false вызвало несколько проблем, поэтому я решил установить предложение LIMIT через фильтр post_limits . Я сохранил offset предложения LIMIT равным 0 чтобы избежать 404 на страничных страницах

Это касается разбиения на страницы и любой проблемы, которая может возникнуть в результате пост-инъекции

ОБЪЕКТ СТРАНИЦЫ

Текущий объект страницы доступен для отображения в виде сообщения, используя цикл по умолчанию на странице, отдельно и поверх введенных сообщений. Если вам это не нужно, вы можете просто установить для параметра $removePageFromLoop значение true, это скроет содержимое страницы.

На этом этапе я использую CSS, чтобы скрыть объект страницы через действия loop_start и loop_end поскольку я не могу найти другой способ сделать это. Недостатком этого метода является то, что все, что the_post крюком действия the_post внутри основного запроса, также будет скрыто по умолчанию, если вы the_post объект страницы.

КЛАСС

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

Используйте, изменяйте и злоупотребляйте по своему усмотрению. Код хорошо прокомментирован, поэтому его следует легко отслеживать и настраивать

 class PreGetPostsForPages { /** * @var string|int $pageID * @access protected * @since 1.0.0 */ protected $pageID; /** * @var string $templatePart * @access protected * @since 1.0.0 */ protected $templatePart; /** * @var bool $postFormatSupport * @access protected * @since 1.0.0 */ protected $postFormatSupport; /** * @var bool $removePageFromLoop * @access protected * @since 1.0.0 */ protected $removePageFromLoop; /** * @var array $args * @access protected * @since 1.0.0 */ protected $args; /** * @var array $mergedArgs * @access protected * @since 1.0.0 */ protected $mergedArgs = []; /** * @var NULL|\stdClass $injectorQuery * @access protected * @since 1.0.0 */ protected $injectorQuery = NULL; /** * @var int $validatedPageID * @access protected * @since 1.0.0 */ protected $validatedPageID = 0; /** * Constructor method * * @param string|int $pageID The ID of the page we would like to target * @param string $templatePart The template part which should be used to display posts * @param string $postFormatSupport Should get_template_part support post format specific template parts * @param bool $removePageFromLoop Should the page content be displayed or not * @param array $args An array of valid arguments compatible with WP_Query * * @since 1.0.0 */ public function __construct( $pageID = NULL, $templatePart = NULL, $postFormatSupport = false, $removePageFromLoop = false, $args = [] ) { $this->pageID = $pageID; $this->templatePart = $templatePart; $this->postFormatSupport = $postFormatSupport; $this->removePageFromLoop = $removePageFromLoop; $this->args = $args; } /** * Public method init() * * The init method will be use to initialize our pre_get_posts action * * @since 1.0.0 */ public function init() { // Initialise our pre_get_posts action add_action( 'pre_get_posts', [$this, 'preGetPosts'] ); } /** * Private method validatePageID() * * Validates the page ID passed * * @since 1.0.0 */ private function validatePageID() { $validatedPageID = filter_var( $this->pageID, FILTER_VALIDATE_INT ); $this->validatedPageID = $validatedPageID; } /** * Private method mergedArgs() * * Merge the default args with the user passed args * * @since 1.0.0 */ private function mergedArgs() { // Set default arguments if ( get_query_var( 'paged' ) ) { $currentPage = get_query_var( 'paged' ); } elseif ( get_query_var( 'page' ) ) { $currentPage = get_query_var( 'page' ); } else { $currentPage = 1; } $default = [ 'suppress_filters' => true, 'ignore_sticky_posts' => 1, 'paged' => $currentPage, 'posts_per_page' => get_option( 'posts_per_page' ), // Set posts per page here to set the LIMIT clause etc 'nopaging' => false ]; $mergedArgs = wp_parse_args( (array) $this->args, $default ); $this->mergedArgs = $mergedArgs; } /** * Public method preGetPosts() * * This is the callback method which will be hooked to the * pre_get_posts action hook. This method will be used to alter * the main query on the page specified by ID. * * @param \stdClass WP_Query The query object passed by reference * @since 1.0.0 */ public function preGetPosts( \WP_Query $q ) { if ( !is_admin() // Only target the front end && $q->is_main_query() // Only target the main query && $q->is_page( filter_var( $this->validatedPageID, FILTER_VALIDATE_INT ) ) // Only target our specified page ) { // Remove the pre_get_posts action to avoid unexpected issues remove_action( current_action(), [$this, __METHOD__] ); // METHODS: // Initialize our method which will return the validated page ID $this->validatePageID(); // Initiale our mergedArgs() method $this->mergedArgs(); // Initiale our custom query method $this->injectorQuery(); /** * We need to alter a couple of things here in order for this to work * - Set posts_per_page to the user set value in order for the query to * to properly calculate the $max_num_pages property for pagination * - Set the $found_posts property of the main query to the $found_posts * property of our custom query we will be using to inject posts * - Set the LIMIT clause to the SQL query. By default, on pages, `is_singular` * returns true on pages which removes the LIMIT clause from the SQL query. * We need the LIMIT clause because an empty limit clause inhibits the calculation * of the $max_num_pages property which we need for pagination */ if ( $this->mergedArgs['posts_per_page'] && true !== $this->mergedArgs['nopaging'] ) { $q->set( 'posts_per_page', $this->mergedArgs['posts_per_page'] ); } elseif ( true === $this->mergedArgs['nopaging'] ) { $q->set( 'posts_per_page', -1 ); } // FILTERS: add_filter( 'found_posts', [$this, 'foundPosts'], PHP_INT_MAX, 2 ); add_filter( 'post_limits', [$this, 'postLimits']); // ACTIONS: /** * We can now add all our actions that we will be using to inject our custom * posts into the main query. We will not be altering the main query or the * main query's $posts property as we would like to keep full integrity of the * $post, $posts globals as well as $wp_query->post. For this reason we will use * post injection */ add_action( 'loop_start', [$this, 'loopStart'], 1 ); add_action( 'loop_end', [$this, 'loopEnd'], 1 ); } } /** * Public method injectorQuery * * This will be the method which will handle our custom * query which will be used to * - return the posts that should be injected into the main * query according to the arguments passed * - alter the $found_posts property of the main query to make * pagination work * * @link https://codex.wordpress.org/Class_Reference/WP_Query * @since 1.0.0 * @return \stdClass $this->injectorQuery */ public function injectorQuery() { //Define our custom query $injectorQuery = new \WP_Query( $this->mergedArgs ); // Update the thumbnail cache update_post_thumbnail_cache( $injectorQuery ); $this->injectorQuery = $injectorQuery; return $this->injectorQuery; } /** * Public callback method foundPosts() * * We need to set found_posts in the main query to the $found_posts * property of the custom query in order for the main query to correctly * calculate $max_num_pages for pagination * * @param string $found_posts Passed by reference by the filter * @param stdClass \WP_Query Sq The current query object passed by refence * @since 1.0.0 * @return $found_posts */ public function foundPosts( $found_posts, \WP_Query $q ) { if ( !$q->is_main_query() ) return $found_posts; remove_filter( current_filter(), [$this, __METHOD__] ); // Make sure that $this->injectorQuery actually have a value and is not NULL if ( $this->injectorQuery instanceof \WP_Query && 0 != $this->injectorQuery->found_posts ) return $found_posts = $this->injectorQuery->found_posts; return $found_posts; } /** * Public callback method postLimits() * * We need to set the LIMIT clause as it it is removed on pages due to * is_singular returning true. Witout the limit clause, $max_num_pages stays * set 0 which avoids pagination. * * We will also leave the offset part of the LIMIT cluase to 0 to avoid paged * pages returning 404's * * @param string $limits Passed by reference in the filter * @since 1.0.0 * @return $limits */ public function postLimits( $limits ) { $posts_per_page = (int) $this->mergedArgs['posts_per_page']; if ( $posts_per_page && -1 != $posts_per_page // Make sure that posts_per_page is not set to return all posts && true !== $this->mergedArgs['nopaging'] // Make sure that nopaging is not set to true ) { $limits = "LIMIT 0, $posts_per_page"; // Leave offset at 0 to avoid 404 on paged pages } return $limits; } /** * Public callback method loopStart() * * Callback function which will be hooked to the loop_start action hook * * @param \stdClass \WP_Query $q Query object passed by reference * @since 1.0.0 */ public function loopStart( \WP_Query $q ) { /** * Although we run this action inside our preGetPosts methods and * and inside a main query check, we need to redo the check here aswell * because failing to do so sets our div in the custom query output as well */ if ( !$q->is_main_query() ) return; /** * Add inline style to hide the page content from the loop * whenever $removePageFromLoop is set to true. You can * alternatively alter the page template in a child theme by removing * everything inside the loop, but keeping the loop * Example of how your loop should look like: * while ( have_posts() ) { * the_post(); * // Add nothing here * } */ if ( true === $this->removePageFromLoop ) echo '<div style="display:none">'; } /** * Public callback method loopEnd() * * Callback function which will be hooked to the loop_end action hook * * @param \stdClass \WP_Query $q Query object passed by reference * @since 1.0.0 */ public function loopEnd( \WP_Query $q ) { /** * Although we run this action inside our preGetPosts methods and * and inside a main query check, we need to redo the check here as well * because failing to do so sets our custom query into an infinite loop */ if ( !$q->is_main_query() ) return; // See the note in the loopStart method if ( true === $this->removePageFromLoop ) echo '</div>'; //Make sure that $this->injectorQuery actually have a value and is not NULL if ( !$this->injectorQuery instanceof \WP_Query ) return; // Setup a counter as wee need to run the custom query only once static $count = 0; /** * Only run the custom query on the first run of the loop. Any consecutive * runs (like if the user runs the loop again), the custom posts won't show. */ if ( 0 === (int) $count ) { // We will now add our custom posts on loop_end $this->injectorQuery->rewind_posts(); // Create our loop if ( $this->injectorQuery->have_posts() ) { /** * Fires before the loop to add pagination. * * @since 1.0.0 * * @param \stdClass $this->injectorQuery Current object (passed by reference). */ do_action( 'pregetgostsforgages_before_loop_pagination', $this->injectorQuery ); // Add a static counter for those who need it static $counter = 0; while ( $this->injectorQuery->have_posts() ) { $this->injectorQuery->the_post(); /** * Fires before get_template_part. * * @since 1.0.0 * * @param int $counter (passed by reference). */ do_action( 'pregetgostsforgages_counter_before_template_part', $counter ); /** * Fires before get_template_part. * * @since 1.0.0 * * @param \stdClass $this->injectorQuery-post Current post object (passed by reference). * @param \stdClass $this->injectorQuery Current object (passed by reference). */ do_action( 'pregetgostsforgages_current_post_and_object', $this->injectorQuery->post, $this->injectorQuery ); /** * Load our custom template part as set by the user * * We will also add template support for post formats. If $this->postFormatSupport * is set to true, get_post_format() will be automatically added in get_template part * * If you have a template called content-video.php, you only need to pass 'content' * to $template part and then set $this->postFormatSupport to true in order to load * content-video.php for video post format posts */ $part = ''; if ( true === $this->postFormatSupport ) $part = get_post_format( $this->injectorQuery->post->ID ); get_template_part( filter_var( $this->templatePart, FILTER_SANITIZE_STRING ), $part ); /** * Fires after get_template_part. * * @since 1.0.0 * * @param int $counter (passed by reference). */ do_action( 'pregetgostsforgages_counter_after_template_part', $counter ); $counter++; //Update the counter } wp_reset_postdata(); /** * Fires after the loop to add pagination. * * @since 1.0.0 * * @param \stdClass $this->injectorQuery Current object (passed by reference). */ do_action( 'pregetgostsforgages_after_loop_pagination', $this->injectorQuery ); } } // Update our static counter $count++; } } 

ПРИМЕНЕНИЕ

Теперь вы можете инициировать класс ( также в своем плагине или файле функций ), как показано ниже, для целевой страницы с идентификатором 251, на котором мы покажем 2 сообщения на страницу из типа post post

 $query = new PreGetPostsForPages( 251, // Page ID we will target 'content', //Template part which will be used to display posts, name should be without .php extension true, // Should get_template_part support post formats false, // Should the page object be excluded from the loop [ // Array of valid arguments that will be passed to WP_Query/pre_get_posts 'post_type' => 'post', 'posts_per_page' => 2 ] ); $query->init(); 

ДОБАВЛЕНИЕ ПЕЧАТИ И ТАМОЖЕННЫЙ СТИЛЬ

Как я уже сказал, в запросе инжектора есть несколько действий, чтобы добавить разбивку на страницы или пользовательский стиль. Здесь я добавил разбивку на страницы после цикла, используя мою собственную функцию разбиения на страницы из связанного ответа . Кроме того, используя встроенный счетчик, я добавил div для отображения моих сообщений в двух столбцах.

Вот действия, которые я использовал

 add_action( 'pregetgostsforgages_counter_before_template_part', function ( $counter ) { $class = $counter%2 ? ' right' : ' left'; echo '<div class="entry-column' . $class . '">'; }); add_action( 'pregetgostsforgages_counter_after_template_part', function ( $counter ) { echo '</div>'; }); add_action( 'pregetgostsforgages_after_loop_pagination', function ( \WP_Query $q ) { paginated_numbers(); }); 

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

Это конечный результат

введите описание изображения здесь

СТАТИЧЕСКИЕ ПЕРЕДНИЕ СТРАНИЦЫ

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

ВЫВОД

Это может показаться действительно большим количеством накладных расходов, и это может быть, но профессионалы перевешивают большое время конфликта

BIG PRO'S

  • Вам не нужно каким-либо образом изменять шаблон страницы для конкретной страницы. Это делает все динамичным и легко переносится между темами без внесения изменений в код вообще, если все сделано в плагине.

  • В лучшем случае вам нужно только создать часть шаблона content.php в своей теме, если в вашей теме еще нет

  • Любая разбивка на страницы, которая работает в основном запросе, будет работать на странице без каких-либо изменений или чего-либо еще от запроса, передаваемого функции.

Есть больше pro, о которых я не могу сейчас думать, но это важные