Play Framework
##よく使うもの
- ソースファイルの置き場所
app
- ビルドのためのスクリプトファイル
sbt.bat
- 設定ファイル置き場
conf
- 全体のレイアウトを記述するファイルや画像などのリソースを置くフォルダ
public
- ビルド生成物が置かれるフォルダ
target
appフォルダ
- controllers ロジック
- views HTML (Scalaのコードを埋め込んだ.scala.htmlという拡張子のファイル
- モデルの定義もここに置く
- ここに作るディレクトリは、フォルダではなくパッケージになる
Welcome to Play! が表示される仕組み
routesというファイルでルーティング設定
(クライアントからサーバに送る要求の種類とURLの組み合わせを、プラグラムのメソッドに結びつける)
GETメソッドでルート(デフォルトではlocalhost:9000)にアクセスすると、
app/controllers
フォルダにあるHomeController
クラスのindex
メソッドが呼ばれる
GET / controllers.HomeController.index
↓
@()
@main("Welcome to Play") {
<h1>Welcome to Play!</h1>
}
indexメソッドによって、テンプレートindexを呼び出す
main関数を実行。
(引数として、
Welcome to Play!
を渡している) ↓ *@
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
</head>
<body>
@content
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
</body>
</html>
テンプレートindexによって、さらにmainを呼び出す
渡されてきた変数をHtmlに埋め込むには、@変数名
とする。
リンクの貼り方
routes
に記載された情報を利用する
GET / controllers.HomeController.index
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
GET /viewtest controllers.ViewTestController.index #ここへのリンクを貼りたい
html内にて、
<a href="@routes.ViewTestController.index">view test</a>
のようにする。
注意点
-
""
で囲んでも、Twirlテンプレートとしてちゃんと動いてくれる -
routes
内ではcontrollers.~~
となっているが、リンクを貼る際はroutes.~~に変えること
テンプレートへの変数の渡し方
こんな感じでテンプレートがあるとする。
@(title: String="自分で作ったファイル")
@viewtest_main("自分で作ったファイル"){
<h1>@(title+"です")</h1>
}
titleという変数を受け取れるようしているが、初期値が設定してあるのでcontrollerでは
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
@Singleton // 「シングルトン」の指定。「このクラスからは、たったひとつのオブジェクトしか作ってはいけない」という指示
class ViewTestController @Inject()(cc: ControllerComponents)
extends AbstractController(cc) { // @Inject 「ccは、フレームワークで作る」というフレームワーク内部への指示
def index() = Action { implicit request: Request[AnyContent] =>
Ok(views.html.viewtest_index())
}
}
この記述でOK。
しかし
@(title: String="自分で作ったファイル")(rnum: Int = 1)
@viewtest_main("自分で作ったファイル"){
<h1>@(title+"です")</h1>
<p>末尾が @rnum の方に大チャンス!!</p>
このように、テンプレートに変数を二つ定義しており、かつ初期値を持っている場合は、コントローラにて、
二つの変数どちらにも値を渡さず、初期値のままにする ということを伝えなければいけません。
その際は、
Ok(views.html.viewtest_index())
ではなく、(エラーが起きる)
Ok(views.html.viewtest_index()())
このように、メソッドの呼び出しにおいて()を二つ、(変数の数分)記述してプログラムに意図を伝えなければいけない。
テンプレート最上段の、@(title: String="自分で作ったファイル")(rnum: Int = 1)
に、
コントローラのviews.html.viewtest_index()()
が対応している形ですね。
そして、初期値を使わずに、コントローラから変数の値を指定する場合にも、変数の数だけ()を二つ並べます。
Ok(views.html.viewtest_index("コントローラから渡したtitle")(5))
また、テンプレート側で、変数の受け取り方を
@(title: String="自分で作ったファイル", rnum: Int = 1)
このように一つの()の中にカンマ区切りで納めると、渡し方のほうも、
Ok(views.html.viewtest_index("コントローラから渡したtitle", 5)
このように「普通の関数みたいな書き方」になります。
状況に応じて使い分けが必要
()を並べる方法は
- 渡す値が関数オブジェクトやHTMLブロックの際に見やすい
-
「変数を渡さない」という記述を、()を書くだけで簡単にできる
その反面、 - 引数が多くなった時にコンパイルに時間がかかる
という特徴があるため。
TwirlでのFor文の書き方
@(title: String= "for loopの練習", topics: Array[String])
<ul>
@for(topic <- topics) {
<li>@topic</li>
}
</ul>
@の場所がちょっとややこしいですね。