Play Framework 2.6(Scala)でFormの処理を作ってみた

## 概要
ScalaのPlay Frameworkで手始めにForm処理を一つ作ってみようとしたら、ネットにあるサンプルソースから仕様が意外に変わっていたので、2.6時点での作成方法を情報整理をしてみました。

## 前提
ログイン画面をイメージしてFormの処理を作ってみました。気づいた点やはまった点を、ソースを交えて記載しています。

## サンプルソース
【routesファイル】

```
GET     /      controllers.LoginController.loginInit
GET     /login controllers.LoginController.loginInit
POST    /login controllers.LoginController.loginSubmit

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
```
【models】

```models.scala
package models

case class LoginUser(
    userid:String, 
    userpw:String); 
```

【controllers】

```LoginController.scala
package controllers

import javax.inject._
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import models._
import play.api.data.validation.Valid
import play.api.data.validation.Constraint
import play.api.data.validation.Invalid
import play.api.i18n.I18nSupport

@Singleton
class LoginController @Inject()(cc: ControllerComponents) extends AbstractController(cc) with I18nSupport {

  // ログインフォーム
  // 空白チェックにオリジナルメッセージを設定してみる
  val loginUserForm = Form( mapping("userid" -> text.verifying("ユーザIDを入力してください" , {!_.isEmpty()}) , 
                                    "userpw" -> text.verifying("パスワードを入力してください" , {!_.isEmpty()})
                                    )
                                    (LoginUser.apply)(LoginUser.unapply) 
                           )
  
  // ログイン画面の初期表示
  def loginInit() = Action { implicit request =>
     Ok( views.html.login(loginUserForm) )
  }
  
  // ログイン画面のSubmit
  def loginSubmit() = Action { implicit request: Request[AnyContent] =>
     loginUserForm.bindFromRequest.fold(
         // 入力チェックNG
         errors => {           
           BadRequest( views.html.login(errors) )
         },
         // 入力チェックOK
         success => {
           val loginUser = loginUserForm.bindFromRequest.get
           Ok( views.html.loginSuccess() )
         }        
     )
  }

}
```
Controllerの作成にあたってまず留意すべきことは、[こちら](https://stackoverflow.com/questions/47280371/implicit-messages-provider-instance-was-not-found-in-play-framework-with-scala)のstackoverflowの記事より、2.6からクラスの継承に必要なものが変わった点です。
あと、これは別に2.6だからということではないのですが、空白チェックにあえてverifyingを使って試しにオリジナルのメッセージを設定してみました。また、入力チェックの詳細については[Playframework 2.0(Scala)でサンプルアプリケーション作成-3.メッセージの国際化(i18n)対応](https://dev.classmethod.jp/server-side/play-yabe-3/)が参考になります。

【view】

```login.scala.html
@(loginUserForm : Form[LoginUser])(implicit request: RequestHeader, messagesProvider: MessagesProvider)
@import helper._
@main("サンプル"){
    <font size=5>■ログイン画面</font><br/>
    @helper.form( action = helper.CSRF(routes.LoginController.loginSubmit) ){
        <fieldset>
          @helper.inputText(loginUserForm("userid") , '_label -> "ログインID")
          @helper.inputPassword(loginUserForm("userpw") , '_label -> "パスワード")
        </fieldset>
        <input type="submit" value="ログイン">
    }
}
```

```loginSuccess.scala.html
@import helper._
@main("サンプル"){
    <font size=5>■ログイン成功</font>
}
```
まず、冒頭のimplicit parameterです。[こちら](https://stackoverflow.com/questions/47280371/implicit-messages-provider-instance-was-not-found-in-play-framework-with-scala)のstackoverflowの記事によると、これがないと2.6ではコンパイルエラーになるそうです。
また、2.6では初期設定ではCSRFの設定がONになっているので、[こちら](https://stackoverflow.com/questions/41684661/unauthorized-you-must-be-authenticated-to-access-this-page-when-passing-play)のstackoverflowの記事によると、actionでCSRFのメソッドを使う必要があるとのこと。
また、2.6というわけではないですが、フィールドコンストラクタがviewのヘルパーの引数に設定できるので、[フォームテンプレートヘルパーの利用](https://www.playframework.com/documentation/ja/2.4.x/JavaFormHelpers)を参考に試しに設定してみました。