NuxtMeetup#5開催しました

こんにちは @hirokinishizawa です。

昨日10/18にNuxtMeetup #5を開催しました。

nuxt-meetup.connpass.com

今回はCyberAgentさんに会場をご提供頂きました。本当にありがとうございます。

f:id:hiroki-nishizawa:20181019113355j:plain

アンケート

今回参加枠100人という中総勢240名の方が応募してくださり誠にありがとうございます。

その中でアンケートを200人もの方が答えてくださいました。アンケート内容としてはVue.js、Nuxt.jsを業務、趣味どちらで使用しているかという内容なっております。

f:id:hiroki-nishizawa:20181019114313p:plain

結果はこのようになっており、Vue.jsと同じぐらいNuxt.jsを業務で使用しているそうで驚きました。Nuxt.jsの知見を共有したいという思いでNuxtMeetupを開催し始めたのでだいぶ広まっているのかなと思います。

発表

バンドルファイルの肥大化問題解消にみる_Nuxt.jsの成熟化 @wkm2134

speakerdeck.com

CyberAgentの若松さんがNuxt.jsのメリットや注意点について話してくれました。 Vue−cli3の登場で規約などの旨味は減ったがSSRを手軽に実装できる点はたしかになと思いました。

フロントエンジニア(実稼働まで)ひとりでできるもん @hiroki_yoshitugu

speakerdeck.com

DODAのサービスの説明と、どういう構成で実装されているのかというところを発表していただきました。

Vue or Nuxt @masaakikunsan

slides.com

弊社フロントエンジニアの石岡が発表してくれました。Vue.jsとNuxt.jsのどちらを採用するのかそれぞれのメリットについて話してくれました。 Nuxt.jsのメリット「規約があるのでプロジェクトを破壊しにくい」。とりあえずNuxt.jsを使っておけばいいと言うのは違うんだなと改めて思いました。

Vueを広めるためのNuxt.jsの可能性 @かめぽん

speakerdeck.com

Vue.jsを定着させる施策としてNuxt.jsを使用するというお話をしてくれました。 Vue.jsよりも前にとりあえずNuxt.jsを定着させるためにNuxt.jsを使用する。組織によっていろいろなやり方があるんだなと思いました。

Nuxtを使っていて地味にハマった小ネタ紹介 @yuki_terashima

speakerdeck.com

Nuxtを使って実際にハマったこと解決方法について話してくれました。

SSRをしている時は500系エラー発生時にlayouts/error.vueが読み込まれないのでapp/views/error.htmlで設定すると行けるらしい。知らなかった。。。 細かい所のハマりネタだったのでためになりました。

nuxt-i18nを使ったWebサイトの多言語化 @odan

speakerdeck.com

nuxt-i18nのお話をしてくれました。 nuxt-i18nの日本語情報がなく公式ドキュメントにp-rを投げる?という発表をする予定だったのに発表2日前にqiitaを書いた人が現れたのは面白かったですw ルーティングを自動生成してくれたりとても便利そうなので気になりました。

NuxtでのJAMStackな開発とポイント @tame

speakerdeck.com

Nuxt.jsでJAMStackな開発をするお話をしてくれました。 前回もお話いただいたtameさん。いろいろな技術的チャレンジをされている話は聞いていてとても面白かったです。

懇親会

LT後にはCyberAgentさんが用意してくださったお寿司とピザを囲みながら親睦会を行いました。

f:id:hiroki-nishizawa:20181019151139j:plainf:id:hiroki-nishizawa:20181019151210j:plain

会場提供並びに懇親会をスポンサーしてくださったCyberAgentの皆さん、ありがとうございました!

次回

次回はまだ未定です。

次回は株式会社SMSにて行われます。

次回以降会場提供してくださる方いましたら弊社CTO kotamatまでご連絡お願いします!

最後に

SCOUTER社では一緒に頑張ってくれる方を募集しております。 デザイン、エンジニアの皆さん興味のある方はご応募お願いします!

LaravelのAPI開発でPhpStorm以外使わなくなった話

こんにちは、 id:kotamat です。 現在SCOUTER社では、新規事業の開発も行っており、そちらのバックエンドを開発しているのですが、そちらでは様々な手法を導入し、効率化を図っています。 今回はPhpStormを使った効率化の紹介となります。 (ちなみに僕はIntelliJ IDEA派なので、PhpStormではないですが、基本的に同じことができるのでPhpStormとして紹介させていただきます。)

f:id:kotamat:20181019110817p:plain

APIに必要な開発フロー

基本的に下記のフローをAPI開発で行うかと思います。

  1. 実装の記述
  2. テストの記述、実行
  3. データベースの確認
  4. APIスペックの記述
  5. GithubのPR作成

こちらすべてPhpStormで構築しているので、そちらの紹介をさせていただきます。

今回使用したプロジェクトはこちらの方に反映しています。

github.com

実装の記述

まぁこちらは普通にPHPを書いていく感じなので、サラッと説明します。

PhpStormでは、型宣言している変数だけではなく、PHPDoc、assert、instanceofでのifガード下等型が明示的に推論できる箇所において補完が効いてくれます。

f:id:kotamat:20181019110006g:plain f:id:kotamat:20181019105831g:plain

Laravelでの開発では、基本的にDI(Dependency Injection)でのインターフェース定義をしながら環境によって実装クラスを分けるというような実装をよく行いますが、下記のようにインターフェースと実装はクリックひとつでそれぞれにジャンプすることができます。

f:id:kotamat:20181019105757g:plain

テストの記述、実行

PHPUnitのテストを記述すると、メソッドとクラス定義の左側に再生ボタンが表示されます。 こちらをクリックすることで、テストの実行が可能です。

また、対象メソッドやクラスのブロック内で、事前に割り当てたショートカットキーを実行すると、同様にテストを実行することができます。

f:id:kotamat:20181019105717g:plain

一度実行したものは、右上の再生ボタンで再実行することができます。 これはどのファイルを開いていても、最後に実行したものが実行されるため、 TDDなどテストを確認しながら実装していく開発手法を行っていると良さが実感できます。

どちらもとても良く使うので、ショートカットキーに登録して気軽に実行できるようにするとよいかと思います。

LaravelでのTDDに関しては、最近発売されたLaravel本にとてもわかり易く記述されているので、参考にしていただけるといいかなと思います。

techblog.scouter.co.jp

データベースの確認

データベースを接続するようなテストを書く場合、実際にどのようなデータが挿入されているかを確認したいことがあるかと思います。

その際も、右側のDatabaseというところから、必要なデータソースを登録することで、テーブルの一覧から簡単にその中身を見ることができます。

f:id:kotamat:20181019105627g:plain

もちろん書き込み権限のあるユーザでログインすればデータベースの中身も編集することができるため、デバッグ時に特定の条件を再現したい場合などもサクッとできてしまいます。

APIスペックの記述

今までは通常のPhpStormの使い方でしたが、下記のブログで紹介したAPIスペックの自動出力のプラグインを使うことによって、APIスペックの生成から挙動確認までPhpStormで行うことができます。

techblog.scouter.co.jp

composer require --dev kotamat/laravel-apispec-generator

上記をインストールし、routes/api.phpをこんな感じにして、

<?php

Route::get('/', function () {
    return ['success' => true];
});

下記のようなテストファイルを実行すると

<?php

namespace Tests\Feature;

use ApiSpec\ApiSpecTestCase;
use Tests\CreatesApplication;

class ExampleTest extends ApiSpecTestCase
{
    use CreatesApplication;

    protected $isExportSpec = true;

    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->getJson('/api/');

        $response->assertStatus(200);
    }
}

storage/app/ディレクトリに、APIスペックが出力されます。

f:id:kotamat:20181019104244p:plain

こちら.httpという拡張子になっているのですが、これはPhpStormで認識できるRFC準拠のhttpプロトコルの記述で書かれたものだと、実行することができます。 もちろん出力されるAPIスペックは上記仕様に準拠しており、出力されたものをそのまま実行できます。

まず、php artisan serveでサーバーを立ち上げ、出力されたファイルの左側にある再生マークをクリックすると、下記のようにレスポンスが表示されます。

f:id:kotamat:20181019105552g:plain もちろん生成されたファイルは編集可能であるため、テストで記載しなかった細かい挙動の確認や、テストデータの手動流し込みなどを簡単に行いたいときは、リクエストボディをいじって実行するだけです。

Gitでコミット、GithubのPR作成

各種テストを行い、PRを出せるタイミングになったら、PhpStorm上から差分を確認してコミットしていきます。

下記のように必要な変更箇所だけチェックを付けてコミットします。

f:id:kotamat:20181019105527g:plain push, PR作成もそれぞれコマンドが用意されており、自由にショートカットキーを割り当てることができるので、PR文を作成してsubmitすると、ポップアップで対象PRのリンクが出現し、そのままPRの詳細に遷移することができます。 f:id:kotamat:20181019105452g:plain f:id:kotamat:20181019105348g:plain f:id:kotamat:20181019105235p:plain

まとめ

実装からPRの作成まで、一連の流れをすべてPhpStormで行う方法をお伝えいたしました。 こちらに記載しているのはあくまで表面的なところであり、もっとたくさんの便利機能が備わっているので、いろいろ触ってみながら自分にとって良い開発環境を整えてみてはいかがでしょうか?

最後に

SCOUTERではLaravelエンジニアを絶賛募集しております!

www.wantedly.com

興味のある方は https://twitter.com/kotamats のほうに気軽にご連絡ください!

また、いくつかイベントを開催しております。 もしご都合つく方いらっしゃればお気軽にご参加ください! Laravueに関しては、次次回以降の会場提供してくださるところも募集しております!

techscouter.connpass.com

laravue.connpass.com

「Nuxt.js ビギナーズガイド」のご紹介

こんにちは、hirokinishizawaです。

f:id:hiroki-nishizawa:20181017212448j:plain

10/17に「Nuxt.js ビギナーズガイド」がついに発売されましたので読んで思ったことについて書こうかと思います。

全体の感想

自分はコードを初めて触ってから8ヶ月になるのですが、progateを一通り終えて初めて触ったフレームワークがNuxt.jsだったので、Nuxt.jsのドキュメントが豊富でも書いてあることの意味が分からなかったりすることが多く、始めた当初にあればなと思うぐらいわかりやすく書かれているので初学者の方にはオススメ出来るなと思いました。

CHAPTER1

冒頭でも言いましたが初めて触れたフレームワークがNuxt.jsで、その後もNuxt.jsとVue.jsで開発を進めてきたのでフロントエンド開発の情勢について全くの無知のまま過ごしてきました。

ここ数年間のトレンドを俯瞰してみると、流れが早いといわれたフロントエンドは今は昔であり、非常に安定し、停滞した状態が続いているといえます。

SPAとAPIによるWebアプリケーションが自分の中では当たり前だったので、他の方法を知ろうともしていませんでした。

他にも「Nuxt.jsがフロントエンドにもたらすもの」という項目で、

Nuxt.jsが利用されているのはどこに理由があるのでしょうか。そこには、筆者は規約という概念が大きく関わっていると考えています。

自分がVue.jsでプロジェクトを作成している時には自由に書いていました。実際にはNuxt.jsでは無意識ではありますが、これがルールだというぐらいの認識で書いていました。

CHAPTER2,3,4

CHAPTER2,3では実際にコードに触れながらQiitaのNuxt.jsタグのビューアーを一緒に作っていくような感じになっています。

この2つのCHAPTERを理解できれば基本的な開発は問題なく出来るようになるのではと思いました。仮に詰まったりしても完成品のサンプルがあるので見直すことが出来ます。

CHAPTER4ではさらに実用的になっていて、ブログの投稿サイトを作成していきます。こちらでもしっかりと完成品のサンプルが乗っているので分からなくなったら確認しましょう。

Nuxt.jsとは関係無いのですがこのCHAPTERの終わりのところでLinterの話を少ししています。自分的に環境の話まで含めてくれるので実際に新規プロダクトを作成するのにとてもいいのではないかと思いました。

CHAPTER5

自分はフロントのテストを書いたことがなく先日e2eテストというものを知りました。

CHAPTER5ではテストの必要性や実際にvuexのテストコードの書き方などが書かれていました。

その中でどこまでテストを書くのかという項目があったので引用させてもらいます。

Vuexデータストアと、挙動が複雑なコンポーネント、そしてフレームワークに依存しないレイヤのコードに絞ってテストを書くべき。

CHAPTER6

3つのモード「Universal」,「generate」,「SPA」のそれぞれメリット、デメリットについて書かれています。実際のメリット、デメリットについては本書を読んで見てください。

自分も3つのモードについてはドキュメントに書かれていますがメリット、デメリットだったり運用コストについては理解できていませんでした。適切なデプロイ方法の選定をするのに知って置くべき内容だなと思いました。

最後に

冒頭でも話しましたがビギナーズガイドというだけあって初学者の方や自分のように実際にどんな理由で使用されているか分かっていないまま開発を進めている人にとってレベルアップにもなるし、中級者の方でもNuxt.jsが出来るまでの経緯だったりフロントエンド開発の情勢についても知れると思うのでとてもオススメできる本だと思いました。 全部で200ページの軽い本ですので読んでみてください。

弊社SCOUTERでは隔月でNuxtMeetUpというものをやらせて頂いています。今日10/18の19時30分からNuxtMeetUp #5を行います!YouTubeで生配信もいたしますのでよければご視聴ください。 始まった際にこちらTwitterアカウントでアナウンスを行いますのでフォローしていただければと思います。

nuxt-meetup.connpass.com

「PHPフレームワーク Laravel Webアプリケーション開発」のご紹介

こんにちは、 id:nunulk です。

いま話題の「PHPフレームワーク Laravel Webアプリケーション開発」が SCOUTER 社に置いてあったので、ざっと読ませていただきました。

f:id:nunulk:20181014111718j:plain

主に「Chapter 3 アプリケーションアーキテクチャ」や「Chapter 7 処理の分離」の章について読んだ感想を書こうと思います。

全体の感想

まず、全体の感想ですが、 Laravel 自体の解説については、公式ドキュメントが充実しているのと、日本語訳も追従が早いので、個人的には書籍の必要性はあまり感じてはいませんでした。

ただ、本書は、JWT を使った認証だったり、Elasticsearch を使った全文検索の例だったりが載っていて、Laravel だけにとどまらず、Laravel を使ってウェブアプリケーションをつくる上で参考になる情報がたくさん掲載されているので、公式ドキュメントだけでは得られないものが得られるんじゃないかと思います。

アプリケーションアーキテクチャについて

ウェブサービスや業務システムでは、チュートリアルや公式ドキュメントに載っているような単純なサンプルコードでは単純すぎて参考にならなくなってきますが、本書ではアプリケーションアーキテクチャについての記述が多くあり、実際に業務で書くような複雑なアプリケーションにも適用可能なアイデアが手に入るんじゃないかと思います。

本書に載っているアーキテクチャ関連のセクションについて、いくつか紹介します。

ADR

ADR がなにか、というのは本書を読んでいただくとして、以下の文を引用しておきます。

ADRパターンを適用すると、実際にはMVCパターンと大きな相違はなく、MVCパターンよりも、より処理の内容が具体化したように感じられる。 (略) ここで重要なことはパターン名ではなく、どのような考え方でクラスや処理グループを分割し、責務を与えることであり、「どうしたらよりよいアプリケーション設計が行えるか」です。

アプリケーションが複雑になり、依存関係が増えてくると、どんどんクラスが大きくなってきて、見通しが悪くなってきますので、こうした分割手法は知っておいて損はないと思います。

レイヤードアーキテクチャ

Laravel は素晴らしいフレームワークですが、アプリケーション独自のクラスや処理(ドメインモデル、ドメインロジック)を書く際の指針は、自分で、あるいはチームで決めないといけないので、試行錯誤が必要かと思います。

それでも、先人たちの知恵を参考に、そうした複雑さを分解して、あるいは特定のクラスに閉じ込めることで、コントロールしやすくなるので、ドメイン駆動設計を理解している著者による、本書のサンプルコードは参考になるはずです。

この章以外にも、「5-5 リポジトリパターン」のところに詳しく載っているリファクタリングのところとか、既存のアプリケーションにリポジトリパターンを適用するようなケースで参考になるんじゃないでしょうか。

実用的な非同期処理の例

Laravel には、キューを使った非同期処理を行う仕組みがありますが、実用的な例、というのはインターネットではなかなか見かけないので、実際の使い方に不安を持っている方も多いんじゃないかと思っているんですが、本書では、supervisor の設定や、ElasticsearchClient の使い方も載っていて、実用的と思います。

本書でアプリケーションアーキテクチャについておおまかに理解したら、Chapter 3 の章末に載っている参考文献を片っ端から読んでみるのもいいかもしれません。

おわりに

全体で 500 ページを超える本ですが、Chapter 2 以降は一度目を通すのをおすすめします。どの章にも、公式ドキュメントを読んだだけでは得られない、へーこんな使い方もできるのかーという発見があるんじゃないかと思います。

SCOUTER では、不定期に「ワイワイLaravel語る会」というのを開催していますので、本書を読んだ感想とか、本書の記載を元にした議論とか、Laraveller のみなさんと語り合えたらうれしいです。

詳しくは Connpass のグループを見てみてください。

techscouter.connpass.com

laravelにnuxtを追加してみて出来たこと出来なかったこと

こんにちはhirokinishizawaです!

今回laravelにnuxtを追加したのですが、この三連休で自分が最終的に出来たこと出来なかったことを書いていこうかと思います。

nuxtを入れたことによって変更したファイル

viewファイル

resources
 └── views
      ├── auth
      │   ├── passwords
      │   │   ├── email.blade.php
      │   │   └── resets.blade.php
      │   └── login.blade.php
      │   └── register.blade.php
      ├── layouts
      │   └── app.blade.php
      └── posts
      │    ├── create.blade.php
      │    ├── delete.blade.php
      │    └── edit.blade.php
      ├── home.blade.php
      └── welcome.blade.php

こちらはcontrollerファイルからviewは呼び出さないので全て削除しました!

routes/web.php : routes/api.php

全てapi経由で使用するのでweb.phpにあったものは全てapi.phpに移行しました!

controllerファイル

controllerファイルはファイルごとに中身は少し変更していますが後ほど話そうかと思います!

出来たこと

nuxt導入

laravelにnuxt導入の仕方は以前 id:kotamatさんが書いてくれた「LaravelとNuxt.jsを同一レポジトリで管理するときの構成」を読んでもらえるとわかると思います!

techblog.scouter.co.jp

記事を読んでもらえるとわかると思いますが、今回サーバーはlocalhost:8000フロントはlocalhost:3000で話していきたいと思います。

フロントでapi繋ぎ込み

以前までのlaravelだけでviewを表示しいていた/homeのcontrollerファイルはこのようになっていました。

<?php

public function index(Request $request)
    {
        $user = $request->user();
        $posts = $user->load('posts');
        return view('home', ['posts'=>$posts->posts]);
    }

こちらでviewファイルであるbladeファイルをreturnしていましたが、今回api呼び出しをするのでこのようにしました

<?php

public function index(Request $request)
    {
        $user = $request->user();
        $posts = $user->load('posts');
        return $posts->posts;
    }

なおvueファイルでapiを叩く際はこのようになっています!

<template>
<div class="card" v-for="(fishingData, key) in data" :key="key">
      <div class="card-header">
           日付:{{fishingData.year}}年{{fishingData.month}}月{{fishingData.day}}日
      </div>
      <div class="card-body">
          <div class="column">
              <div class="fish_name">魚種:{{fishingData.fish_name}}</div>
          </div>
          <div class="column">
              <div class="place">場所:{{fishingData.prefecture}}{{fishingData.place}}</div>
          </div>
      </div>
</div
</template>

<script>
export default {
        async asyncData({app}){
            const data = await app.$axios.$get('http://localhost:8000/home')
            return {data};
        },
}
<script>

見た目はこんな感じです!

f:id:hiroki-nishizawa:20180925011343p:plain

他にそれぞれページの表示やページ遷移は<nuxt-link>を使ったりで出来たのですが、axios-moduleを使用して記録を作成したり編集したりすることは出来ませんでした。

なにに詰まったか

user認証

まず最初にlaravelでやっていたユーザー認証をnuxtではどのようにするのかと疑問を持ったので調べて参考にした記事がこちらになります

そこでcomposer require laravel/passportを実行すると

Your requirements could not be resolved to an installable set of packages.                                                                                                                                                                    
                                                                                                                                                                                                                                              
  Problem 1                                                                                                                                                                                                                                   
    - Conclusion: don't install laravel/passport v4.0.3                                                                                                                                                                                       
    - Conclusion: don't install laravel/passport v4.0.2                                                                                                                                                                                       
    - Conclusion: don't install laravel/passport v4.0.1                                                                                                                                                                                       
    - Conclusion: remove paragonie/random_compat v9.99.99                                                                                                                                                                                     
    - Installation request for laravel/passport ~4.0 -> satisfiable by laravel/passport[v4.0.0, v4.0.1, v4.0.2, v4.0.3].                                                                                                                      
    - Conclusion: don't install paragonie/random_compat v9.99.99                                                                                                                                                                              
    - laravel/passport v4.0.0 requires league/oauth2-server ^6.0 -> satisfiable by league/oauth2-server[6.0.0, 6.0.1, 6.0.2, 6.1.0, 6.1.1].                                                                                                   
    - league/oauth2-server 6.0.0 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.
6, v2.0.7, v2.0.8, v2.0.9].                                                                                                                                                                                                                   
    - league/oauth2-server 6.0.1 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.
6, v2.0.7, v2.0.8, v2.0.9].                                                                                                                                                                                                                   
    - league/oauth2-server 6.0.2 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.
6, v2.0.7, v2.0.8, v2.0.9].                                                                                                                                                                                                                   
    - league/oauth2-server 6.1.0 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.
6, v2.0.7, v2.0.8, v2.0.9].                                                                                                                                                                                                                   
    - league/oauth2-server 6.1.1 requires paragonie/random_compat ^2.0 -> satisfiable by paragonie/random_compat[v2.0.0, v2.0.1, v2.0.10, v2.0.11, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.2, v2.0.3, v2.0.4, v2.0.5, v2.0.
6, v2.0.7, v2.0.8, v2.0.9].                                                                                                                                                                                                                   
    - Can only install one of: paragonie/random_compat[v2.0.0, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.1, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.10, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.11, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.12, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.13, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.14, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.15, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.16, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.17, v9.99.99].                                                                                                                                                                    
    - Can only install one of: paragonie/random_compat[v2.0.2, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.3, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.4, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.5, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.6, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.7, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.8, v9.99.99].                                                                                                                                                                     
    - Can only install one of: paragonie/random_compat[v2.0.9, v9.99.99].
    - Installation request for paragonie/random_compat (locked at v9.99.99) -> satisfiable by paragonie/random_compat[v9.99.99].


Installation failed, reverting ./composer.json to its original content.

このようなエラーがでました。

その中のrandom_compatがv9.99.99になっていたので変だと思ったので2.0.0にしたところエラーが解消されました!

postするときのエラー

postするときaxios.post('http://localhost:8006/api/posts', this.foge)とやって作成ボタンを押すとNo 'Access-Control-Allow-Origin'のエラーが出てきました。 調べたところCORS対応が必要みたいです。今回は説明を省くのでこちらを参考にしてください。

最後に

laravelとnuxtでの記事が少なく参考を探すのが大変でした。次回はしっかり解決して解決策をかければと思います!

Laravel ユーザー毎に記録を作成、表示できるように

こんにちは!Laravel勉強中のhirokinishizawaです!

このlaravel勉強ブログでは、はじめてversion minorをしてみたので前回から見て頂けると幸いです!(一気に.5上がってるのは内緒の方向でお願いします)

techblog.scouter.co.jp

はじめに

今回は前回のブログで言っていたユーザー毎に釣りの記録を管理できるようにしました!(あと何もやってなかったスタイルも少しだけ笑)

f:id:hiroki-nishizawa:20180917060008j:plain

f:id:hiroki-nishizawa:20180917060014j:plain

f:id:hiroki-nishizawa:20180917060017j:plain

ディレクトリについてしばらく書いていなかったので軽く書こうかと思います!

Model

User.php
Post.php

Controller

HomeController.php
PostsController.php

Views

resources
 └── views
      ├── auth
      │   ├── passwords
      │   │   ├── email.blade.php
      │   │   └── resets.blade.php
      │   └── login.blade.php
      │   └── register.blade.php
      ├── layouts
      │   └── app.blade.php
      └── posts
      │    ├── create.blade.php
      │    ├── delete.blade.php
      │    └── edit.blade.php
      ├── home.blade.php
      └── welcome.blade.php

この中で今回のユーザー毎に表示や作成出来るようにするためにModelとControllerファイルを変更しました!

モデル

UserとPostsの関係は1対多と呼ばれる関係です!

ユーザーは複数の記録を保存できるので、Userは複数のPostを保存する 1つの記録の情報は1人しか存在しないのでPostは1つのUserしか持ちません! 上記の関係に基づき、各モデルにはこのように関数を追記しました!!(リレーション)

User.php

<?php
public function posts()
{
    return $this->hasMany('App\Post');
}

Post.php

<?php
public function user()
{
    return $this->belongsTo('App\User');
}

コントローラー

HomeController.php

<?php
public function index(Request $request)
{
    $user = $request->user();
    $posts = $user->load('posts');
    return view('home', ['posts'=>$posts->posts]);
}

PostsController.php

<?php
public function create()
    {
        return view('posts.create');
    }

    public function edit(Post $post)
    {
        return view('posts.edit')->with('post', $post);
    }

    public function post(PostRequest $request)
    {
        $post = new Post();
        $post->fish_name = $request->fish_name;
        $post->year = $request->year;
        $post->month = $request->month;
        $post->day = $request->day;
        $post->prefecture = $request->prefecture;
        $post->place = $request->place;
        $post->user_id = $request->user()->id;
        $post->save();
        return redirect('/home');
    }

    public function update(PostRequest $request, Post $post)
    {
        $post->fish_name = $request->fish_name;
        $post->year = $request->year;
        $post->month = $request->month;
        $post->day = $request->day;
        $post->prefecture = $request->prefecture;
        $post->place = $request->place;
        $post->save();
        return redirect('/home');
    }

    public function delete(Request $request)
    {
        $post = Post::find($request->id);
        return view('posts.delete')->with('post',$post);
    }

    public function remove(Request $request)
    {
        $post = Post::find($request->id);
        $post->delete();
        return redirect('/home');
    }

実際に変更点があったのはpostだけになります。 user_idを取得するために$post->user_id = $request->user()->id;になっています!

躓いた点

リレーションと関係あるかはわからないですが、postをユーザー管理を出来るようにuser_idを作ってから送信しようとしたらUnknown column 'updated_at'というエラーが出てくるようになりました。 調べてみたところpublic $timestamps = false;でupdate_atを更新するのを回避できると書いてあったので試しにやってみたら次はcreated_atがないよーと怒られました。。。 postなのに作成日時はないとだめなのかな??

migrationファイルを見てみると作成した時からあるcreatedとmodifiedがありましたが、update_atはありませんでした。なのでcreatedとmodified($table->datetime('created');、$table->datetime('modified');)を削除してtimestamps($table->timestamps();)を入れることにより対応できました!

最後に

だんだんlaravelの内容が難しくなってきて、実装と文章にするのが難しくなってきましたーーー泣 分かりづらかったら申し訳ございません。

今は全てapp直下のmodelとcontrollerファイルだけを使って書いていますが何かほかのrepositoryファイルとかも使って作成していこうかと思います!

先週nuxtmeetup#5のイベントを公開したので興味あれば是非参加してください!! nuxt-meetup.connpass.com

ありがとうございました!

Laravel: アカウント登録出来るようにする

こんにちは!scouterでフロントエンジニアをしてるhirokinishizawaです!

はじめに

今回Laravel勉強version5.0.0では前回まで作っていた釣りの記録をユーザー管理するための準備でアカウント登録できるようにしました!

前回投稿した記事

techblog.scouter.co.jp

アカウント登録できるようにするにあたって

最初に言っておきますLaravelでアカウント登録をできるようにするのはとても簡単です!

アカウントを登録出来るようにするにはターミナルでLaravelをインストールしたプロジェクトに移動して

php artisan make:auth

こちらを実行すると次のようにアカウント登録するたに必要なファイルやルーティングが生成されアカウント登録、ログインなどが出来るようになります!

生成されるファイルはこちらになっています!

Created View: /resources/views/auth/login.blade.php
Created View: /resources/views/auth/register.blade.php
Created View: /resources/views/auth/passwords/email.blade.php
Created View: /resources/views/auth/passwords/reset.blade.php
Created View: /resources/views/auth/emails/password.blade.php
Created View: /resources/views/layouts/app.blade.php
Created View: /resources/views/home.blade.php
Created View: /resources/views/welcome.blade.php
Installed HomeController.
Updated Routes File.
Authentication scaffolding generated successfully!

ルーティングには

<?php

Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');

がweb.phpに追加されています!

Route::get('/home', 'HomeController@index')->name('home');こちらは作成されたHemeController.phpの中のindexメソッドを使用しているのはわかりますが、Auth::routes();の方はちょっとよく分かりませんでしたが今は置いておいてとりあえず出来ることが何なのかブラウザ上で確認してみようかと思います!Auth::routes();のルーティングの中身は後ほど説明したいと思います!

make:authをした後の挙動

最初の画面(topページ)

サーバーを立ち上げた後localhost:8000を開くと以前は

f:id:hiroki-nishizawa:20180910010206p:plain

このような画面でしたが上書きされて

f:id:hiroki-nishizawa:20180910010143p:plain

このような画面になっています!

アカウント登録,ログイン画面

topページのヘッダーにあるloginとregisterを押すとログイン画面、アカウント登録画面にいきます。

f:id:hiroki-nishizawa:20180910010146p:plain

f:id:hiroki-nishizawa:20180910010151p:plain

home画面

login完了するとhome画面に行きます

f:id:hiroki-nishizawa:20180910010155p:plain

初期画面はこのようになっているのですが、自分は前回まで作っていた釣りのhome画面があるので/homeにアクセスすると

f:id:hiroki-nishizawa:20180910010159p:plain

このような感じになっています!今はまだユーザー毎に記録したものを表示出来るようにしていないので、どのユーザーでアクセスしても同じ内容が表示されます!!

Forgot Your Password?

topページにあるForgot Your Password? を押すとパスワード再発行をする画面に行きます!

f:id:hiroki-nishizawa:20180910010202p:plain

追加されたAuth::routes()の中身

冒頭でmake:authをしたときルーティングに追加されたAuth::routes()の中身について書いていこうかと思います!

ルーティングの中身

先程わからないと言っていたAuth::routes()を調べてみたら中はvender\laravel\framework\src\Illuminate\Routing\Route.phpに記載されていることがわかりました!

中のauthメソッドを見てみるとこのようになっていました!

<?php
 public function auth()
    {
        // Authentication Routes...
        $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');
        $this->post('logout', 'Auth\LoginController@logout')->name('logout');

        // Registration Routes...
        $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
        $this->post('register', 'Auth\RegisterController@register');

        // Password Reset Routes...
        $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
        $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
        $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
        $this->post('password/reset', 'Auth\ResetPasswordController@reset');
    }

login画面を例として話していきます。login画面はルーティングを見る感じLoginControllerのshowLoginFormメソッドに書かれているのがわかると思います!ですがLoginControllerを見てみるとshoLoginFormというメソッドは見つかりませんでした。他のルーティングも見る限りApp\Http\Controllersの中のControllerファイルにはありませんでした。

結局分からず一度調べることに。。。

認証系のメソッドはほぼトレイトとして実装されており、その実体は、Illuminate\Foundation\Auth\以下に存在します。

らしいです。。。。。

こちらはmake:authを実行した際にAuth::routes();が追加されたことによって参照されるようになるみたいです!

すごい便利。。。笑

改めてLaravelの凄さを実感しました!笑

ではアカウント登録をするとき、ログインをしたときの動きをControllerファイルで見ていきましょう!

アカウント登録をするとき

ルーティング

// Registration Routes...
        $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
        $this->post('register', 'Auth\RegisterController@register');

RegisterController@showRegistrationForm'

<?php
public function showRegistrationForm()
    {
        return view('auth.register');
    }

こちらはただアカウント登録をするページを表示するだけのメソッドでした!

RegisterController@register

<?php
public function register(Request $request)
    {
        $this->validator($request->all())->validate();

        event(new Registered($user = $this->create($request->all())));

        $this->guard()->login($user);

        return $this->registered($request, $user)
                        ?: redirect($this->redirectPath());
    }

登録したらその場でログインをし、AuthControllerで設定されたリダイレクト先へリダイレクトするようになっています。というわけで/homeにリダイレクトされます!

ログインするとき

ルーティング

// Authentication Routes...
        $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');

LoginController@showLoginForm

<?php
public function showLoginForm()
    {
        return view('auth.login');
    }

こちらはただログインする画面を表示するだけのメソッドでした!

LoginController@login

<?php
public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if ($this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request)) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

認証がOKならログイン処理が行われます。 その他にもスロットル処理が行われており、ここではログインを何度も失敗して一定の数を超えると、しばらくログインできないという処理が加わっています。

最後に

このようにLaravelでアカウント認証の処理をしたいと思ったらphp artisan make:authをするだけで簡単にできます!本当に便利だと思いました!

来週はアカウント認証系のスタイルを釣りの記録用に変更をしたり釣りの記録をユーザー別に管理をしてみようかなーと思います!

このブログと同時に本日12:00にNuxtMeetUp #5を公開しました!10/18日です!ぜひご参加ください!

nuxt-meetup.connpass.com