ドキュメント

§カスタムルーティング

Playは、パスまたはクエリ文字列パラメータから型をバインドするメカニズムを提供します。

§PathBindable

PathBindableを使用すると、URLパスからビジネスオブジェクトをバインドできます。つまり、次のようなアクションを呼び出すために、/user/3のようなルートを定義できます。

def user(user: User) = Action {
  Ok(user.name)
}

`user`パラメータは、URLパスから抽出されたIDを使用して自動的に取得されます。たとえば、次のルート定義を使用します。

GET     /user/:user            controllers.BinderApplication.user(user: scalaguide.binder.models.User)

リクエストパスから直接バインドできるようにしたい任意の型Aに対して、PathBindable[A]の実装を提供できます。 bind(パスから値を構築する)とunbind(値からパスフラグメントを構築する)という抽象メソッドを定義します。

クラス定義の場合

case class User(id: Int, name: String) {}

`:id`パスパラメータをバインドするバインダーの使用例を以下に示します。

implicit def pathBinder(implicit intBinder: PathBindable[Int]): PathBindable[User] = new PathBindable[User] {
  override def bind(key: String, value: String): Either[String, User] = {
    for {
      id   <- intBinder.bind(key, value)
      user <- User.findById(id).toRight("User not found")
    } yield user
  }
  override def unbind(key: String, user: User): String = {
    user.id.toString
  }
}

この例では、findByIdメソッドが呼び出されてUserインスタンスが取得されます。ただし、現実の世界では、このようなメソッドは軽量で、DBアクセスなどを伴わないようにする必要があります。これは、コードがサーバーIOスレッドで呼び出され、完全にノンブロッキングである必要があるためです。

したがって、たとえば、単純なオブジェクト識別子をパスバインド可能として使用し、アクションコンポジションを使用して実際の値を取得します。

§QueryStringBindable

クエリ文字列パラメータにも同様のメカニズムが使用されます。 /ageのようなルートを定義して、次のようなアクションを呼び出すことができます。

def age(age: AgeRange) = Action {
  Ok(age.from.toString)
}

`age`パラメータは、クエリ文字列から抽出されたパラメータを使用して自動的に取得されます。例:/age?from=1&to=10

リクエストクエリ文字列から直接バインドできるようにしたい任意の型Aに対して、QueryStringBindable[A]の実装を提供できます。 PathBindableと同様に、抽象メソッドbindunbindを定義します。

クラス定義の場合

case class AgeRange(from: Int, to: Int) {}

`:from`および`:to`クエリ文字列パラメータをバインドするバインダーの使用例を以下に示します。

implicit def queryStringBindable(implicit intBinder: QueryStringBindable[Int]): QueryStringBindable[AgeRange] =
  new QueryStringBindable[AgeRange] {
    override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, AgeRange]] = {
      for {
        from <- intBinder.bind("from", params)
        to   <- intBinder.bind("to", params)
      } yield {
        (from, to) match {
          case (Right(from), Right(to)) => Right(AgeRange(from, to))
          case _                        => Left("Unable to bind an AgeRange")
        }
      }
    }
    override def unbind(key: String, ageRange: AgeRange): String = {
      intBinder.unbind("from", ageRange.from) + "&" + intBinder.unbind("to", ageRange.to)
    }
  }

Playが提供するすべてのバインダーは、unbindメソッドでフォームURLエンコーディングを自動的に適用するため、すべての特殊文字は安全にURLエンコードされます。ただし、カスタムバインダーを実装する場合、これは自動的には行われないため、必要に応じてキー/値の部分をエンコードしてください。

override def unbind(key: String, cartItem: CartItem): String = {
  // If we don't use Play's QueryStringBindable[String].unbind() for some reason, we need to construct the result string manually.
  // The key is constant and does not contain any special character, but
  // value may contain special characters => need form URL encoding for cartItem.identifier:
  "identifier=" + URLEncoder.encode(cartItem.identifier, "utf-8")
}

次: Playの拡張


このドキュメントに誤りを見つけましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを送信してください。質問やアドバイスがあれば、コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。