【Wordpress】ページングしつつランダムに記事を表示させる

電脳備忘録

いつから問題なく動作していると錯覚していた?
リロードしてもcookieが削除されず値を保持し続けるため、ランダム表示されないことに気が付きました。また書き方についても禁忌を犯していたようなので合わせて修正しました。

2023.03.09更新

jQuery.cookie.jsで、リロード時にcookieを破棄し、新たに取得するように書いていたのですがcookieを削除できません。また、cookieの値も取得できませんでした。原因がわからないまま開発モードでcookieの値を確認したところ、「HttpOnly」の項目にチェックが入っていることに気が付きました。
調べてみるとjavascriptでcookieを触らせないための設定のようです。謎が解けました。この設定が有効になっていたため阻止されていたのですね。

セキュリティ的には「HttpOnly」を無効にすることは許されないのでしょうけれど、ページャーのページを切り替に影響を受けることなく記事の表示順を維持させるだけのために使用しているので、この設定を無効にすることにしました。
無効を有効に設定する方法は検索すればいくらでも見つかったのですが、無効にする方法はなかなか見つかりませんでした。

最終的には「session_start」に'cookie_httponly' => false,と書くことで「HttpOnly」が無効になり、jQuery.cookie.jsによるcookieの制御が可能になりました。

修正版

function.phpの記述を修正しました。

session_name("pgsession");
session_start(['cookie_httponly' => false,]);
add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby( $orderby ) {
$seed = $_SESSION['pgsession'];
if (empty($seed)) {
$seed = rand();
$_SESSION['pgsession'] = $seed;
}
$orderby = 'RAND(' . $seed . ')';
return $orderby;
}

ブラウザがどうやって読み込みこまれたか判定するには「PerformanceNavigationTiming」を使うべきであって「performance.navigation.type」で判定するのは禁忌らしいです。怖い人たちが押し寄せてきて総括を強要される前に、下記のエントリーを参考にして修正しました。

[Javascript]ブラウザバック時にステータスを反映させる

修正版

jQueryの記述を修正しました。
取得した値が「reload」だった場合cookieを削除するようにしています。

<?php $url = $_SERVER['REQUEST_URI'];
if(strstr($url,'page')==false):
?>
<script>
jQuery(document).ready(function( $ ) {
var perfEntries = performance.getEntriesByType("navigation");
var type = null;
//タイプの判定
perfEntries.forEach(function(pe){
type = pe.type;
//navigate	通常読み込み
//reload	更新
//back_forward	戻る or 進む
//prerender	事前のページ読み込み
});
if(type == 'reload'){
var sesid = "pgsession";
$.removeCookie(sesid);
$.cookie(sesid, null);
$.cookie(sesid, "", {expires: -1});
$.cookie(sesid,"",{path:"/",expires:-1});
}
});
</script>
<?php endif; ?>

修正前の記事については消さずに残しておくことにします・・・。

旧記事

「Wordpressで記事をランダムに表示させたい。あ、もちろんページャーは実装してね。」という依頼を受け、早速グーグル先生に問い合わせましたが、記事をランダムに表示するやり方の記載はあるもののページャー(ページ分割)に対応した記事はほぼほぼありませんでした。

多くのサイトで紹介されている方法fだと1ページ目に表示された記事が2ページ目以降にさも当たり前のように表示されてしまうんですよね・・・。結局こちらの記事を参考にして実装することができました。

WordPress 記事をランダムに表示してページングする方法

function.phpに追記。ページングで分割しても記事が重複することなく表示されるようになりました。


<?php
session_name("pgsession");
session_start();
add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby( $orderby ) {
$seed = $_SESSION['pgsession'];
if (empty($seed)) {
$seed = rand();
$_SESSION['pgsession'] = $seed;
}
$orderby = 'RAND(' . $seed . ')';
return $orderby;
}
?>

確かにページ分割しても記事が重複せずに表示されるようになったのですが、この方法だとsessionの値が変わらない限りランダムに並び変わりません。ブラウザをリロードしても何も変わりません・・・。

トップページ(ページャーの1ページ目)に戻った時、トップページでリロードした時に再度記事をランダムに重複することなく表示させるのが仕様です。 そこで、トップページ(ページャーの1ページ目)に戻った時、もしくはトップページでブラウザをリロードした時にsessionを破棄して値を取り直すことで記事の並びを変えることを思いつき、PHPでの実装を試みたのですが、どうやっても記事が重複して表示されてしまい実装できませんでした。

PHPがダメならjQueryでと半ばやけくそでjquery.cookie.jsを使い、トップページへのリンクをクリックした時、もしくはトップページ(ページャーの1ページ目)でリロードした時のみsessionを破棄するようにしたところ、意図した動きをしてくれるようになりました。

jQuery(document).ready(function( $ ) {
$('.go-to-toppage').on('click',function(){
var sesid = "pgsession";
$.removeCookie(sesid);
$.cookie(sesid, null);
$.cookie(sesid, "", {expires: -1});
$.cookie(sesid,"",{path:"/",expires:-1});
});

トップページへのリンクをクリックした時にセッションを破棄するようにしました。

<?php $url = $_SERVER['REQUEST_URI'];
if(strstr($url,'page')==false):
?>
jQuery(document).ready(function( $ ) {
if (window.performance) {
if (performance.navigation.type === 1) {
var sesid = "pgsession";
$.removeCookie(sesid);
$.cookie(sesid, null);
$.cookie(sesid, "", {expires: -1});
$.cookie(sesid,"",{path:"/",expires:-1});
}
}
});
<?php endif; ?>

トップページ(1ページ目)でリロードした時のみsessionを破棄するようにしました。ページ分割しているので2ページ目以降はURLに「page」という文字列が含まれますが、1ページ目には表示されないのでこれをトリガーにしています。

PHPとjQueryの合わせ技とスマートな方法ではありませんがなんとか実装できました。本当はPHPで完結したかったんですけどね・・・。

広告

ブログの維持費に充てるでございます・・・。