[Site] ランキング (処理)

タグ :

作成サイト「koweboo」についてまとめるシリーズです。
今回は前記事に続いてランキングの「データ取得処理」についてまとめます。

作成サイト内の関連箇所 — 「ランキング

音声ランキングのデータ取得

音声のランキング表示に必要なデータを取得と順位の算出を行います。
処理はコンポーネント化して使用します。
過去記事「コンポーネント化する」で作成した TopicComponent.php へ追加します。

function GetRankVoice($model, $genre_id) {
	$date = date('Y-m-d', strtotime("-1 month"));
	$model->contain('Request', 'CountVoice');
	if($genre_id) {
		$voices = $model->find('all', array(
			'conditions' => array(
				'Voice.created >=' => $date,
				'Request.genre_id' => $genre_id
			),
			'order' => array('Voice.created' => 'desc')
		));
	} else {
		$voices = $model->find('all', array(
			'conditions' => array('Voice.created >=' => $date),
			'order' => array('Voice.created' => 'desc')
		));
	}
	/* 音声ランキング情報取得 */
	$user = $this->GetUserName(
		$model,
		array('Voice.created >=' => $date)
	);
	$ranks = array();
	foreach ($voices as $voice) {	// データ結合
		$ranks += array(
			$voice['Voice']['id'] => array(
				'Request' => array(
					'title' => $voice['Request']['title'],
					'id' => $voice['Request']['id']
				),
				'Voice' => array(
					'id' => $voice['Voice']['id'],
					'title' => $voice['Voice']['title'],
					'filename' => $voice['Voice']['filename'],
					'created' => $voice['Voice']['created']
				),
				'User' => array(
					'id' => $voice['Voice']['user_id']
				),
				'count' => 0,
				'good' => 0,
				'point' => 0,
			),
		);
		$ranks['req_id'][$voice['Voice']['id']] = $voice['Voice']['request_id'];
		$ranks['User'][$voice['Voice']['user_id']] = array(
			'name' => $user[$voice['Voice']['user_id']]['name'],
			'img' => $user[$voice['Voice']['user_id']]['img'],
			'type' => $user[$voice['Voice']['user_id']]['type']
		);
		// こえの再生回数取得
		foreach($voice['CountVoice'] as $count) {
			$ranks[$voice['Voice']['id']]['count'] += $count['count'];
			$ranks[$voice['Voice']['id']]['point'] += $count['count'] * 2;
		}
	}
	
	/* 音声情報取得 */
	$voice_req = $this->GetVoiceData($model, array(
		'conditions' => array('Voice.request_id' => $ranks['req_id']),
		'order' => array('Voice.created' => 'desc')
	));
	foreach ($voice_req as $req) {
		// こえの評価数取得
		foreach($req['VoicesGood'] as $good) {
			$ranks[$req['Voice']['id']]['good'] += $good['good'];
			$ranks[$req['Voice']['id']]['point'] += $good['good'] * 3;
		}
		// お題への投稿数取得
		$ranks[$req['Voice']['id']]['CountRequest'] = $req['CountRequest'];
		// コメント取得
		$ranks[$req['Voice']['id']]['VoicesComment'] = $req['VoicesComment'];
	}
	
	return $ranks;
}

1行目で引数としてモデルオブジェクトとジャンル指定用のIDを受け取るようにしています。

2行目は現在の日付から算出した条件用の日付を取得します。
今回一ヶ月前までのデータのみを取得するようにしています。

4行目〜17行目ではジャンル指定に応じてデータ取得時の条件を可変するようにしています。
条件は日付とジャンルIDで、取得順は新着順になるように設定します。

19行目〜22行目では音声をアップロードしたユーザー情報を取得します。
使用している関数「GetUserName()」は過去記事「コンポーネント化する」を参照してください。

23行目〜56行目にて表示に必要な音声情報をまとめます。
ちょっと強引ですが、一つの変数にまとめておくことで表示時に扱いやすくなると思います。

59行目〜62行目では音声一覧表示用のデータを取得します。
使用している関数「GetVoiceData()」に関しては後述します。

63行目〜73行目にて音声の評価数、お題への投稿数、コメントをまとめています。
同じように表示時に扱いやすいようにまとめているだけです。

75行目で戻り値としてまとめたデータを返します。

上記の処理内で使用している「GetVoiceData()」は、音声一覧用にデータ取得する処理です。
処理行数が長くなるのが嫌だったのでコンポーネント化しただけの理由で作成したのですが、他のページで音声データを取得するのにも使えるようにしています。

function GetVoiceData($model, $param) {
	// 音声情報取得
	$model->contain('VoicesComment', 'VoicesGood', 'Request');
	$voices = array();
	$voices = $model->find('all', $param);
	// 音声のお題情報取得
	foreach($voices as $voice) {
		$req_id[$voice['Voice']['request_id']] = $voice['Voice']['request_id'];
	}
	$model->Request->contain('CountRequest');
	$voice_req = $model->Request->find('all', array(
		'conditions' => array('Request.id' => $req_id)
	));
	for($i = 0; $i < count($voices); $i++) {
		foreach($voice_req as $req) {
			if($voices[$i]['Voice']['request_id'] == $req['CountRequest'][0]['request_id']) {
				$voices[$i] += $req;
			}
		}
		$voices[$i]['User']['id'] = $voices[$i]['Voice']['user_id'];
	}
	
	return $voices;
}

モデルオブジェクトと取得条件を引数として渡せば、音声一覧表示用のデータとして戻り値が取得できる、というものです。

3行目〜5行目で音声データを取得します。
引数で受け取った条件を指定して取得します。

7行目〜21行目にて、その音声のお題へのアップロード数も取得してくるようにしています。
同じように表示時に扱いやすくするためにデータをまとめています。

表示用処理

音声ランキング表示用の処理を作成します。
コントローラファイル「RankingsController.php」を手動で作成して、その中に処理を書きます。
他のファイルをマネして index() を作ります。

public function index($genre_id = null) {
	/* こえランキング情報取得 */
	$ranks =$this->Topic->GetRankVoice($this->Voice, $genre_id);

	/* データ分割 */
	$req_id = $ranks['req_id'];
	$user = $ranks['User'];
	unset($ranks['req_id']);
	unset($ranks['User']);

	/* point数の多い順にソート、上位10個を抽出 */
	$sort = array_slice(Set::sort($ranks, '{n}.point', 'desc'), 0, 10);
	$this->set('voice_ranks', $sort);
	$this->set('user', $user);
	foreach ($ranks as $rank) {
		// 評価数取得
		$goodcnt[$rank['Voice']['id']] = $rank['good'];
		// コメント数取得
		$comcnt[$rank['Voice']['id']] = 0;
		foreach ($rank['VoicesComment'] as $com) {
			$comcnt[$com['voice_id']]++;
		}
	}
	$this->set('goodcnt', $goodcnt);
	$this->set('comcnt', $comcnt);
}

1行目の引数のジャンルIDはURLパラメータの値が入ります。
ランキングデータを取得する際に使用します。

3行目でコンポーネント化した関数を使用して音声ランキングデータを取得します。

6行目〜9行目上記関数で一括でデータを取得してくるので、表示時に扱いやすくするようにあえて分割します。
データをコピーした後はそのデータは不要なので「unset()」で削除しています。
削除する必要は無いかもしれないですが、ビューへ渡すデータ量を軽くしようという心遣いです。

12行目ではランキング順に並べ替えを行っています。
取得してきた音声ランキングデータには「point」というランキング用の計算値(合計値)も取得するので、それを基に並べ替えを行います。
さらに、ランキングは上位10個となるようにしています。

15行目〜23行目にて表示用の評価数とコメント数を取得します。
ここの処理もテーブルを作成してデータベースから取得した方がカッコいいのですが、後付けで追加した箇所なので、これで勘弁してください。。。

これで音声ランキングが表示されるはずです。
残りのランキングについては同じような処理になりますので省略します。

Share

  • このエントリーをはてなブックマークに追加

Comment

コメントを残す

*がついている欄は必須項目です。

  • Twitter
  • Facebook
  • Google Plus
  • RSS Feed