私はpre_get_posts、真のページと静的なフロントページでの使用方法について非常に広範な研究を行ってきましたが、絶対確実な方法はないようです。
私がこれまでに見つけた最良のオプションは、Stackoverflowの@birgireによる投稿からのものでした。私はそれをデモクラスに書き直し、コードをもう少し動的にしました
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ループ内の最後の投稿に設定されます。
必要なのは、3つすべてがクエリされたオブジェクト/現在のページオブジェクトに戻されることです。
wpメソッドをloop_endアクションにフックしようとしましたが、動作しません。wpメソッドをget_sidebarアクションにフックすることはできますが、手遅れです。
add_action( 'get_sidebar', [$this, 'wp'] );printGlobals()テンプレートのループの直後に実行する$wp_the_query->postと   、as $wp_query->postがまだ最初の投稿と$post最後の投稿に設定されていることが確認されます。
wpテンプレート内のループの後にメソッド内にコードを手動で追加できますが、テーマ間でプラグインでクラスを転送できるようにするため、アイデアはテンプレートファイルを直接変更することではありません。
一度の実行この問題解決するために任意の適切な方法がありpre_get_posts、まだ真のページ上と静的フロントページとはの整合性を保つには$wp_the_query->post、$wp_query->post、および$post(照会オブジェクトにこれらのセットを持つループの前と後)。
編集
必要なものとそれが必要な理由について混乱があるようです
必要なもの
私は、の値を保持する必要がある$wp_the_query->post、$wp_query->postと$post関係なく、テンプレート間で、その値は、照会オブジェクトでなければなりません。この段階で、私が投稿したコードでは、これら3つの変数の値はページオブジェクトを保持していませんが、ループ内の投稿のオブジェクトを投稿しています。私はそれが十分に明確であることを願っています。
これらの変数をテストするために使用できるコードを投稿しました
なぜ必要なのか
pre_get_postsページ全体の機能を変更せずに、ページテンプレートおよび静的なフロントページに投稿を追加する信頼性の高い方法が必要です。この段階では、問題のコードが立っ$postているため、「間違った」投稿オブジェクトが保持されているため、ループ後にブレッドクラム機能と関連ページ機能が中断さ   れます。
何よりも、ページテンプレートを直接変更したくありません。私はせずにページのテンプレートに投稿を追加できるようにしたいANYテンプレートに変更
