在第 4 部分中為您的 Agavi 示常式序實現一個簡單的搜索引擎並添加對多種輸出類型(XML、RSS 或 SOAP)的支持。這個 5 部分系列是為對開源、靈活並且可伸縮的 Agavi 框架感興趣的 PHP 開發人員編寫的。
簡介
在本系列的第 3 部分中,您經歷了構建基於 Web 的應用程序時經常遇到的一個任務:實現一個允許管理員通過 Web 界面執行 CRUD 操作的管理模塊。您還探索了 Agavi 的安全模型,構建了用於驗證用戶的登錄系統,以保護對應用程序資源的訪問。
現在繼續 Agavi 學習,為這個 WASP(Web 汽車銷售平台)示例應用程序添加更多功能。您將實現一個搜索引擎,允許用戶直接搜索資料庫,獲取匹配特定條件的清單。而且,Agavi 為開發人員提供了一個複雜的框架,允許他們為應用程序輕鬆添加對多種輸出類型(XML、RSS 或 SOAP)的支持。本文將學習如何通過最少的編程支持從搜索引擎返回 XML 編碼的結果。
處理搜索標準
|
到目前為止,這個 WASP 應用程序可以接受經銷商提交的車輛清單並將其存儲在資料庫中以便批准。本系列第 3 部分開發的管理模塊允許管理員審查並批准這些提交的清單,以便在 Web 站點上顯示它們。管理員還可以定義每個清單在網站上顯示的時間長度。
要使潛在買家更容易地找到滿足他們需要的車輛,現在最好嚮應用程序添加一個搜索功能。這個搜索界面將接收來自買家的特定條件,搜索批准的清單以尋找滿足條件的汽車,最後顯示結果以進一步檢查。
首先,使用 Agavi 構建腳本向 Listing 模塊添加一個新的 SearchAction:
shell> agavi action-wizard Module name: Listing Action name: Search Space-separated list of views to create for Search [Success]: Error Success |
並且更新應用程序的路由表,為這個 Action 添加一個新的路由,如 清單 1 所示:
<?xml version="1.0" encoding="UTF-8"?> <ae:configurations xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" xmlns="http://agavi.org/agavi/config/parts/routing/1.0"> <ae:configuration> <routes> ... <!-- action for listing pages "/listing" --> <route name="listing" pattern="^/listing" module="Listing"> <route name=".create" pattern="^/create___FCKpd___1quot; action="Create" /> <route name=".display" pattern="^/display/(id:\d+)___FCKpd___1quot; action="Display" /> <route name=".search" pattern="^/search___FCKpd___1quot; action="Search" /> </route> ... </routes> </ae:configuration> </ae:configurations> |
SearchAction 的默認行為是顯示一個搜索表單,以便用戶輸入各種搜索條件。完成這個任務的典型方法是對錶單使用一個 SearchInputView,對結果使用一個 SearchSuccessView。但是您已經了解了這種技術……並且我討厭乏味的重複!因此,我將進行一點小小的變化,將表單和它的結果合併到一個 SearchSuccessView 中,這也將是 SearchAction 的默認視圖(見 清單 2)。
<?php class Listing_SearchAction extends WASPListingBaseAction { public function getDefaultViewName() { return 'Success'; } } ?> |
現在看看搜索表單本身。清單 3 是 SearchSuccessView 的代碼。注意,這個視圖中使用了 AgaviFormPopulationFilter,以確保搜索表單使用用戶輸入的條件自動重新填充。
<?php class Listing_SearchSuccessView extends WASPListingBaseView { public function executeHtml(AgaviRequestDataHolder $rd) { $this->setupHtml($rd); $this->getContext()->getRequest()->setAttribute('populate', array('fsearch' => true), 'org.agavi.filter.FormPopulationFilter'); } } ?> |
清單 4 顯示了對應的 SearchSuccess 模板:
<h3>Search Listings</h3> <form id="fsearch" action="<?php echo $ro->gen('listing.search'); ?>" method="get"> <fieldset> <legend>Criteria</legend> Color: <input id="color" type="text" name="color" style="width:120px" /> Year: <input id="year" type="text" name="year" size="4" style="width:100px" /> Price: <input id="price" type="text" name="price" style="width:140px" /> <button id="search" type="submit"/> </fieldset> </form> <h3>Search Results</h3> <?php if (count($t['records']) == 0): ?> No records available <?php else: ?> <?php $x = 1; ?> <?php foreach ($t['records'] as $record): ?> <div> <strong><?php echo $x; ?>. <a href="<?php echo $ro->gen('listing.display', array('id' => $record['RecordID'])); ?>"><?php printf('%d %s %s (%s)', $record['VehicleYear'], $record['Manufacturer']['ManufacturerName'], ucwords(strtolower($record['VehicleModel'])), ucwords(strtolower($record['VehicleColor']))); ?></a> </strong> <br/> Mileage: <?php echo $record['VehicleMileage']; ?> <br/> Sale price: ___FCKpd___4lt;?php echo $record['VehicleSalePriceMin']; ?> - ___FCKpd___4lt;?php echo $record['VehicleSalePriceMax']; ?> <?php echo ($record['VehicleSalePriceIsNegotiable'] == 1) ? '(negotiable)' : null; ?> <br/> Location: <?php echo $record['OwnerCity']; ?>, <?php echo $record['Country']['CountryName']; ?> <br/> Submitted: <?php echo date('d M Y', strtotime($record['RecordDate'])); ?> <p/> </div> <?php $x++; ?> <?php endforeach; ?> <?php endif; ?> <p/> <strong> <a href="<?php echo $ro->gen('listing.create'); ?>"> Add a new listing</a> </strong> |
在 清單 4 中,您看到了模板的兩個部分。第一個部分包含一個搜索表單,用戶可以用該表單輸入他們的選購條件。這些值被提交和處理之後,第二個部分將顯示在資料庫中發現的匹配記錄。這裡還有一個添加新清單的鏈接。
為簡便起見,我將表單限制為 3 個條件:顏色、價格和製造年份。毫無疑問,這些輸入值在進入 SearchAction 之前必須接受驗證。清單 5 是必要的驗證規則:
<?xml version="1.0" encoding="UTF-8"?> <ae:configurations xmlns="http://agavi.org/agavi/config/parts/validators/1.0" xmlns:ae="http://agavi.org/agavi/config/global/envelope/1.0" parent="%core.module_dir%/Listing/config/validators.xml" > <ae:configuration> <validators> <validator class="string"> <arguments> <argument>color</argument> </arguments> <errors> <error>ERROR: Vehicle color is invalid</error> </errors> <ae:parameters> <ae:parameter name="required">false</ae:parameter> </ae:parameters> </validator> <validator class="number"> <arguments> <argument>year</argument> </arguments> <errors> <error for="type">ERROR: Vehicle year of manufacture is invalid </error> <error for="min">ERROR: Vehicle year of manufacture is before 1900 </error> <error for="max">ERROR: Vehicle year of manufacture is after 2020 </error> </errors> <ae:parameters> <ae:parameter name="type">int</ae:parameter> <ae:parameter name="min">1901</ae:parameter> <ae:parameter name="max">2020</ae:parameter> <ae:parameter name="required">false</ae:parameter> </ae:parameters> </validator> <validator class="number"> <arguments> <argument>price</argument> </arguments> <errors> <error>ERROR: Vehicle price is invalid</error> </errors> <ae:parameters> <ae:parameter name="type">int</ae:parameter> <ae:parameter name="min">0</ae:parameter> <ae:parameter name="required">false</ae:parameter> </ae:parameters> </validator> </validators> </ae:configuration> </ae:configurations> |
[火星人 ] 使用 Agavi 進行 MVC 編程簡介,第 4 部分: 創建一個帶有多種輸已經有852次圍觀