この章では、ページを構成する構造要素であるモジュールの作成方法を学びます。同時に、アクションとテンプレートに分かれたページの作成方法も学びます。アクションとテンプレートに分かれている理由は、MVC パターンによるものです。リンクと認識は基本的なページ インタラクションであり、これらの要素をテンプレートに挿入し、アクションで処理する方法を学びます。
モジュールフレームワークの作成
第 2 章で学んだとおり、Symfony はページをモジュールに編成します。ページを作成する前に、モジュールを作成し、それを Symfony が認識できるファイル構造を持つ空のシェルに初期化する必要があります。
Symfony コマンドラインはモジュールの作成を自動化します。 init-module タスクを呼び出し、プログラム名とモジュール名をパラメータとして使用するだけです。前の章では、myapp プログラムを作成しました。このプログラムに mymodule モジュールを追加するには、次のコマンドを入力します:
> cd ~/myproject
> symfony init-module myapp mymodule
> dir+ ~/myproject/apps/myapp/modules / mymodule
>> dir+ ~/myproject/apps/myapp/modules/mymodule/actions
>> ファイル+ ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php
>> dir+ ~/myproject/apps/myapp/modules/mymodule/config
> dir+ ~/myproject/apps/myapp/modules/mymodule/lib
> dir+ ~/myproject/apps/myapp/modules/mymodule /templates>> ファイル+ ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php
> dir+ ~/myproject/apps/myapp/modules/mymodule/validate
> ~/myproject/test/function/myapp/mymoduleActionsTest.php
>> トークン ~/myproject/test/function/myapp/mymoduleActionsTest.php
> トークン ~/myproject/apps/myapp/modules/mymodule / events/actions.class.php
>> トークン ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php
は、actions/,config/,lib/,templates/,validate/ ディレクトリに対応します切り離された場合、このコマンドは 3 つのファイルのみを作成します。 test/ ディレクトリにあるのは単体テストです。 events.class.php は、デフォルトのモジュールのウェルカム ページを指します。 templates/indexSuccess.php ファイルは空です。
actions/actions.class.php ファイル内のデフォルト生成アクション:
<?php class mymoduleActions extends sfActions { public function executeIndex() { $this->forward('default', 'module'); } }新しいモジュールごとに、Symfony はデフォルトのインデックスアクションを作成します。これは、executeIndex という名前のアクション メソッドと、indexSuccess.php という名前のテンプレート ファイルで構成されます。次の URL から対応するページを参照できます:
http://localhost/myapp_dev.php/mymodule/index
この章ではデフォルトのインデックスアクションを使用しないため、actions.class.php から開始できます。ファイルからexecuteIndex()メソッドを実行し、templates/ディレクトリからindexSuccess.phpファイルを削除します。
コマンドラインに加えて、Symfony はモジュールを初期化するための他のメソッドも提供します。 1 つの方法は、ディレクトリとファイルを手動で作成することです。多くの場合、モジュールのアクションとテンプレートは、特定のデータ テーブルのデータを操作することを目的としています。データテーブルからデータレコードを作成、取得、更新、削除するために必要なコードは通常同じであるため、Symfony はこのコードを生成するためのフレームワークと呼ばれるメカニズムを提供します。このテクニックについて詳しくは、第 14 章をご覧ください。
ページを追加する
Symfony では、ページの背後にあるロジックはアクションに保存され、サーフェスはテンプレートに保存されます。ロジックのないページでも空のアクションが必要です。
アクションを追加します
「Hello, world!」このページには、myAction アクションを通じてアクセスします。このアクションを作成するには、以下に示すように、mymoduleActions クラスにexecuteMyAction メソッドを追加するだけです。
<?php class mymoduleActions extends sfActions { public function executeMyAction() { } }
动作方法的名字总是execute'Xxx'()的形式,其中名字的第二部分是动作的名字,并且第一个字母大写。
现在我们可以请求下面的URL:
http://localhost/myapp_dev.php/mymodule/myAction
Symfony将会抱怨丢失了myActionSuccess.php模板。这是正常的。在Symfony中,一个页面通常是由一个动和与一个模板组成的。
URL是响应的一部分
Symfony包含一个路由系统允许我们在实际的动作名与需要调用的URL格式之间有一个完整的分隔。这允许自定义URL的自定义格式,就如同他是响应的一部分。我们不再为文件的结构或是请求的参数据限制,一个动作的URL看起来就我们所希望的解析。例如,到一个名为article模块的索引动作调用通常如下面的样子:
http://localhost/myapp_dev.php/article/index?id=123
这个URL由一个数据获取一篇指定的文章。但是URL可以通过在routingyml配置文件中作一些小的改动而以一种完全不同的方式进行编写:
http://localhost/articles/europe/france/finance.html
这样的URL不仅对于搜索引擎友好的,他对于用户来说也是十分重要的,这样用户就可以将地址栏作为一个伪码命令来自定义查询,例如下面的例子:
http://localhost/articles/tagged/finance+france+euro
Symfony知道如何为用户解析并生成URL。路由系统会自动从一个简洁URL中脱去所请求的参数,并使其为动作可用。他同时也会格式化响应中所包含的超链接,从而使其看起来更为简洁。我们将会在第九章了解这个特性的更多内容。
总之,这就意味着我们命名程序的动作的方式不应受到调用他们的URL的样子的影响,而是受程序中动作的函数控制。一个动作的名了解释了动作实际所做的内容,而且通常为不定式格式中的一个动词(例如show,list,edit)。动作的名字可以做到对于终端用户完全不可见,从而不必担心使用显式的动作名。我们可以有效的利用代码注释来解释我们的函数功能,从而使代码更读。
添加一个模板
动作需要一个模板来进行封装。一个模板就是位于一个模块的templates/目录的一个文件,通常是以动作和动作的词尾来进行命名的。默认的动作词尾为"success",所以为myAction动作所创建的模板文件应命名为myActionSuccess.php。
模板只包含表现代码,所以在其中要包含尽可有少的PHP代码。实际上,一个显示"Hello,world!"的页面只有一行的代码的模板。
e388a4556c0f65e1904146cc1a846beeHello, world!94b3e26ee717c64999d7867364b1b4a3
如果我们需要在模板中运行一些PHP代码,我们应避免使用下面所列的通常的PHP语法。相反,应使用另一种PHP语法来编写我们的模板,从而使得代码对于非PHP程序来说更易于理解。不仅最终代码是正确的,而且有助于我们在动作中保持复杂的PHP代码,因为只有控制语句有对应代码。
通常的PHP语法如下:
<p>Hello, world!</p> <?php if ($test) { echo "<p>".time()."</p>"; } ?>
替代的PHP语法如下:
<p>Hello, world!</p> <?php if ($test): ?> <p><?php echo time(); ?></p> <?php endif; ?>
由动作向模板传递信息
动作的工作是要完成所有复杂的计算,数据读取以及测试,并且设置要输出或是测试的模板变量。Symfony使得动作类的属性在全局名字空间中为模板可用。下面显示如何由动作向模板传递信息。
在动作中设置动作属性从而使其为模板可用:
<?php class mymoduleActions extends sfActions { public function executeMyAction() { $today = getdate(); $this->hour = $today['hours']; } }
模板直接访问动作属性:
<p>Hello, world!</p> <?php if ($hour >= 18): ?> <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> <?php endif; ?>
模板已经可以访问一些数据,而不需要在动作中设置任何变量。每一个模板通常可以调用$sf_context,$sf_request,$sf_params,$sf_user对象的方法。他们包含与当前内容,请求,请求参数以及会话相关的数据。我们很快就会学到他们的用法。
使用表单向用户收集信息
表单是向用户收集信息的一个好方法。使用HTML编写表单以及表单元素有时是相当麻烦的,尤其是当我们希望适用于XTHML时更是如此。我们可以用通常的方式在Symfony模板中包含表单元素,如下面所示,但是Symfony提供了帮助器从而使得这个任务更为简单。
模板可以包含通常的HTML代码:
<p>Hello, world!</p> <?php if ($hour >= 18): ?> <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> <?php endif; ?>
一个帮助器是用在模板中的由Symfony定义的PHP函数。他输出HTML代码,并且比我们自己编写实际的HTML代码要快速得多。使用Symfony帮助器,我们用下面的代码得到的输出结果与上面通常的HTML代码相同:
<p>Hello, world!</p> <?php if ($hour >= 18): ?> <p>Or should I say good evening? It's already <?php echo $hour ?>.</p> <?php endif; ?>
如果在上面的代码中,我们认为使用帮助器的版本并不会比编写HTML代码快,那么我们可以考虑一下下面的情况:
<?php $card_list = array( 'VISA' => 'Visa', 'MAST' => 'MasterCard', 'AMEX' => 'American Express', 'DISC' => 'Discover'); echo select_tag('cc_type', options_for_select($card_list, 'AMEX')); ?>
这会得到下面的HTML输出结果:
<select name="cc_type" id="cc_type"> <option value="VISA">Visa</option> <option value="MAST">MasterCard</option> <option value="AMEX" selected="selected">American Express</option> <option value="DISC">Discover</option> </select>
在模板中使用的帮助器的好处就在于加快了编码的速度,代码的清晰与简洁。而代价就是我们需要花费时进行学习。所以我们可以在模板中不使用Symfony帮助器,并且以我们通常的方式来编写代码,但是这会是一个巨大的损失。
注意,短开放标记的用法(9eee67b8e03f03e11e407215ebc041e8has()方法,而不使用get()测试实际的值。
在模板中测试请求参数的存在:
<?php if ($sf_params->has('name')): ?> <p>Hello, <?php echo $sf_params->get('name') ?>!</p> <?php else: ?> <p>Hello, John Doe!</p> <?php endif; ?>
我们已经猜到了,这可以在单一的代码行中编写。与Symfony中大多数的获取方法一样,动作中的getRequestParameter()方法与模板中的$sf_params->get()(实际上调用同一个对象的相同主法)方法接受第二个参数:如果没有提供请求参数则使用默认值:
<p>Hello, <?php echo $sf_params->get('name', 'John Doe') ?>!</p>
总结
在Symfony中,页面是由一个动作(actions/actions.class.php文件中以execute为前缀的一个方法)和一个模板(templates/目录下的一个文件,通常以Success.php结尾)组成的。他们通地在程序中的函数组织在一个模块中。编写模板是由帮助器来完成的,而帮助器则是由Symfony提供的返回HTML代码的函数。而我们需要将URL看作响应的一部分,而URL在需要可以格式化,所以我们应避免在动作命名中使用到URL的直接引用或者是请求参数检索。
一旦我们知道了这些基本原则,我们就可以使用Symfony来编写一个完整的Web程序了。但是我们的路还有很长,因为我们在程序开发过程需要处理的每一个任务由一些Symfony特性来完成的。