Endo Tech Blog

Techブログと言う名のただのブログです。

日報サービス「DuPo」を作った話

日付をまたいでしまいましたが、この記事はpepabo Advent Calendar 2016 - Qiita 13日目の記事です。 昨日はzipperさんよく使うpuppetモジュールの紹介でした! 


始めに

始めまして。 現在、GMOペパボ株式会社でアルバイトで働いているid:kikuchi1201です。
idはkikuchiですが、本名はendoです。
よろしくお願いします。

そもそもDuPoって何?

f:id:kikuchi1201:20161214080442p:plain

http://dupo-fendo1201.sqale.jp/

DuPoは簡単な日報サービスです。 使用言語はPHPで、フレームワークにLaravel 5.3を使っています。元々の土台は以前ドットインストールLaravelの講義 を基に作ったwebアプリケーションがあったので、その時に作成したコードを再利用して開発しました。

github.com

当時はLaravelのverが5.1で、route.phpがweb.phpになったり、ディレクトリ先が変わったり等ありましたが、それ以外は殆ど同じコードを流用しています。

DuPoページ

f:id:kikuchi1201:20161214081014p:plain

DuPoページでは記事の投稿一覧の表示と、記事の作成、記事の消去、編集の一連のCRUDを実装しています。これらの処理を今回はDupoControllerで統一して管理しています。例えば新規投稿記事を作るとすと以下の手順でLaravelでは新規投稿記事を作成する事が可能です。

(1) ユーザが新規投稿にアクセスする。
↓
(2)ルーティング(web.php)にgetで`/dupo/create`をリクエストする。
↓
(3)Route::get('/dupo/create','DupoController@create');が実行され、次にDupoControllerのcreateメソッドが呼びだされ処理を実行する。
↓
(4)DupoControllerのcreateメソッドを実行
↓
(5)create メソッドが呼び出される。
↓
(6)新規投稿ページへ飛ぶ。記事を記述する。
↓
(8)記事を投稿する。
↓
(9)ルーティング(web.php)にPOSTで`dupo/store`をリクエストする。
↓
(10)Route::post('/dupo/store','DupoController@store');が実行され、次にDupoControllerのstoreメソッドが呼びだされ処理を実行する。
↓
(11)DupoControllerのstoreメソッドを実行
↓
(12)storeメソッドが呼び出される。
↓
(13)新規投稿記事をDBに登録する。
↓
(14)投稿画面一覧に戻る。

大分詳細を省いてしまっていますが、基本的に最初にルーティングから動作を考え、どのコントローラを使って処理を実装していくかを考えながら書いていきます。 従って今回作成したDupoControllerでは以下の7つのメソッド作成しました。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\NipoRequest;
use App\Http\Controllers\Controller;
use App\Nipo;


class DupoController extends Controller
{

        public function top()
{
            $nipos = Nipo::latest('created_at')->get();
            return view('dupos.dupo')->with('nipos',$nipos);

        }
        
        public function create(){
           return view('dupos.create');
        }

        public function show($id){
            $nipo = Nipo::findOrFail($id);
            return view('dupos.show')->with('nipo',$nipo);
        }

        public function edit($id){
            $nipo = Nipo::findOrFail($id);
            return view('dupos.edit')->with('nipo',$nipo);
        }


        public function store(NipoRequest $request){
            $nipo = new Nipo();
            $nipo->title =$request->title;
            $nipo->body  =$request->body;
            $nipo->save();
            return redirect('/dupo')->with('flash_message', '新規記事を作成しました!');
        }

        public function update(NipoRequest $request,$id){
            //記事を取得
            $nipo = Nipo::findOrFail($id);
            $nipo->title =$request->title;
            $nipo->body  =$request->body;
            $nipo->save();
            return redirect('/dupo')->with('flash_message', '記事を更新しました。');
        }
        public function destroy($id){
           $nipo = Nipo::findOrFail($id);
           $nipo -> delete();
           return redirect('/dupo')->with('flash_message', '記事を消去しました。');
       }
}

それぞれのメッソッドが具体的に何をしているのかを簡単に解説すると

  • DupoController
    • top();
      • 記事一覧を最新順で取得してviewファイル(dupos.dupo)に渡す。
    • create();
      • 新規記事作成画面のviewファイルを返す。
    • show();
      • 受け取った$idに該当する記事があったら、記事を取得してviewファイル(dupos.show)に渡す。そうでなければ例外を発生させる。
    • edit();
      • 受け取った$idに該当する記事があったら、記事を取得してviewファイル(dupos.edit)に渡す。そうでなければ例外を発生させる。
    • store();
      • 受け取ったtitleとbodyの値を DB に保存して、/dupoflashメッセージ(新規記事を作成しました!)付きでリダイレクトさせる。
    • update();
      • 受け取った$idに該当する記事があったら、記事を取得して、新しく受け取ったtitleとbodyの値をDBに保存すして、/dupoflashメッセージ(記事を更新しました。!)付きでリダイレクトさせる。
    • destroy();
      • 受け取った$idに該当する記事があったら、記事を取得して削除して、そのまま/dupoflashメッセージ(記事を更新しました。!)付きでリダイレクトさせる。

about,aboutme,error,indexページ

f:id:kikuchi1201:20161214080541p:plain

今回この様な単純な表示するだけのページはIndexControllerで制御しています。理由は単純に1つのコントローラーにやりたい事と関係の無いメソッドが含まれると混乱する為、このように静的なページを表示するだけのControllerとなっています。IndexControllerの処理は以下の通りになっています。

  • IndexController
    • index();
      • 最初のtop画面
    • error();
      • エラーページ
    • about();
    • aboutme();
      • Guest用のaboutmeページ
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class IndexController extends Controller
{

    public function index(){
        return view('dupos.index');
    }

    // about ページ
    public function about(){
        return view('dupos.about');
    }

    // about meページ
    public function aboutme(){
        return view('dupos.aboutme');
    }

    // errorページ
    public function error(){
       return view('dupos.error');
    }

}

Guestページ

f:id:kikuchi1201:20161214042723p:plain

http://dupo-fendo1201.sqale.jp/guest_dupo

Guestページでは、DuPoページと違って記事の一覧表示閲覧のみしか利用できないようにします。具体的な実装方法としては先程作成したDupoControllerから、記事の作成と消去する機能を省きます。また、それに加えてGuest専用の、aboutページとaboutmeページを表示する処理を加えるので、今回Guestページを制御する為に作成する GuestControllerは以下の様に

  • GuestController
    • top();
    • show();
    • about();
    • aboutme();

実際に書かれているGuestControllerは以下の様な内容になります。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Nipo;

class GuestController extends Controller
{
    //

    public function show($id){
        $nipo = Nipo::findOrFail($id);
        return view('guest.show')->with('nipo',$nipo);
    }

    public function top(){
        $nipos = Nipo::latest('created_at')->get();
        return view('guest.dupo')->with('nipos',$nipos);
    }

    public function about(){
        return view('guest.about');
    }

    // about meページ
    public function aboutme(){
        return view('guest.aboutme');
    }

}

裏DuPoページ

現在DuPoにはLaravelで標準で用意されている認証機能(ログイン画面)を実装しています。ですが、実装しているものの、ユーザの個別ページが用意できていな….つまりはログインに成功した所で、全員が同じDBの同じtableを操作する処置となっている為、誰でも記事を自由に書けたり、遠藤が書いた記事を勝手に編集、消去ができる無法地帯なページとなっています。なので、実質ログインしてなくても、ログインが出来てしまっている状態になっているので、セキュリティ的には 完全にアウトな状態ですが、せっかくなんで触ってもらおうと思い、裏DuPoページを開設した考えです。 暫くの内にDuPoがバージョンアップして僕の技術力が向上した際に、ちゃんと実装する予定ですが、昨日Laravelの認証機能を触ってみて、コマンド1発でログインページを実装できるのは、大変嬉しいのは嬉しいのですが、肝心の裏側の処理がどうなっているのかさっぱり理解できてないので、それが理解出来次第、ちゃんと真面目に実装します。なので、それまでは自由に使ってみて下さい。

まとめ

今回、DuPoが作られた背景としては、アルバイト期間中の日報を管理していたGithubのissueが伸びに伸びに、伸びてしまったので、いちいちレビューする人が下までスクロールするのは大変だし、面倒だという事で何か解決策はないかと考え出した末の「DuPo」だった。 でも、今思うと….日付毎に新しくissue立てればそれで終わりだった話が、いつのまにか「作るか!」となり、最後の方は「やるしかねぇ」に変わっていた。今となっては、やって良かったとか思いたいが、残念ながらちゃんと実装できてない部分があるので悔しい気持ちと、昨日から一睡もせずにこの文章を書いてる眠気で、今は凄まじく布団の中で寝たい。 24時間布団の中で寝たいという気持ちしか湧いてこない。

実際CRUD操作の部分までは早かったが、そこからデザインやらログイン認証の実装など、本気で実装しだしたら、全然終わりが見えなかった。終わりが見えないというのは、変な表現かもしれないのだが、デザインにしろ、機能にしろ、ハマリ出した途端に視野が狭くなってしまい、ずぅーとそればっかり考えてしまう。 今日も全然期限が過ぎているのにAdvent Calendarの記事を書いては、DuPoを弄って、書いては、弄って、気づいたら3時になって、そして現在に至る。結論、楽しいのだ。…いやもしかすると、今ハイな状態なので、そんな事をいってるだけかもしれないが1から自分でwebサービスを作れるのは、純粋にいい勉強になったし、終わりがないからやはり楽しい。

そんな感じで全然まとめになってはないかもしれないが、webサービスを1から自分で作ってみるのは否応が勉強せざる環境になる為、かなり力がつくのと、公開をするプレッシャーで気を使ったりするので、大変学びが多く、良い経験になった。

おわり。