이 장에서는 페이지를 구성하는 구조 요소인 모듈을 만드는 방법을 알아봅니다. 동시에 액션과 템플릿으로 구분되는 페이지를 만드는 방법도 알아보겠습니다. 이유는 MVC 패턴 때문입니다. 링크와 인식은 기본적인 페이지 상호 작용이며 이러한 요소를 템플릿에 삽입하고 작업에서 처리하는 방법을 알아봅니다.
모듈 프레임워크 만들기
2장에서 배운 것과 똑같이 Symfony는 페이지를 모듈로 구성합니다. 페이지를 생성하기 전에 모듈을 생성하고 Symfony가 인식할 수 있는 파일 구조를 가진 빈 쉘로 초기화해야 합니다.
Symfony 명령줄은 모듈 생성을 자동화합니다. init-module 작업을 호출하고 프로그램 이름과 모듈 이름을 매개변수로 사용하기만 하면 됩니다. 이전 장에서는 myapp 프로그램을 만들었습니다. 이 프로그램에 mymodule 모듈을 추가하려면 다음 명령을 입력하면 됩니다:
> cd ~/myproject
> ~/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
>> file+ ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php
>> dir+ ~/myproject/apps/myapp/modules/mymodule/validate
>> 파일+ ~/myproject/test/function/myapp/mymoduleActionsTest.php
>> /test/function/myapp/mymoduleActionsTest.php
>> 토큰 ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php
>> 토큰 ~/myproject/apps /myapp/modules/mymodule/templates/indexSuccess.php
는 actions/,config/,lib/,templates/,validate/ 디렉터리와 구분됩니다. 이 명령은 세 개의 파일만 생성합니다. test/ 디렉터리에 있는 것이 단위 테스트입니다. actions.class.php는 기본 모듈 시작 페이지를 가리킵니다. template/indexSuccess.php 파일이 비어 있습니다.
actions/actions.class.php 파일에서 기본적으로 생성되는 액션:
<?php class mymoduleActions extends sfActions { public function executeIndex() { $this->forward('default', 'module'); } }http://localhost/myapp_dev.php/mymodule/index
이 장에서는 기본 인덱스 액션을 사용하지 않으므로 액션을 사용할 수 있습니다. ExecutionIndex 제거 () 메서드를 .class.php 파일에서 삭제하고 template/ 디렉터리에서 indexSuccess.php 파일을 삭제합니다.
Symfony는 명령줄 외에도 모듈을 초기화하는 다른 방법도 제공합니다. 한 가지 방법은 디렉터리와 파일을 수동으로 만드는 것입니다. 많은 경우 모듈의 작업과 템플릿은 주어진 데이터 테이블의 데이터를 조작하기 위한 것입니다. 데이터 테이블에서 데이터 레코드를 생성, 가져오기, 업데이트 및 삭제하는 데 필요한 코드는 일반적으로 동일하기 때문에 Symfony는 이 코드를 생성할 수 있는 프레임워크라는 메커니즘을 제공합니다. 이 기술에 대해 더 자세히 알아볼 수 있는 14장을 확인하세요.
페이지 추가
Symfony에서 페이지 뒤의 로직은 액션에 저장되고 표면은 템플릿에 저장됩니다. 논리가 없는 페이지에는 여전히 빈 작업이 필요합니다.
액션 추가
"Hello, world!" 페이지는 myAction 액션을 통해 액세스됩니다. 이 작업을 생성하려면 다음과 같이 mymoduleActions 클래스에 ExecutionMyAction 메서드를 추가하면 됩니다.
<?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特性来完成的。