本文實例分析了Symfony頁面的基本創建方法。分享給大家供大家參考。具體如下:
這裡我們將會學習如何創建一個模塊,這是組織頁面的結構化元素。同時我們也會學習如何創創建一個分為一個動作也一個模板的頁面,之所以分為動作與模板,是因為MVC模式。鏈接與表彰是基本的頁面交互,我們將會學習如何在模板中插入這些元素並且在動作中進行處理。
創建一個模塊框架
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
>> file+ ~/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
>> file+ ~/myproject/test/functional/myapp/mymoduleActionsTest.php
>> tokens ~/myproject/test/functional/myapp/mymoduleActionsTest.php
>> tokens ~/myproject/apps/myapp/modules/mymodule/actions/actions.class.php
>> tokens ~/myproject/apps/myapp/modules/mymodule/templates/indexSuccess.php
與actions/,config/,lib/,templates/,validate/目錄相分離,這個命令只創建三個文件。位於test/目錄中的一個為單元測試。actions.class.php指向默認的模塊歡迎頁面。templates/indexSuccess.php文件為空。
在actions/actions.class.php文件中默認生成的動作:
復制代碼 代碼如下:<?php
class mymoduleActions extends sfActions
{
public function executeIndex()
{
$this->forward('default', 'module');
}
}
?>
對於每一個新的模塊,Symfony會創建一個默認的index動作。他是由一個名為executeIndex的動作方法以及一個名為indexSuccess.php的模板文件組成。我們可以通過下面的URL來浏覽相應的頁面:
http://localhost/myapp_dev.php/mymodule/index
這裡我們並不會使用默認的index動作,所以我們可以從actions.class.php文件中移除executeIndex()方法,並且從templates/目錄中刪除indexSuccess.php文件。
除了命令行,Symfony還提供了其他的方法來初始化一個模塊。其中一個方法就是手動來創建目錄與文件。在許多情況下,一個模塊的動作與模板就意味著操作一個給定數據表的數據。因為創建,獲取,更新,以及從一個數據表中刪除數據記錄的必須代碼通常都是相同的,Symfony提供了一個名為框架的機制來我們生成這些代碼。我們後續會繼續介紹。
添加一個頁面
在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!"的頁面只有一行的代碼的模板。
復制代碼 代碼如下:<p>Hello, world!</p>
如果我們需要在模板中運行一些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; ?>
<form method="post" target="/myapp_dev.php/mymodule/anotherAction">
<label for="name">What is your name?</label>
<input type="text" name="name" id="name" value="" />
<input type="submit" value="Ok" />
</form>
一個幫助器是用在模板中的由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; ?>
<?php echo form_tag('mymodule/anotherAction') ?>
<?php echo label_for('name', 'What is your name?') ?>
<?php echo input_tag('name') ?>
<?php echo submit_tag('Ok') ?>
</form>
如果在上面的代碼中,我們認為使用幫助器的版本並不會比編寫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幫助器,並且以我們通常的方式來編寫代碼,但是這會是一個巨大的損失。
注意,短開放標記的用法(<?=,等同於<?php echo)並不推薦在專業的web程序中使用,因為我們的web服務器也許會理解多個腳本語言,從而會使其變得迷惑。另外,短開放標記並不會與默認的PHP配置進行工作,而且需要修改服務來激活。最後,當我們必須處理XML與驗證時,他會出錯,因為<?在XML中有著特殊的意義。
表單處理有專門的一章進行討論,因為Symfony提供了許多工具,絕大數的幫助器,來使其簡單。我們將會在第10章了解到關於幫助器更多的內容。
鏈接到另一個動作
我們現在已經知道在動作名字與需要調用的URL之間有一個分離。所以我們使用下面的方式來創建到另一個動作的鏈接時,他只會工作在默認的路由系統中。如果我們以後決定改變URL的樣子,那麼我們就需要查看所有的模板來改變超鏈接。
超鏈接,通常的方法:
復制代碼 代碼如下:<a href="/myapp_dev.php/mymodule/anotherAction?name=anonymous">
I never say my name
</a>
要避免這樣的麻煩,我們應總是使用link_to()幫助器來我們的程序動作創建超鏈接。下面的例子演示了超鏈接幫助器的用法。
link_to()幫助器:
復制代碼 代碼如下:<p>Hello, world!</p>
<?php if ($hour >= 18): ?>
<p>Or should I say good evening? It's already <?php echo $hour ?>.</p>
<?php endif; ?>
<?php echo form_tag('mymodule/anotherAction') ?>
<?php echo label_for('name', 'What is your name?') ?>
<?php echo input_tag('name') ?>
<?php echo submit_tag('Ok') ?>
<?php echo link_to('I never say my name','mymodule/anotherAction?name=anonymous') ?>
</form>
生成的HTML與前面的相同,所不同的就在於當我們改變我們的路由規則時,所有的模板都會正確工作,並且重新格式化URL。
link_to()幫助器,就像其他的幫助器,會接受特定選項的額外參數和額外的標簽屬性。下面的例子顯示了一個可選參數以及生成的HTML。選項參數或者是一個相關的數組或者是由空格分隔的顯示key=value的簡單字符串。
大多數幫助器接收一個可選參數:
復制代碼 代碼如下:// Option argument as an associative array
<?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous',
array(
'class' => 'special_link',
'confirm' => 'Are you sure?',
'absolute' => true
)) ?>
// Option argument as a string
<?php echo link_to('I never say my name', 'mymodule/anotherAction?name=anonymous',
'class=special_link confirm=Are you sure? absolute=true') ?>
// Both calls output the same
=> <a class="special_link" onclick="return confirm('Are you sure?');"
href="http://localhost/myapp_dev.php/mymodule/anotherAction/name/anonymous">
I never say my name</a>
任何時候我們使用一個Symfony幫助器來輸出一個HTML標記時,我們可以在可選參數中插入額外的標記屬性。我們可以使用HTML 4.0的方式來編寫這樣的屬性,而Symfony將會以更簡潔的格式進行輸出。這也就是為什麼幫助器會比HTML更容易編寫的原因。
因為他需要一個額外的分析與轉換,字符串語法比數組語法要慢一些。
與表單幫助器相類似,鏈接幫助器有更多的數量和選項。
由請求得到信息
無論用戶通過表單發送信息(通常以POST請求的方式)還是通過URL(GET請求),我們可以通過帶有sfActions對象的getRequestParameter()方法的動作來獲取數據。下面的例子顯示如何在anotherAction中得到name參數的值。
在動作中由請求參數得到數據:
復制代碼 代碼如下:<?php
class mymoduleActions extends sfActions
{
...
public function executeAnotherAction()
{
$this->name = $this->getRequestParameter('name');
}
}
如果數據的處理是簡單的,我們甚至並不需要使用動作來得到請求參數。模板可以訪問一個名為$sf_params的對象,他提供了get()方法來得到請求參數,就如同動作中的getRequestParameter()方法。
如果executeAnotherAction()方法是空的,下面的例子顯示了anotherActionSuccess.php模板文件如何得到同樣的name參數。
在模板中直接由請求參數得到數據:
復制代碼 代碼如下:<p>Hello, <?php echo $sf_params->get('name') ?>!</p>
那麼為什麼不使用$_POST,$_GET或是$_REQUEST變量呢?因為我們的URL將會不同的方式進行格式化(http://localhost/articles/europe/france/finance.html),這樣通常的PHP變量就會再起作用,並且只有路由系統可以得到請求參數。而我們希望添加輸入過濾來阻止惡意代碼注入,而這只有當我們將所有的請求參數保存在一個簡潔的參數裝配器中才可能。
$sf_params對象比僅提供一個與數組等同的方法要強大得多。例如,如果我們只是希望檢測一個請求參數是否存在,我們可以簡單的使用$sf_params->has()方法,而不使用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特性來完成的。
希望本文所述對大家的symfony框架程序設計有所幫助。