Thymeleaf if else 複雑な条件式の書き方をやさしく解説
新人
「先輩、Thymeleafでifやelseを使って条件分岐をしたいんですが、複雑な条件のときにうまく書けなくて困ってます。」
先輩
「ThymeleafではJavaのように直接if elseを書くわけではなく、th:ifやth:unlessを使って条件を制御するんだよ。」
新人
「なるほど。でも、ifとunlessってどう違うんですか?そして、elseはどう書くんですか?」
先輩
「それじゃあ、Thymeleafの条件分岐について順に見ていこう。pleiadesでSpring Bootのプロジェクトを作って、実際にテンプレートを動かして確認してみよう。」
1. Thymeleafとは?(テンプレートエンジンの基本)
Thymeleaf(タイムリーフ)は、Spring MVCで使われる代表的なテンプレートエンジンのひとつです。HTMLをそのままテンプレートとして扱いながら、th:textやth:ifなどの属性を使って動的に内容を切り替えることができます。つまり、HTMLにJavaの値を埋め込みながら条件分岐や繰り返しを行うことができるのが特徴です。
pleiadesのGradle環境でSpringプロジェクトを作成し、依存関係にspring-boot-starter-thymeleafを追加すれば、すぐにThymeleafを使えます。@ControllerクラスでModelに値を渡し、HTML側でそれを表示します。テンプレート分岐を実現するときは、このThymeleafの条件式がとても便利です。
2. ifとunlessの基本構文(条件分岐の考え方)
Thymeleafのth:ifは、条件がtrueのときに要素を表示します。一方で、th:unlessは、条件がfalseのときに要素を表示する構文です。つまり、ifの逆の動作をするのがunlessです。Javaのifとelseに近い関係になります。
以下のような例で、条件に応じてメッセージを切り替えることができます。
<p th:if="${user.age >= 20}">成人のユーザーです。</p>
<p th:unless="${user.age >= 20}">未成年のユーザーです。</p>
この例では、Modelに渡されたuser.ageが20以上なら上の行が表示され、それ以外なら下の行が表示されます。Thymeleafではこのように、条件分岐をHTMLの属性として直感的に書けるのが特徴です。
次に、Java側でModelに値を設定する例を見てみましょう。
@Controller
public class UserController {
@GetMapping("/user")
public String user(Model model) {
User user = new User();
user.setName("太郎");
user.setAge(18);
model.addAttribute("user", user);
return "user";
}
}
このコードでは、ControllerでUserオブジェクトを作成し、Modelに追加しています。テンプレート側では、このuserオブジェクトを使って条件分岐を行います。Thymeleaf if構文は、シンプルながら柔軟な条件式を書ける点が魅力です。
3. else相当の書き方(th:ifとth:unlessの組み合わせ)
ThymeleafにはJavaのようなelse構文は存在しません。しかし、th:ifとth:unlessを組み合わせることで、実質的に同じ動作を実現できます。
たとえば、次のように記述することで、条件がtrueの場合とfalseの場合で異なるメッセージを出し分けることができます。
<div th:if="${product.stock > 0}">
<p>在庫があります!今すぐ購入可能です。</p>
</div>
<div th:unless="${product.stock > 0}">
<p>現在在庫切れです。入荷をお待ちください。</p>
</div>
このように書くと、条件式を一度だけ指定して、trueとfalseのそれぞれで異なる内容を表示できます。Thymeleafの条件式では、HTML構造を保ったまま動的に表示を切り替えることができるため、HTMLを壊すことなく制御が可能です。
また、th:ifの中に複雑な条件を書くことも可能です。例えば、次のように複数の条件をandやorで組み合わせることもできます。
<p th:if="${user.role == 'ADMIN' or user.role == 'MANAGER'}">管理者画面へのリンクを表示</p>
<p th:unless="${user.role == 'ADMIN' or user.role == 'MANAGER'}">一般ユーザー画面です</p>
この例のように、条件式を複雑に組み合わせることで、実際のアプリケーションの要件に柔軟に対応できます。特にSpring MVCとの連携では、Controller側でModelに値を設定し、テンプレート側でThymeleaf if構文を使って条件を表現するのが基本的なパターンです。
Thymeleaf if else構文を理解しておくことで、テンプレート分岐の可読性を保ちつつ、エラーを防ぐことができます。次の記事では、複数条件の組み合わせや比較演算子の使い方をさらに詳しく見ていきましょう。
4. 複数条件の組み合わせ(and/orの使い方)
Thymeleafのif構文では、複数の条件を組み合わせることができます。Javaでよく使う&&や||の代わりに、Thymeleafではandやorを使います。これにより、複雑な条件分岐をHTMLテンプレート内で柔軟に表現できます。
たとえば、ユーザーが「有効な会員」で「年齢が20歳以上」である場合だけ特別なメッセージを表示したいときは、次のように記述します。
<p th:if="${user.isActive and user.age >= 20}">会員特典をご利用いただけます。</p>
<p th:unless="${user.isActive and user.age >= 20}">会員登録または年齢確認が必要です。</p>
この例では、2つの条件を「and」で結合しています。両方の条件がtrueである場合のみ、上のメッセージが表示されます。一方、どちらか一方でもfalseの場合はth:unless側が表示されます。
次に、「or」を使う場合を見てみましょう。ユーザーが管理者またはモデレーターのいずれかであれば、特別メニューを表示するように書けます。
<p th:if="${user.role == 'ADMIN' or user.role == 'MODERATOR'}">管理メニューが利用できます。</p>
<p th:unless="${user.role == 'ADMIN' or user.role == 'MODERATOR'}">一般ユーザー向けのページです。</p>
このように、「or」を使うと、いずれかの条件を満たすだけでtrueとみなされます。Thymeleafでは、条件を柔軟に組み合わせることで、テンプレート分岐の表現力を高めることができます。Spring MVCの@Controller側でModelに値を渡し、HTML側でif条件を使って表示を切り替えるのが基本パターンです。
@Controller
public class RoleController {
@GetMapping("/role")
public String role(Model model) {
User user = new User();
user.setRole("ADMIN");
user.setActive(true);
user.setAge(25);
model.addAttribute("user", user);
return "role";
}
}
このControllerでは、ユーザー情報をModelに格納してHTMLに渡しています。Thymeleafの条件式はModelの値を元に動的に評価されるため、ビューとビジネスロジックを明確に分離できます。
5. 比較演算子(eq, ne, gt, ltなど)の使い方
Thymeleafでは、Javaの比較演算子(==、!=、>、<など)と同じ意味を持つキーワードを使用できます。これにより、テンプレート内でも安全かつ可読性の高い条件式を書くことができます。
eq:equals(等しい)ne:not equals(等しくない)gt:greater than(より大きい)lt:less than(より小さい)ge:greater or equal(以上)le:less or equal(以下)
例えば、商品の在庫数を条件に分岐するケースを考えてみましょう。
<p th:if="${product.stock eq 0}">在庫がありません。</p>
<p th:if="${product.stock gt 0 and product.stock le 10}">在庫が少なくなっています。</p>
<p th:if="${product.stock gt 10}">在庫は十分にあります。</p>
これらの条件式はJavaの記述に非常に似ていますが、ThymeleafではHTMLテンプレート内に直接書く点が特徴です。特にeqと==は意味が似ていますが、Thymeleafでは文字列比較の際にeqを使うのが安全です。==を使うと、オブジェクトの参照比較になることがあるため、意図しない結果になる可能性があります。
また、比較演算子は数値だけでなく文字列やオブジェクトの状態にも使えます。次のような例も可能です。
<p th:if="${user.status eq 'ACTIVE'}">ユーザーは有効です。</p>
<p th:if="${user.status ne 'ACTIVE'}">ユーザーは無効です。</p>
このように、Thymeleafの条件分岐はeqやneなどのキーワードを用いることで、Javaと同じ感覚で比較を行えます。特にテンプレート条件式を多用する場合は、eqやneを積極的に使うと、コードの可読性が向上します。
6. nullチェックや空文字チェックの実装方法
Thymeleafでは、値がnullかどうか、または空文字かどうかを判定することもできます。テンプレート分岐の中でも特によく使われるのがこのチェックです。Javaではif (value != null)のように書きますが、ThymeleafではEL式を使ってより簡潔に記述できます。
以下の例は、ユーザーのニックネームがnullまたは空文字であるかどうかを判定する方法です。
<p th:if="${user.nickname != null and user.nickname != ''}">こんにちは、[[${user.nickname}]] さん!</p>
<p th:unless="${user.nickname != null and user.nickname != ''}">こんにちは、ゲストさん!</p>
このように、nullチェックと空文字チェックを組み合わせることで、テンプレート内で安全に文字列を扱えます。もし値がnullのまま出力しようとすると、意図せぬ例外や表示崩れが発生することがあります。そのため、Thymeleafの条件分岐ではこのような書き方が推奨されます。
また、Thymeleafには便利な関数#stringsがあり、これを使うともっと簡潔に記述できます。
<p th:if="${!#strings.isEmpty(user.nickname)}">ようこそ、[[${user.nickname}]] さん!</p>
<p th:unless="${!#strings.isEmpty(user.nickname)}">ようこそ、ゲストさん!</p>
#strings.isEmpty()は、文字列がnullまたは空である場合にtrueを返す関数です。これに否定演算子!をつけることで、空でない場合だけ表示されます。この書き方は実務でも非常によく使われ、テンプレートの安全性と可読性を高めます。
さらに、Spring MVCの@ControllerでModelを渡す際にも、nullが入る可能性がある変数には注意が必要です。たとえば、次のようにControllerでnicknameをModelに追加する例を考えます。
@Controller
public class GreetingController {
@GetMapping("/greet")
public String greet(Model model) {
String nickname = null; // 未設定の場合を想定
model.addAttribute("user", new User("太郎", nickname));
return "greet";
}
}
この場合、テンプレート側でth:text="${user.nickname}"を直接書くと、nullのまま出力される可能性があります。そのため、th:ifとth:unlessを活用して安全に制御するのが基本です。
Thymeleafのif条件は、Javaでのロジックとほぼ同じ感覚で書けるため、学習コストが低いのが特徴です。テンプレート条件式を活用して、より読みやすく、安全なビューを作成していきましょう。次の章では、ネスト構造(入れ子条件)やth:switchとの違いについて詳しく解説します。
7. 入れ子(ネスト)構造での条件分岐の書き方
Thymeleafのテンプレート条件分岐では、if構文を入れ子(ネスト)にして書くことができます。たとえば、ユーザーがログインしていて、かつ管理者権限を持っている場合のみ特別なメッセージを表示したいときなどに使われます。Javaでいう「ifの中にifを書く」イメージです。
次のように、th:ifの中にさらにth:ifを記述することで、条件を段階的に判定できます。
<div th:if="${user != null}">
<p>ログイン中のユーザーです。</p>
<div th:if="${user.role eq 'ADMIN'}">
<p>管理者専用のメニューを表示します。</p>
</div>
<div th:unless="${user.role eq 'ADMIN'}">
<p>一般ユーザー用のメニューを表示します。</p>
</div>
</div>
<div th:unless="${user != null}">
<p>ログインしていません。ログインしてください。</p>
</div>
この構成では、まずuserが存在するか(nullでないか)を判定し、その中でさらにroleの値を確認しています。入れ子構造を使うことで、条件ごとに異なる表示内容を細かく制御できます。
また、ネストを深くしすぎるとテンプレートが読みづらくなるため、可能な限り条件を整理し、必要最小限の階層にするのがポイントです。Thymeleafのif条件はJavaと同様の評価ルールを持つため、ネスト構造でも直感的に理解できます。
8. th:switch/th:caseを使った条件分岐との違い
Thymeleafでは、if/elseのほかにth:switchとth:caseを使った条件分岐も用意されています。これはJavaのswitch文に似た構文で、特定の値によって出し分けを行いたい場合に便利です。
if構文との違いは、「複数の条件を順番に判定する必要がない」という点です。たとえば、ユーザーのステータスによってメッセージを切り替える場合を考えてみましょう。
<div th:switch="${user.status}">
<p th:case="'ACTIVE'">アクティブユーザーです。</p>
<p th:case="'INACTIVE'">利用停止中です。</p>
<p th:case="'BANNED'">アクセス制限中です。</p>
<p th:case="*">不明な状態です。</p>
</div>
th:switchに評価対象の変数を指定し、th:caseごとに条件を定義します。最後の*はデフォルト(default)に相当し、どの条件にも一致しない場合に表示されます。
この書き方は、特定の値に基づいてテンプレートを分岐したいときに特に便利です。一方で、複数の条件をandやorで組み合わせたい場合は、th:ifやth:unlessを使う方が柔軟です。つまり、「値の比較がメインならth:switch」「論理条件が複雑ならth:if」という使い分けが重要です。
たとえば、if構文で同じことを書くと以下のようになります。
<p th:if="${user.status eq 'ACTIVE'}">アクティブユーザーです。</p>
<p th:if="${user.status eq 'INACTIVE'}">利用停止中です。</p>
<p th:if="${user.status eq 'BANNED'}">アクセス制限中です。</p>
<p th:unless="${user.status eq 'ACTIVE' or user.status eq 'INACTIVE' or user.status eq 'BANNED'}">不明な状態です。</p>
このように、if条件を並べるとやや冗長になります。th:switchを使えば同じロジックをより簡潔に書けるのです。Thymeleafテンプレート条件分岐の中でも、このswitch構文は可読性を重視したいときに最適です。
9. 実際のSpring Controllerとの連携例(Modelから値を渡して動作確認)
最後に、実際にSpring MVCの@ControllerからModelを渡し、Thymeleafの条件分岐がどのように動くかを確認してみましょう。ここでは、ユーザーの状態と権限をModelに設定し、それに応じてテンプレート側で表示を切り替えます。
@Controller
public class StatusController {
@GetMapping("/status")
public String status(Model model) {
User user = new User();
user.setName("花子");
user.setStatus("ACTIVE");
user.setRole("ADMIN");
model.addAttribute("user", user);
return "status";
}
}
このControllerでは、Userオブジェクトを作成し、ステータスと権限を設定しています。model.addAttributeでテンプレートに渡すことで、HTML側から${user.status}や${user.role}を参照できます。
次に、テンプレート「status.html」側では次のように条件分岐を記述します。
<div th:switch="${user.status}">
<p th:case="'ACTIVE'">[[${user.name}]] さんは現在アクティブです。</p>
<p th:case="'INACTIVE'">[[${user.name}]] さんは休止中です。</p>
<p th:case="'BANNED'">[[${user.name}]] さんはアクセス制限されています。</p>
</div>
<div th:if="${user.role eq 'ADMIN'}">
<p>管理者機能が有効になっています。</p>
</div>
<div th:unless="${user.role eq 'ADMIN'}">
<p>一般ユーザーとしてログイン中です。</p>
</div>
このテンプレートでは、まずth:switch構文を使ってステータスに応じたメッセージを切り替え、その下でif構文によって権限を判定しています。テンプレート条件分岐がネストされており、実際のアプリケーションでよく使う構成です。
実行すると、ブラウザには「花子 さんは現在アクティブです。」および「管理者機能が有効になっています。」が表示されます。もしController側でuser.setRole("USER")と変更すれば、表示は自動的に切り替わります。
このように、Spring MVCとThymeleafを組み合わせることで、サーバーサイドで設定したModelの値をテンプレート側で条件分岐し、柔軟に画面を制御できます。pleiadesのGradle構成でも同じように動作し、Mavenを使う場合と挙動の違いはありません。
Thymeleaf th:ifやth:unless、th:switchを適切に使い分けることで、複雑なロジックをビュー側に安全に表現できます。特に初心者のうちは、Java側でできる限りシンプルな値を渡し、テンプレート内では見た目に関する制御だけを行うのがコツです。これにより、コードの保守性が向上し、テンプレート構造も見通しやすくなります。
ここまで学んだif構文、unless構文、switch構文を使いこなせば、Thymeleafテンプレート条件分岐の基礎から応用までを一通り理解できるでしょう。次回はさらに実践的なシナリオとして、フォーム入力と連動した条件分岐を扱います。