web-dev-qa-db-ja.com

経由で投稿を読み込む AJAX 更新されたURLを持つ隠されたdivに?

AJAXを介して同じインデックスページに投稿を非同期的に読み込むために、以下のコードを使用しています。私もURLを更新できるようにしたいのですが、私が現在持っているものにそれを追加することについてどうやって行けばよいかわからない。

最終目標は これ に似た効果です。投稿をクリックすると、上の非表示のdivに投稿が読み込まれていることがわかり、アドレスバーにもURLが更新されていることがわかります。

誰かが私を手伝ってくれる?

インデックステンプレート

<div id="single-post-container"></div>

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

    <a class="post-link" rel="<?php the_ID(); ?>" href="<?php the_permalink(); ?>">

       <?php the_title(); ?> 

    </a>

<?php endwhile; endif; ?>

単一投稿テンプレート

<?php

    $post = get_post($_POST['id']);

?>
    <div id="single-post post-<?php the_ID(); ?>">

    <?php while (have_posts()) : the_post(); ?>

                <?php the_title();?>

                <?php the_content();?>

    <?php endwhile;?> 

    </div>

jQuery

   $(document).ready(function(){

        $.ajaxSetup({cache:false});
        $(".post-link").click(function(){
            var post_link = $(this).attr("href");

            $("#single-post-container").html("content loading");
            $("#single-post-container").load(post_link);
        return false;
        });

    });

編集:また、私はadmin-ajax.phpに組み込まれたWordPressを使用することが推奨されていることをカップルの情報源から読みました。 admin-ajax.phpを使用することは私にとって有益であろうか、そしてもしそうなら、私は現在持っているものでどうやってそれを "切り替える"でしょうか?

更新(2015年1月4日):


インデックステンプレート

<div id="project-container"></div>

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

    <a class="post-link" rel="<?php the_ID(); ?>" href="<?php the_permalink(); ?>">

       <?php the_title(); ?> 

    </a>

<?php endwhile; endif; ?>

単一投稿テンプレート

<div id="single-post post-<?php the_ID(); ?>">

<?php while (have_posts()) : the_post(); ?>

    <?php the_title();?>

    <?php the_content();?>

<?php endwhile;?> 

</div>

Functions.php

/**
 * Enqueue scripts and styles.
 */
function starter_scripts() {
    wp_deregister_script( 'jquery' );
    wp_register_script( 'jquery', includes_url( '/js/jquery/jquery.js' ), false, NULL, true );
    wp_enqueue_script( 'jquery' );

    wp_enqueue_style( 'starter-style', get_stylesheet_uri() );
    wp_enqueue_script( 'includes', get_template_directory_uri() . '/js/min/includes.min.js', array('jquery'), '', true );
    wp_enqueue_script( 'gray', get_template_directory_uri() . '/js/min/jquery.gray.min.js', array('jquery'), '', true );
    wp_localize_script( 'includes', 'site', array(
                'theme_path' => get_template_directory_uri(),
                'ajaxurl'    => admin_url('admin-ajax.php')
            )
    );
}
add_action( 'wp_enqueue_scripts', 'starter_scripts' );

/**
 * AJAX nopriv 
 */
add_action('wp_ajax_load-single-post', 'prefix_ajax_single_post');
add_action('wp_ajax_nopriv_load-single-post', 'prefix_ajax_single_post');

function prefix_ajax_single_post() {
    $pid = (int) filter_input(INPUT_GET, 'pID', FILTER_SANITIZE_NUMBER_INT);
    if ($pid > 0) {
        global $post;
        $post = get_post($pid);
        setup_postdata($post);
        printf('<div id="single-post post-%d">', $pid);
        the_title();
        the_content();
        echo '</div>';
    }
    exit();
}

jQuery(includes.js)

// Load posts via AJAX
(function($, D){

$.ajaxSetup({cache:false});

    $(".post-link").click(function(){

        var postID = $(this).attr('rel');
        var $container = $("#project-container");
        $container.html("content loading");
        $.get(D.ajaxurl, {action: 'load-single-post', pID: postID}, function(content) {
          $container.html(content);
        });

    });

})(jQuery, site);
1
Desi

JavaScriptを使用してURLを更新することはWordPressとは関係ありませんが、jQueryコードで window.location.hash を変更するだけです。

admin-ajax.phpの使用に関しては、wp-load.phpを必要とするmanuallyの代わりに、AJAX環境をロードする必要があるWordPressを介してタスクを実行することをお勧めします。

あなたの場合、通常のWordPress URLにリクエストを送信しているので、それほど悪くはありませんが、現在のコードにはいくつかの問題があります。

$_POST['id']」問題

あなたの特異な投稿には

$post = get_post($_POST['id']);

これはまったく必要ありません。単一の投稿URLにリクエストを送信しているため、WordPressによって投稿変数が自動的に設定されることを意味します。

さらに、$_POST['id']が設定されていない可能性があります。特にかなりパーマリンクを使用している場合は、PHP警告がスローされます。

「シングルビュー」問題

単独の投稿には、引き続きパーマリンクがあります。これらのパーマリンクのいずれかにアクセスすると、<html><head>、または<body>タグを含まず、ページのコンテンツのみを含むbrokenhtmlページが表示されます。

この問題は2つの方法で修正できます。

  • 'post_link' フックを使用して投稿のパーマリンクを変更し、適切なハッシュでインデックスページを指すようにします。また、アドレスバーに単一のURLを入力するユーザーをインデックスページに送信するリダイレクトを配置します適切なハッシュで。それはいいかもしれませんが、そのようにあなたの投稿が単一のビューで決して見ることができません。

  • 2番目の方法は、単一の投稿テンプレートを編集し、ページが通常の(つまり非AJAX)リクエストで読み込まれたときに適切なhtmlタグを条件付きで出力することです。

    function is_ajax() {
      return isset($_SERVER['HTTP_X_REQUESTED_WITH'])
             && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
    }
    
    if (is_ajax()) {
       // open here <html>, <head> and <body> tags
    }
    
    // page content here
    
    if (is_ajax()) {
       // close here <html>, <head> and <body> tags
    }
    

このように、通常のリクエストを使用してリクエストされた場合、投稿は整形式のhtmlページに表示されます。

パフォーマンスへの影響

上記の2つの方法のいずれかを使用すると、現在のコードの主な問題を解決できますが、パフォーマンスの問題がまだあります。

WordPress URLへのリクエストは、admin-ajax.phpへのリクエストよりもパフォーマンスが少し高価です。両方が完全なWP環境をロードしても、通常のリクエストではWordPressはクエリへのパーマリンクをresolveする必要があります。これは、データベースから一連の書き換えルールをロードし、現在のURLのいずれかに一致するまで、任意のルールに対して正規表現チェックをプログラムで実行します。

リクエスト自体の一部として投稿IDを含むajaxリクエストを送信できる場合、そのチェックをスキップしてパフォーマンスを向上させる投稿コンテンツを出力できます。

それを取得するには、 WordPress AJAX API を使用する必要があります。何かのようなもの:

functions.php

add_action('wp_enqueue_scripts', function() {
  // $script_url is the full url to your js file
  wp_enqueue_script('myjs', $script_url, array('jquery'), true, null, true);
  wp_localize_script('myjs', 'myData', array('ajaxurl' => admin_url('admin-ajax.php));
});

add_action('wp_ajax_load-single-post', 'prefix_ajax_single_post');
add_action('wp_ajax_nopriv_load-single-post', 'prefix_ajax_single_post');

function prefix_ajax_single_post() {
  $pid = (int) filter_input(INPUT_GET, 'pID', FILTSER_SANITIZE_NUMBER_INT);
  if ($pid > 0) {
    global $post;
    $post = get_post($pid);
    setup_postdata($post);
    printf('<div id="single-post post-%d">', $pid);
    the_title();
    the_content();
    echo '</div>';
  }
  exit();
}

jQuery(URLが上記のコードの$script_url varであるファイルに入れます)

(function($, D){

  $.ajaxSetup({cache:false});

  $(".post-link").click(function(){

    var postID = $(this).attr('rel');
    var $container = $("#single-post-container");
    $container.html("content loading");
    $.get(D.ajaxurl, {action: 'load-single-post', pID: postID}, function(content) {
      $container.html(content);
    });

  });

})(jQuery, myData);

インデックステンプレートのコードは同じままにすることができます。

このアプローチを使用すると、すべての問題が解決されます。また、ご覧のとおり、単一の投稿テンプレートはまったく関係ないため、単一の投稿ビューを好きなように表示できます。 (単一の投稿ビューが必要ない場合は、The "Single View" Issueの下の最初の提案を引き続き使用できます)。

2
gmazzap