ブログ一覧をランダム表示に

【環境情報】
・baserCMSのバージョン:4.4.6
・レンタルサーバー名:ロリポップ
・使用テーマ: nada-icons
・PHPスキル(自己評価): 全くわからない

こんにちは。よろしくお願いします。
テーマnada-iconsをカスタマイズしながら、
ふたつのブログを稼働させるべく、準備をすすめています。
ふたつのうち、片方のブログのトップ画面、つまり、

theme>[nada-icons_改]>Blog>[ブログ1]>index.php

の表示のみ、
すべての公開記事の中から、指定した件数をピックアップして、
ランダムに表示させることは可能でしょうか?
(わたしのサイト内では9件の予定)
ためしに、index.php内に、

<?php shuffle($posts); ?>  //←この1行を追加

<!-- list -->
<?php if (!empty($posts)): ?>
<?php foreach($posts as $post): ?>

としてみたところ、
ブログ設定>詳細設定 で指定した「一覧表示件数」どおり、
ページは分割され(pagination が機能している)、
その、各ページ単位ごとには、記事の順番が、ランダム表示されることを確認しました。

過去、ネット情報を頼りにWordPressに実装したことがあるため、見よう見まねで試行錯誤してみましたが、
プログラミングの知識がないため、まったく手も足も出ませんでした。
なお、ランダムに表示するのはindex.phpだけで、archives.phpは、通常の動作としたいです。

ご助言くださいましたら嬉しく思います。
よろしくお願いいたします。

@erdmond 全ての公開記事からとなると根っこの部分の動作を変えないといけないですね。

テンプレートだけでは難しくプラグインを作る必要があります。

ざくっと作ってみましたので、次のファイルとして保存して、管理画面よりプラグインを有効化してみてください。

// app/Plugin/Rondom/Event/RandomModelEventListener.php
<?php
class RandomModelEventListener extends BcModelEventListener
{
	public $events = ['Blog.BlogPost.beforeFind'];

	public function blogBlogPostBeforeFind($event)
	{
		if(!BcUtil::isAdminSystem()) {
			$event->data[0]['order'] = 'RAND()';
		}
	}
}
「いいね!」 2

ryuring 様
ご返信、ありがとうございます。

Plugin直下のフォルダを、Randomとすることで、
全ての公開記事からランダムに表示することができるようになりました。
また、paginationに関する記述を削除することで、
ブログ1のindex.phpで、望み通りの動作をしています。

ただ、更新日時(modified)や投稿日時(blogPosts)のソートが効かないらしく、
ブログ2も、ランダムに表示されるようになりました。
また、archives.phpで表示するカテゴリも、
クリックするたびに、順序が入れ替わり、
トップページの更新日時(modified)と投稿日時(blogPosts)、
およびサイドメニューのウィジェットによるPost一覧が、
それぞれ別々の表示(ランダム)になってしまいます。

なにか、とてつもない無理難題をお願いしてしまったようで恐縮しています。
ひとまず、現状報告とさせていただきます。
ご協力に感謝いたします。

「いいね!」 1

@erdmond ご希望の条件を満たすコードを書いてみました。ちょっと難しいかもですが、処理の説明も書いています。

<?php
// app/Plugin/Rondom/Event/RandomModelEventListener.php
class RandomModelEventListener extends BcModelEventListener
{
	// ブログの記事取得直前で処理を横取りする宣言
	public $events = ['Blog.BlogPost.beforeFind'];

	public function blogBlogPostBeforeFind($event)
	{
		// 管理画面でない場合は終了
		if(BcUtil::isAdminSystem()) {
			return;
		}
		// ブログの index ページでない場合は終了
		if(!$this->isAction('Blog.Index')) {
			return;
		}
		// $event->data[0] に 検索条件などが入ってくる
		// メインの一覧の場合のみ type に customParams という
		// 文字列がセットされるためそうでない場合は終了
		if(empty($event->data[0]['type'])) {
			return;
		}
		// 並び替え条件をランダムで上書き
		$event->data[0]['order'][0] = 'RAND()';
	}
}
「いいね!」 2

ryuring 様
ありがとうございます!
望んだ通りの表示となりました。素晴らしいです。
なお、いただいたコードだけですと、ブログ1、2ともにランダム表示となるため、
過去ログを頼りに、特定ブログの判定を付け加え、

この様な形で利用させていただいています。

<?php
// 20210619 forum.basercms.net/t/topic/711/4
// app/Plugin/Rondom/Event/RandomModelEventListener.php
class RondomModelEventListener extends BcModelEventListener
{
	// ブログの記事取得直前で処理を横取りする宣言
	public $events = ['Blog.BlogPost.beforeFind'];

	public function blogBlogPostBeforeFind($event)
	{
		// 管理画面でない場合は終了
		if(BcUtil::isAdminSystem()) {
			return;
		}
		// ブログの index ページでない場合は終了
		if(!$this->isAction('Blog.Index')) {
			return;
		}
		// $event->data[0] に 検索条件などが入ってくる
		// メインの一覧の場合のみ type に customParams という
		// 文字列がセットされるためそうでない場合は終了
		if(empty($event->data[0]['type'])) {
			return;
		}
		// 特定ブログの判定(entityId は、ブログ設定画面の「実体ID」 forum.basercms.net/t/topic/366/4)
		$request = Router::getRequest();
		if($request->params['entityId'] === '2'){
		// 並び替え条件をランダムで上書き
		$event->data[0]['order'][0] = 'RAND()';
		}
	}
}

お力添えに、心から感謝しております。
どうもありがとうございました。

「いいね!」 1

@erdmond あ、ブログの絞り込み漏れてましたね:sweat_smile:
実装されたとのことで素晴らしい!よかったです!

「いいね!」 2

お世話になりました。
baserCMSを通して、いろいろ学ばせていただいています。
またお世話になるかもしれませんが、
その時はよろしくお願いいたします。

「いいね!」 2