こちらでははじめまして! Web制作コースとエンジニアコースを受講しておりました金子と申します。
中高生の頃にwebサイト、flashゲーム等を作っていたことからweb制作のお仕事につきたいと考えて受講させて頂きました。今後こちらでは、私が制作中に気がついたことや便利だなと思ったものを共有させて頂きたいなと考えております。皆様アドバイスお願いいたします!

今回のお題は、よくブログ記事の下についている↓こういうやつをCakePHP2で作りたい!

ので作りました。が、たったこれだけだったのにとんでもない大冒険になりました……ヘトヘトです。私の辿ったルートを晒して、もっと楽なルートを皆さんに教えて頂きたいな~と思い投稿させて頂きます。
(ベースになっているのはエンジニアコースphpレッスンで作成したview.ctpです。)

これじゃダメだった! 最初に試したこと

条件

・記事投稿者が、投稿済みの記事(=レコード)を削除できる
・テーブル構造は以下の通り(テーブル名:recipes)
IDはA_I設定です。

やりたいこと

・URL:〜view/3にアクセスした時、前のレコード(ID=1)へのリンクと次のレコード(ID=4)へのリンクを表示したい
・URL:〜view/1にアクセスした時、前のレコードは存在しないので、リンクも表示しない
・URL:〜view/4にアクセスした時、次のレコードは存在しないので、リンクも表示しない

方法

・今の記事のID±1の変数を作成して、リンクに組み込む

結果

失敗!
たとえばID=3の記事なら、前記事のID=2、次記事のID=4となるので、リンクがそうなるように変数を作っておけばOK…と思ったけれど…

 

皆さまお気付きのように、このテーブル、ID2の記事が既に削除されていて存在しないのです。ってことは、ID=3の前後記事のIDは1と4……!
そんなわけで「記事ID±1=前後の記事IDになるから、それでリンクを貼る」方法はダメということがわかりました。
じゃあ記事ID±1のIDが存在してるか確かめて、なかったらもう1件隣を見ていくか…めんどくさ! でもそれ以外に方法が思いつかないし……
debug($posts[$id])とかやっても、id≠配列のキーだから、欲しいレコードをピンポイントで綺麗に取ってこれないし! array_keys関数でいけるかとも思ったけどやっぱりダメ!
ものすご~く面倒だけど今の私にはとにかくこれしかできそうにない! ってことでやりました。

これで解決! CakePHP2で作る面倒な前後記事へのリンク

無事解決した際に書いたコードはこんな感じになりました。
ちょっと日本語力がやばくて分かりにくいかもしれませんが、どうぞ心で感じてください……。

//ここからはControllerに書くものです
    //前後に投稿されているレシピを調べて、前後記事へのリンクを作る準備をする
      $all_recipe = $this -> Recipe -> find('all'); //投稿済みの記事全部取得
      $count = 0; //配列のキーとして設定
      $now_recipe_id_key = ($all_recipe[$count]['Recipe']['id']); //1件目のデータのidを取得
      $max = count($all_recipe); //投稿済みの記事件数

      while($id != $now_recipe_id_key){
        /* 1件目のデータのidと表示中の記事のidが一致するか最初から見ていき、
           表示中の記事が、配列として何件目に位置するデータなのかを$countに記録 */
        $count++;
        $now_recipe_id_key = ($all_recipe[$count]['Recipe']['id']);
      }
      $prev = $count -1; //前記事が配列として何件目のデータなのか
      $next = $count +1; //次記事が配列として何件目のデータなのか

      if($prev < 0){ 
     //$prevが負の値のとき前記事は存在しないので、前記事へのリンクを表示しないよう準備をする
        $prev_link = false; 
    }else{ $prev_link = true; } 
    if($next >= $max){
        //$nextが投稿済みの記事件数を上回るとき次記事は存在しないので、次記事へのリンクを表示しないよう準備をする
        $next_link = false;
      }else{
        $next_link = true;
      }

      // viewでリンクを作る際に必要なのは配列のキーではなく記事IDであるため、viewに渡す前に変換しておく
      if ($prev_link == true) {
        $prev = $all_recipe[$prev]['Recipe']['id'];
      }
      if ($next_link == true) {
        $next = $all_recipe[$next]['Recipe']['id'];
      }

      //前後記事へのリンクに関する変数をviewに渡す
      $this -> set(compact('prev','next','prev_link','next_link'));

//Controllrに書くもの終わり
//ここからはview.ctpに書くものです

    if($prev_link == true){
      echo '<a href="'.$prev.'"><< 前のレシピへ</a>';
    }
    if($prev_link == true & $next_link == true){
      echo ' | ';
    }
    if($next_link == true){
      echo '<a href="'.$next.'">次のレシピへ >></a>';
    }

//view.ctpに書くもの終わり

ここまで長かった…! 「前後記事へのリンク」なんて当たり前すぎるものなのに、自分で作ろうとするとこんなに大変な目にあうんですね。そういうやつやらなくていいWordPressの凄さたるや……。いや、個人的にはコードを書いてるときが楽し苦過ごせる時間なのでWordPressはさほど好みではないのですけれど……。
記事の公開・非公開・下書き…みたいな設定をつけて、公開以外は見れないようにしたい、っていう時も同じ手を使えそうです。
でもこんな面倒なことをしなくても、この方法を使えばサクッと作れるよ!というのをご存知の方はアドバイスをいただけると嬉しいです。
というか一発で前後記事取ってこられる関数とかが存在していてほしい……散々ネサフして見つけられなかったから、ないのかなあ……?

The following two tabs change content below.

金子風月

犬と歯車がついたものと跨り移動系スポーツ(馬・自転車)が好きな駆け出しweb系エンジニア。 2018年2月より、株式会社凛の皆様のおかげで憧れのweb系エンジニアになることができました。