SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

symfony入門

symfony入門(4):symfonyプログラミング 開発のテクニック(前篇)

symfonyによる実践的なPHPアプリケーション開発


ビュー総括:レイアウトや断片化など(2/2)

フラグメンテーション:パーシャル/コンポーネント/コンポーネントスロット/スロット

 ここではsymfonyにおけるコードの断片化の方法について紹介します。断片化により同じコードを何度も記述する必要がなくなり、また変更が生じた場合でも一カ所書き換えるだけで全体に反映されるのでメンテナンスなどがしやすくなります。

パーシャル:アクションを必要としないテンプレートの断片

パーシャル
パーシャル

 パーシャルでは、モジュールのテンプレートフォルダ内に「_<パーシャル名>.php」というファイルを作りその中に呼び出したいテンプレートの断片を入れておきます。例えば次のような内容になります。

<?php echo $a->getId() ?>
<?php mail_to($a->getMail(), 'メールを送る') ?>

 これは、複数のモジュールから呼び出す事が可能です。呼び出す時は

include_partial('<モジュール名>/<パーシャル名>',
 array(<パーシャル内で必要となる変数の配列>))

 とします。第一引数は呼び出し元とパーシャルのモジュールが同一の場合、モジュール名を省略できます。また、アプリケーションフォルダ直下の「templates/」フォルダ内に置いたパーシャルは、'global'モジュールの一部分とみなされ、

include_partial('global/<パーシャル名>',array(...))

 と呼び出す事になります。第2引数には、例えばarray('a' => $bbsdata)のような感じで、オブジェクトを配列で入れるなどします。

コンポーネント:アクションを必要とするテンプレートの断片と、そのアクション

コンポーネント
コンポーネント

 パーシャルで表示する内容にデータの抽出やソートなどといったロジックが必要な場合、アクションをパーシャルに添える事ができます。これがコンポーネントです。コンポーネントで使用するアクションは、「actions」フォルダ内に「components.class.php」というファイルを作成し、次のように記述します(モジュール名bbsdata、パーシャル名Headlinesとします)。

<?php
class bbsdataComponents extends sfComponents
{
  public function executeHeadlines()
  {
    ...
    (ここにアクション/ロジックを配置)
  }
}
?>

 クラス名は<小文字モジュール名>Components、関数名はexecute<パーシャル名(最初大文字)>()としてください。さらにパーシャル単独の時同様に「_<パーシャル名>.php」ファイルをテンプレートフォルダに配置します。呼び出しは

include_component('モジュール名', 'パーシャル名')

 で行います。パーシャル呼び出し時同様に、配列で変数を渡す事もできます。

 以下に、パーシャル・コンポーネントを用いたごく簡単なサンプルを示します(fragmentアクションとします)。

fragmentSuccess.php
パーシャル使用例 <br />
<?php include_partial('mod1/date', array('f' => 'yyyy年 MM月dd日')) ?>
<br />
コンポーネント使用例 <br />
<?php include_component('mod1', 'date2',
 array('f' => 'yyyy年 MM月dd日')) ?>

<br />
_date.php
<?php use_helper('Date') ?>
今日は:<?php echo format_date(date("Y/n/j"), $f) ?>
<br />
_date2.php
<?php use_helper('Date') ?>
<?php echo format_date(date("Y/n/j"), $f) ?>現在、
<?php echo $message ?>
<br />

 「_date.php」「_date2.php」共に、$fに日付のフォーマットを受け取っています。双方のパーシャルで用いられているformat_date()は直前の行で宣言されている「Date」ヘルパーの一つで、サイトの国際化などに関連して日付のフォーマットを整えるためのヘルパーです。第1引数で日付を受け取り、第2引数でフォーマットを指定します。詳細は次回紹介します。

components.class.php
<?php

class mod1Components extends sfComponents
{
  public function executeDate2()
  {
    $this->message = 'コンポーネントを使用しています。';
  }
}

?>

 アクション「executeDate2()」から、パーシャル「_date2.php」へ$messageを送っています。

fragmentアクション実行例
fragmentアクション実行例

コンポーネントスロット:動的なコンポーネントと、その設定(view.yml)

コンポーネントスロット
コンポーネントスロット

 呼び出し元などによりコンポーネントに変化を期待する場合は、コンポーネントを複数用意して、モジュール内「view.yml」に呼び出すコンポーネント名とそれが存在するモジュール名とを指定することによってそれを実現します。コンポーネントスロットと呼ばれ、

include_component_slot('コンポーネントスロット名')

 として呼び出します。これは、呼び出し元モジュールフォルダ内の「view.yml」の設定に従ってコンポーネントを呼び出します。

view.yml例
all:
  components:
    sidebar:  [bar, user]

 上記は、コンポーネントスロット「sidebar」についての設定です。include_component_slot('sidebar')として呼び出された場合、barモジュールの「components.class.php」内の関数executeUser()が実行され、同じくbarモジュール内のパーシャル「_user.php」が呼び出されます。

 コンポーネントスロットが用いられる場面としては、例えば「layout.php」内で配置したコンポーネントの内容を、呼び出し元により切り替えたい場合などです。

 以下にコンポーネントスロットのごく簡単な実例を示します。まず「layout.php」にコンポーネントスロットを配置します。

layout.php(抜粋)
<i>Copyright(c) 2005-2007, Wings Project. All Right Reserved.</i>
<br />
<hr>
<?php include_component_slot('date3') ?>
</body>

 これを2つのモジュール「mod1」「mod2」から呼び出すとします。モジュールごとの「view.yml」は次のようになります。

mod1/config/view.yml(抜粋)
all:
  metas:
    title: サンプルアプリケーション
  components:
  date3: [mod1, date3]  (mod1のdate3コンポーネントを呼び出す)
mod2/config/view.yml
# view.yml mod2
all:
  metas:
    title: モジュール-2
  components:
  date3: [mod2, date]   (mod2のdateコンポーネントを呼び出す)

 モジュールごとに呼び出すコンポーネントを指定できるので、「layout.php」上の同じ位置に、呼び出し元モジュールごとに個別のコンポーネントを呼び出すことが可能になります。次のように2つのコンポーネントを用意します。

mod1/templates/_date3.php
<?php use_helper('Date') ?>
<?php echo format_date(date("Y/n/j"), 'MM/dd/yyyy') ?>現在、
<?php echo $message ?>
<br />
mod1/actions/components.class.php(抜粋)
  public function executeDate3()
  {
    $this->message = 'コンポーネントスロットを使用しています。';
  }
mod2/templates/_date.php
<?php use_helper('Date') ?>
今日は:<?php echo format_date(date("Y/n/j"), 'yyyy/MM/dd') ?>
<br />
<?php echo $message ?>
mod2/actions/components.class.php(抜粋)
  public function executeDate()
  {
    $this->message = 'mod2のコンポーネントスロットを使用しています。';
  }

 結果は以下のようになります。

mod1から呼び出されたコンポーネントスロット
mod1から呼び出されたコンポーネントスロット
mod2から呼び出されたコンポーネントスロット
mod2から呼び出されたコンポーネントスロット

スロット:アクションによる動的なレイアウト生成などに用いるテンプレートコード

 スロットは、どこでも定義でき、どこでも呼び出しが行えるという、コンポーネントスロットよりも高速な仕組みです。

 ここでチェックしておきたいのは、

  • 読み込みはテンプレート(この中でパーシャルが呼び出される)→レイアウトの順
  • スロットを定義する前に呼び出す事はできない

 という2点です。

 例えばスロットをコンポーネントスロットのように使うとすれば、呼び出し元テンプレートでスロットを定義し、レイアウトで呼び出すという流れになります。しかし「view.yml」を必要としないスロットは、アクションごとに定義することもできます。

 スロットの定義は「slot('<スロット名>')」と「end_slot()」の間でなされ、「include_slot('<スロット名>')」ヘルパーで呼び出します。

 また、「has_slot('<スロット名>')」関数でそのスロットが定義されているかを知る事ができるので、定義されていない場合どうするかといった管理も可能です。

 以下に、スロットをindex、fragment各アクションに実装したごく簡単な例を示します。コンポーネントスロット同様に、まず「layout.php」にスロットを配置します。

layout.php(抜粋)
<body>
<?php if(has_slot('actionname')): ?>
<?php include_slot('actionname') ?>
<br />
<?php endif; ?>

 上記では、スロット「actionname」が定義されていれば表示するよう設定しています。

 続いてindexSuccess、fragmentSuccessの各テンプレートにそれぞれ以下を追記し、個別にスロットを定義します。

indexSuccess.php(追記分)
<?php slot('actionname') ?>
これは「index」アクションの結果です。
<?php end_slot() ?>
fragmentSuccess.php(追記分)
<?php slot('actionname') ?>
これは「fragment」アクションの結果です。
<?php end_slot() ?>

 各アクションのスロット呼び出しの結果は次のようになります。

indexアクションから呼び出されたスロット
indexアクションから呼び出されたスロット
fragmentアクションから呼び出されたスロット
fragmentアクションから呼び出されたスロット

断片化要素一覧

 ここまで一通り断片化の方法を見てきましたので、ここでまとめて表にしておきます。

断片化要素のまとめ
断片構成要素呼び出し方用途
パーシャルパーシャルinclude_partial()アクションを必要としないテンプレートを断片化したい時
コンポーネントパーシャル・コンポーネントinclude_component()アクションと共にテンプレートを断片化したい時
コンポーネントスロット複数のパーシャルとコンポーネント・view.ymlinclude_compoment_slot()呼び出し元でコンポーネントを使い分けたい時
スロット(ヘルパーで挟まれた領域)include_slot()アクションごとに動的な内容を盛り込みたい時
smartyとの連携について
 smartyとの連携についてはこれまで要望が高かったもののなかなか実現されませんでした。しかし最近smarty連携を実現するプラグインが出ましたので、次回プラグインの項で紹介します。

次のページ
ルーティング

この記事は参考になりましたか?

symfony入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 川北 季(カワキタ ミノル)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1063 2007/03/09 10:05

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー