LoginSignup
16
11

More than 5 years have passed since last update.

ScalaでPlayFramework: コントローラ編

Last updated at Posted at 2016-12-11

この記事は以下の記事の続きです。
ScalaでPlayFramework: 環境構築編

Playは公式ドキュメントがちゃんとあるので、細かいところはそちらを参照してください。
Play 2.5.10 documentation
この記事を執筆している段階では、日本語化されているのは2.4までみたいなので、頑張って英語読みましょう。
全てが全て変わっているというわけでもないので、基本2.4を見つつ、うまく行かなかったら2.5見てみるでもいいかもしれません。
この記事の内容は、だいたい以下のページに書かれています。

ルーティングを見てみる

プロジェクトルート以下のconf/routesを開きます。初期状態では以下のようになっているはずです。

conf/routes
...
# An example controller showing a sample home page
GET     /                           controllers.HomeController.index
# An example controller showing how to use dependency injection
GET     /count                      controllers.CountController.count
# An example controller showing how to write asynchronous code
GET     /message                    controllers.AsyncController.message
...

method /path actionと書くことで、/pathmethodでアクセスが来たときactionが実行されるようになります。
下でコントローラにアクションを書いていきますが、アクションができたら都度このファイルに追加していきます。

コントローラをいじる

プロジェクトルート以下のapp/controller/HomeController.scalaを開きます。最初はアクションが一つだけあります。

app/controller/HomeController.scala
...
@Singleton
class HomeController @Inject() extends Controller {
...
  def index = Action {
    Ok(views.html.index("Your new application is ready."))
  }
}

アクションを作るには、ズバリActionを定義してやればいいです。

文字列を返す

とりあえずHello Worldしてみましょう。
app/controller/HomeController.scalaに以下を追加します。

app/controller/HomeController.scala
...
  def hello = Action {
    Ok("World")
  }
...

ルーティングにも追加します。

conf/routes
...
GET     /hello                      controllers.HomeController.hello
...

できたら、プロジェクトを起動してブラウザからアクセスしてみましょう。
http://localhost:9000/hello
Worldという文字列が表示されればOKです。


ちなみに、runでプロジェクトを起動すれば、ファイルを更新した時にいちいちプロジェクトを再起動する必要はありません。
ファイルに更新があった場合は、アクセス時にコンパイルが走ります。その為、更新した直後1回目のアクセスは少し時間がかかります。

もし、ファイルを更新後アクセスすると反応がなくなってしまう場合は、以下の設定を追加するとうまくいくようになるかもしれません。

build.sbt
...
fork in run := false

パラメータを受け取る

アクションに引数をつけることでパラメータを受け取れるようになります。

app/controller/HomeController.scala
...
  def show(id: String) = Action {
    Ok(id)
  }
...

URLのパスの一部を受け取る

/から次の/までのパスを受け取る場合は:idを使います(idは任意の文字列)。
パスは特に指定しない限り、Stringで受け取ることになります。

conf/routes
...
GET     /show/:id/go                 controllers.HomeController.show(id)
...

例えば、/show/1/goとか/show/hello/goとかがマッチします。その時idとなるのは、1helloです。

ある/以降の全てのパスを受け取る場合は*pathを使います(pathは任意の文字列)。

conf/routes
...
GET     /show/*path                 controllers.HomeController.show(path)
...

/show/hoge/fugaの場合、pathhoge/fugaになります。

正規表現を使いたい場合は、$id<regex>を使います(idは任意の文字列、regexは正規表現)。

conf/routes
...
GET     /regex/$id<[0-9]+>          controllers.HomeController.show(id)
...

/regex/1とか/regex/9999とかがマッチします。


ちなみに、conf/routesは上から順番にマッチするかの判定が行われます。
例えば下記のように書いてしまうと、controllers.SomeController.helloは絶対に呼ばれません。注意しましょう。

conf/routes
GET     /show/:id                   controllers.SomeController.show(id)
GET     /show/hello                 controllers.SomeController.hello

逆にこれを利用し、一番最後にどんなパスにもマッチする様書いておけば、自作の404ページを表示させたりすることもできます。

conf/routes
...
# 最後
GET     /*any                       controllers.SomeController.response404(any)

GET(POST)パラメータを受け取る

例えば以下のようなアクションを定義します。

app/controller/HomeController.scala
...
  def params(a: String, b: Int, c: Option[String]) = Action {
    Ok("%s, %d, %s".format(a, b, c))
  }
...

ルーティングには以下のように書きます。

conf/routes
...
GET     /params                     controllers.HomeController.params(a, b: Int, c: Option[String])
...

これだけです。/params?a=hoge&b=1&c=fugaみたいな感じでアクセスすれば、パラメータが渡せていることが確認できます。
パラメータでString以外のものを扱う場合は、型を明記する必要があります。
型をOptionにすることで、あっても無くてもいいパラメータを作ることができます。

パラメータにデフォルト値をもたせたい場合は以下のようにします。

conf/routes
...
GET     /params_b_default           controllers.HomeController.params(a, b: Int = 1, c: Option[String])
...

/params_b_default?a=hogeみたいな感じでアクセスできます。もちろんbcに値を指定しても構いません。

リダイレクトする

一行でできます。

app/controller/HomeController.scala
...
  def redirectHello = Action {
    Redirect("/hello")
  }
...

レスポンスヘッダをいじる、セッションを使う、JSONで返す

3つまとめて。後ろにくっつけます。

app/controller/HomeController.scala
...
  def additional = Action {
    Ok("additional")
      .withHeaders(
          CACHE_CONTROL -> "max-age=3600",
          ETAG -> "xx"
      )
      .withSession(
          "connected" -> "hoge",
          "foo" -> "bar"
      )
      .as(JSON)
  }
...

セッションのチェックは以下の感じで。connectedはただのキーなので、お好きな名前で大丈夫です。

app/controller/HomeController.scala
...
  def checkSession = Action { request =>
    request.session.get("connected").map { user =>
      Ok("Hello " + user)
    }.getOrElse {
      Unauthorized("you are not connected")
    }
  }
...

セッションをクリアするにはこうします。

app/controller/HomeController.scala
...
  def clearSession = Action { request =>
    Ok("cleared")
      .withNewSession
  }
...

Flashとやらを使う

Flashは1度の遷移のみ有効なセッション、みたいなものらしいです。

app/controller/HomeController.scala
  def redirectOnly = Action { implicit request =>
    Ok {
      request.flash.get("success").getOrElse("Welcome!")
    }
  }

  def success = Action {
    Redirect("/redirect_only")
      .flashing(
          "success" -> "yeah!!"
      )
  }

おわりに

公式ドキュメントがよくできています。もうそっち読めばいいんじゃないかな。
自分なりにまとめるっていうのも必要ですよね。うん、きっとそうに違いない。
次はビューを扱います。

次: ScalaでPlayFramework: ビュー編

16
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
11