joomla插件开发入门(六)
介紹
本文重點關注為管理員向當前的靜態頁面/文章添加功能。對于管理員,當前默認的視圖是沒有什么用的。它并沒有做什么實質工作– 只是顯示了存儲在數據庫中的條目。
為了讓它更具實用性,我們需要添加一些按鈕和鏈接。本文為組件擴展內容管理的任務。將要增加的典型任務是添加、變更和刪除。
增加互動
將在兩個層面添加互動。在管理員框架層面增加工具條及在文章自身層面增加鏈接引用和表單提交。
了解基礎知識,查看Joomla MVC組件開發– 第4部分– 創建管理員界面。
工具條
你可能已經注意到在其它Joomla組件的管理員面板上方出現的工具條。我們的組件同樣也需要一個。Joomla做到這個非常簡單。我們將添加按鈕刪除記錄、編輯記錄和創建新記錄。我們也將添加一個顯示在工具條上的標題。
通過向視圖中增加代碼來實現這些。我們使用Joomla JToolBarHelper類的靜態方法來增加按鈕。代碼如下:
JToolBarHelper::title( JText::_('Hello Manager'), 'generic.png');
JToolBarHelper::deleteList();
JToolBarHelper::editListX();
JToolBarHelper::addNewX();
這三個方法將創建想要的按鈕。deleteList()方法最多三個可選參數– 第一個參數是一個顯示給用戶的字符串,用來確認他們要刪除記錄。第二個參數是發送的查詢任務(默認是'remove');第三個參數是顯示在按鈕上的文本。
editListX() 和addNewX()每個方法最多兩個可選參數。第一個參數是任務(默認值分別是edit和add),第二個參數是顯示在按鈕上的文本。
<!--[if !supportLists]-->§ <!--[endif]-->你可能已經注意到在之前的模板中和這里都使用了JText::_ 方法。這是個方便的功能,它讓組件的翻譯更加容易。JText::_ 方法將查找組件語言文件中的字符串,并返回轉換后的字符串。如果沒有找到轉換文本,則返回你傳遞給它的字符串。如果你要將組件翻譯成其它語言,所要做的就是創建語言文件,并將引號內的字符串映射為翻譯版本的字符串。
選擇框和鏈接
現在,我們有了按鈕。其中兩個按鈕用來處理已存在的記錄。但是,我們怎么知道該處理那條記錄呢?這需要讓用戶告訴我們。要做到這些,需要為表格添加選擇框,從而用戶能選擇明確的記錄。這在模板中實現。
需要向表格增加額外的列來增加選擇框。我們在已存在的兩列之間增加該列。
在列頭,我們增加一個選擇框,用來切換其下所有選擇框的選中或未選中狀態:
<th width="20">
<input type="checkbox" name="toggle" value="" οnclick="checkAll(<?phpecho count( $this->items ); ?>);" />
</th>
Javascript函數checkAll內置在Joomla的基本Javascript包中,它提供了我們想要的功能。
現在,我們向獨立的行增加選擇框。Joomla的JHTML類有一個方法JHTML::_(),它將為我們生成選擇框。我們向循環中增加下面的代碼行:
$checked = JHTML::_('grid.id', $i, $row->id);
這行之后:
$row=& $this->items[$i];
然后,我們在已存在的兩列之間中增加一個單元格:
<td>
<?phpecho$checked; ?>
</td>
必須先選中想要編輯的選擇框,然后再向上移動點擊編輯按鈕,這樣做不夠方便。因此,我們增加一個鏈接,這樣就會直接鏈接到greeting的編輯表單。我們在調用JHTML::_()方法之后,增加下面的代碼行來生成HTML鏈接:
$link =JRoute::_('index.php?option=com_hello&controller=hello&task=edit&cid[]='. $row->id);
然后,為顯示greeting文本的單元格加上鏈接:
<td>
<a href="<?php echo $link; ?>"><?php echo$row->greeting; ?></a>
</td>
你應該注意到了這個鏈接指向hello控制器。這個控制器將處理greeting的數據操作。
如果你還記得前面的代碼,在表單的底部有四個隱藏的字段。第一個輸入字段是'option’。這個字段是必須的,填寫我們的組件名。第二個輸入字段是’task’。當點擊工具欄的按鈕時,設置這個表單屬性。如果省略了這個輸入字段,會產生Javascript錯誤并且按鈕也無法運行。第三個輸入字段是’boxchecked’。這個字段一直跟隨當前選中的選擇框編號。編輯和刪除按鈕將對該值進行檢查來確保它大于0,而且如果該值沒有設置將不允許提交表單。第四個輸入字段是’ controller’。用來指定由hello控制器來處理該表單觸發的任務。
下面是完整的default.php文件源代碼:
<?phpdefined('_JEXEC') or die('Restrictedaccess'); ?>
<form action="index.php" method="post" name="adminForm">
<div id="editcell">
<table class="adminlist">
<thead>
<tr>
<thwidth="5">
<?phpecho JText::_('ID'); ?>
</th>
<thwidth="20">
<input type="checkbox" name="toggle" value="" οnclick="checkAll(<?php echo count( $this->items );?>);" />
</th>
<th>
<?phpecho JText::_('Greeting'); ?>
</th>
</tr>
</thead>
<?php
$k = 0;
for($i=0, $n=count($this->items); $i < $n; $i++)
{
$row =& $this->items[$i];
$checked = JHTML::_('grid.id', $i, $row->id);
$link = JRoute::_('index.php?option=com_hello&controller=hello&task=edit&cid[]='. $row->id);
?>
<tr class="<?php echo "row$k"; ?>">
<td>
<?phpecho$row->id; ?>
</td>
<td>
<?phpecho$checked; ?>
</td>
<td>
<a href="<?php echo$link; ?>"><?php echo$row->greeting;?></a>
</td>
</tr>
<?php
$k = 1- $k;
}
?>
</table>
</div>
<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
<input type="hidden" name="controller" value="hello" />
</form>
現在hellos視圖完成了。
Getting Down and Dirty: Doing the Real Work
現在,Hellos視圖已經完成,是轉向Hello控制器和模型的時候了。這里,將完成真正的工作。
Hello 控制器
Hello控制器工作時,我們的默認控制器不會妨礙它– 它要做的一切的就是顯示視圖。
我們需要能夠處理從Hellos視圖發起的任務:添加、編輯和刪除。創建Hello控制器(位于控制器子目錄)用來實際執行添加、編輯和刪除單個條目。
本質上講,添加和編輯是同樣的任務:它們都是向用戶顯示一個編輯greeting的表單。唯一的不同是,添加顯示一個空白表單,而編輯顯示一個帶有數據的表單。既然它們很相似,我們將添加任務映射到編輯任務的處理中。這在我們的構造函數中指定:
/**
* constructor(registers additional tasks to methods)
* @return void
*/
function __construct()
{
parent::__construct();
// Register Extra tasks
$this->registerTask('add', 'edit');
}
JController::registerTask方法的第一個參數是被映射的任務,第二個參數是映射的目標任務。
我們將開始處理編輯任務。對于編輯任務來講,控制器的工作是相當簡單。所有要做的就是指定加載的視圖和布局(hello視圖和表單布局)。我們也將告訴Joomla,當編輯greeting時禁用mainmenu。這能防止用戶離開未保存的記錄。
編輯任務的處理看起來如下:
/**
* display the editform
* @return void
*/
function edit()
{
JRequest::setVar('view', 'hello');
JRequest::setVar('layout', 'form' );
JRequest::setVar('hidemainmenu', 1);
parent::display();
}
注意:關于命名約定:入口調用程序(hello.php)來假定控制器的文件名和類名。針對這個列子,匯總如下:
Defaultcontroller path: …/controller.php
Defaultcontroller class name: HellosController
Requestedcontroller path …/controllers/<requestName>.php
Requestedcontroller class name: HellosController<requestName>
admin/controllers/hello.php中的控制器源代碼:
<?php
/**
* Hello Controllerfor Hello World Component
*
* @package Joomla.Tutorials
* @subpackageComponents
* @linkhttp://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_4
* @license GNU/GPL
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
/**
* Hello HelloController
*
* @package Joomla.Tutorials
* @subpackageComponents
*/
classHellosControllerHello extends HellosController
{
/**
*constructor (registers additional tasks to methods)
* @returnvoid
*/
function__construct()
{
parent::__construct();
// Register Extra tasks
$this->registerTask('add' , 'edit');
}
/**
* displaythe edit form
* @returnvoid
*/
functionedit()
{
JRequest::setVar('view', 'hello');
JRequest::setVar('layout', 'form' );
JRequest::setVar('hidemainmenu', 1);
parent::display();
}
}
Hello 視圖
Hello視圖將顯示讓用戶編輯greeting的表單。hello視圖的顯示方法要做一些簡單的任務:
<!--[if !supportLists]-->§ <!--[endif]-->從模型中獲取數據
<!--[if !supportLists]-->§ <!--[endif]-->建立工具條
<!--[if !supportLists]-->§ <!--[endif]-->將數據注入模板
<!--[if !supportLists]-->§ <!--[endif]-->調用display()方法來渲染模板
因為要在一個視圖中同時處理編輯和添加任務,這變得有點復雜。在工具條中,我們要讓用戶知道他們是在添加,還是編輯。因此,我們必須確定那個任務被觸發了。
既然,已經從模型中取得了想要顯示的數據記錄,我們就能使用這個數據來決定那個任務被觸發了。如果是編輯任務,那么記錄的id字段會被設置。如果是添加任務,那么id字段不會設置。這可以用來確定,我們是有一個新記錄,還是現有記錄。
我們添加兩個按鈕到工具條:保存和取消。雖然功能是一樣的,但是我們還是要根據是新增還是現有記錄,來顯示不同的按鈕。如果是新增記錄,我們將顯示取消。如果是現有記錄,我們將顯示關閉。
因而,我們的顯示方法如下:
/**
* display methodof Hello view
* @return void
**/
function display($tpl = null)
{
//get the hello
$hello =& $this->get('Data');
$isNew = ($hello->id < 1);
$text = $isNew ? JText::_('New') : JText::_('Edit');
JToolBarHelper::title( JText::_('Hello').': < small><small>[ ' . $text.']</small></small>');
JToolBarHelper::save();
if($isNew) {
JToolBarHelper::cancel();
}else{
// for existing items the button is renamed`close`
JToolBarHelper::cancel('cancel', 'Close');
}
$this->assignRef('hello', $hello);
parent::display($tpl);
}
admin/views/hello/view.html.php中的視圖源代碼:
<?php
/**
* Hello View forHello World Component
*
* @package Joomla.Tutorials
* @subpackageComponents
* @linkhttp://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_4
* @license GNU/GPL
*/
// No direct access
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.view');
/**
* Hello View
*
* @package Joomla.Tutorials
* @subpackageComponents
*/
classHellosViewHello extends JView
{
/**
* displaymethod of Hello view
* @returnvoid
**/
functiondisplay($tpl = null)
{
//get the hello
$hello =& $this->get('Data');
$isNew = ($hello->id < 1);
$text = $isNew ? JText::_('New') : JText::_('Edit');
JToolBarHelper::title( JText::_('Hello').': < small><small>[ ' . $text.']</small></small>');
JToolBarHelper::save();
if($isNew) {
JToolBarHelper::cancel();
}else{
// for existing itemsthe button is renamed `close`
JToolBarHelper::cancel('cancel', 'Close');
}
$this->assignRef('hello', $hello);
parent::display($tpl);
}
}
Hello 模型
我們的視圖需要數據。因而,我們需要創建一個模型來模擬hello。
模型將有兩個屬性:_id和_data。_id將保存greeting的id,而數據保存在_data中。
我們從構造函數開始,它將嘗試從查詢中獲取id:
/**
* Constructor thatretrieves the ID from the request
*
* @access public
* @return void
*/
function __construct()
{
parent::__construct();
$array = JRequest::getVar('cid', 0, '', 'array');
$this->setId((int)$array[0]);
}
JRequest::getVar()方法用來從request中獲取數據。第一個參數是表單的變量名稱。第二個參數是變量在未找到值時的默認賦值。第三個參數是獲取數據方式的名稱(如:get, post),最后一個是變量強制轉換的數據類型。
構造函數將cid數組的第一個數據賦值給id。
setId()方法用來設置id值。更改模型指向的id意味著id將指向錯誤的數據。因此,當設置id時,我們將清除數據屬性:
/**
* Method to setthe hello identifier
*
* @access public
* @param int Hello identifier
* @return void
*/
function setId($id)
{
// Set id and wipe data
$this->_id = $id;
$this->_data = null;
}
最后,我們需要一個方法來獲取數據:getData()
getData將檢查_data屬性是否已經設置,如果已經設置了,就簡單的返回該數據。否則,將從數據庫中加載數據。
/**
* Method to get ahello
* @return objectwith data
*/
function & getData()
{
// Load the data
if(empty($this->_data )){
$query = ' SELECT* FROM #__hello '.
' WHEREid = '.$this->_id;
$this->_db->setQuery($query);
$this->_data = $this->_db->loadObject();
}
if(!$this->_data){
$this->_data = new stdClass();
$this->_data->id = 0;
$this->_data->greeting = null;
}
return$this->_data;
}
表單
現在,剩下的工作是建立用來填充數據的表單。既然,我們為表單指定了布局,那么該表單將執行位于hello視圖模板目錄下的form.php文件。
<?phpdefined('_JEXEC') or die('Restrictedaccess'); ?>
<form action="index.php" method="post" name="adminForm" id="adminForm">
<div class="col100">
<fieldset class="adminform">
<legend><?php echo JText::_('Details');?></legend>
<table class="admintable">
<tr>
<tdwidth="100" align="right"class="key">
<label for="greeting">
<?phpecho JText::_('Greeting'); ?>:
</label>
</td>
<td>
<input class="text_area" type="text" name="greeting" id="greeting" size="32" maxlength="250" value="<?php echo $this->hello->greeting;?>" />
</td>
</tr>
</table>
</fieldset>
</div>
<div class="clr"></div>
<input type="hidden" name="option" value="com_hello" />
<input type="hidden" name="id" value="<?php echo$this->hello->id; ?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="controller" value="hello" />
</form>
注意,除了輸入字段,還有隱藏的id字段。用戶不需要編輯該id(并且是不能編輯),所以,我們在表單中默默傳遞它。
已實現的功能
到目前為止,我們的控制器僅能處理兩個任務:編輯和添加。但是,我們也有按鈕來保存、刪除和取消記錄。我們需要編寫代碼來處理和執行這些任務。
保存記錄
按照常理,下一步是實現保存記錄的功能。通常,這需要一些開關和邏輯來處理不同的情況,比如創建一個新記錄(INSERT查詢)和更新現有記錄(UPDATE查詢)之間的不同。而且,從表單獲取數據并放入查詢語句也有些復雜。
Joomla 框架為你想到了這些。JTable類讓你在不用關心SQL語句的情況下,方便地處理數據庫記錄。同時,HTML表單的數據轉移到數據庫也將變得容易。
創建表格類
JTable類是一個抽象類,你可以繼承子類來處理指定的表。要使用它,只需要簡單地創建一個JTable類的的子類,添加數據庫字段作為屬性,并且重寫構造函數來指定表名和主鍵。
這是我們的JTable類:
<?php
/**
* Hello Worldtable class
*
* @package Joomla.Tutorials
* @subpackageComponents
* @linkhttp://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_4
* @license GNU/GPL
*/
// No direct access
defined('_JEXEC') or die('Restrictedaccess');
/**
* Hello Tableclass
*
* @package Joomla.Tutorials
* @subpackageComponents
*/
classTableHello extends JTable
{
/**
* Primary Key
*
* @var int
*/
var $id = null;
/**
* @var string
*/
var $greeting = null;
/**
* Constructor
*
* @paramobject Database connector object
*/
function__construct( &$db){
parent::__construct('#__hello', 'id', $db);
}
}
你會看到,我們定義了兩個字段:id字段和greeting字段。然后,我們定義了一個構造函數,其調用了父類的構造函數,并將表名(hello)、主鍵的字段名(id)和數據庫連接對象傳遞給它。
這個文件應該叫做hello.php,放在組件管理單元的tables目錄下。
在模型中實現功能
現在,我們準備向模型里面增加一個方法來保存記錄。這個方法叫做store。store()方法做三個事情:綁定表單數據到TableHello對象,檢查以確保記錄被正確組裝,保存記錄到數據庫。
這個方法如下:
/**
* Method to storea record
*
* @access public
* @return boolean True on success
*/
function store()
{
$row =& $this->getTable();
$data = JRequest::get('post');
// Bind the form fields to the hello table
if(!$row->bind($data)){
$this->setError($this->_db->getErrorMsg());
returnfalse;
}
// Make sure the hello record is valid
if(!$row->check()){
$this->setError($this->_db->getErrorMsg());
returnfalse;
}
// Store the web link table to the database
if(!$row->store()){
$this->setError($this->_db->getErrorMsg());
returnfalse;
}
returntrue;
}
這個方法被添加到hello模型。
這個方法接受一個參數:我們要存儲到數據庫的數據組成的數組。稍后將會看到,從request中獲取數據很容易。
你會看到,第一行返回一個JTable對象的引用。如果表格命名正確,我們不需要指定它的名字– JModel類知道到哪里去找到它。你可能還記得,我們將表格類叫做TableHello,并把該類放到了tables目錄下的hello.php文件中。如果遵循該約定,JModel類能自動創建你的對象。
第二行從表單中獲取數據。用JRequest類實現非常容易。在本例中,我們獲取用'POST'方法提交的所有變量。這些變量以關系數組形式返回。
剩下的簡單– 綁定、檢查和存儲。bind()方法將數組的數據復制到對應表格對象的屬性。在本例中,將獲取的id和greeting的值,復制到TableHello對象。
check()方法將執行數據校驗。在JTable()類中,這個方法簡單地返回true。雖然,現在沒有為我們提供任何價值,但是在將來使用TableHello類時,我們就可以通過調用這個方法進行數據檢查。在TableHello類中,我們可以重寫該方法,來執行適合的檢查。
store()方法將對象中的數據存儲到數據庫。如果id是0,它將創建一個新記錄(INSERT),否則它將更新現有記錄(UPDATE)。
向控制器添加任務
現在,我們準備向控制器中添加任務了。既然,我們觸發的任務叫做'save',那么我們的方法必須被命名為'save'。這很簡單:
/**
* save a record(and redirect to main page)
* @return void
*/
function save()
{
$model = $this->getModel('hello');
if($model->store()){
$msg = JText::_('Greeting Saved!');
}else{
$msg = JText::_('Error Saving Greeting');
}
// Check the table in so it can be edited....we are done with it anyway
$link = 'index.php?option=com_hello';
$this->setRedirect($link, $msg);
}
我們所要做的就是獲取模型,并調用store()方法。然后,我們使用setRedirect()方法,重定向返回到greeting列表。我們也順便傳遞一個信息,以顯示在頁面的頂部。
刪除記錄(在模型中實現該功能)
在模型中,我們檢索要刪除的ID列表,并調用JTable類來刪除它們。
具體如下:
/**
* Method to deleterecord(s)
*
* @access public
* @return boolean True on success
*/
function delete()
{
$cids = JRequest::getVar('cid', array(0), 'post', 'array');
$row =& $this->getTable();
foreach($cidsas$cid){
if(!$row->delete($cid)){
$this->setError($row->getErrorMsg());
returnfalse;
}
}
returntrue;
}
我們調用JRequest::getVar()方法從request中獲取數據,然后調用$row->delete()方法刪除每一行。我們可以在模型中保存錯誤消息,如果需要,可以在后面再獲取它們。
在控制器中處理刪除任務
這和處理保存任務的save()方法類似:
/**
* remove record(s)
* @return void
*/
function remove()
{
$model = $this->getModel('hello');
if(!$model->delete()){
$msg = JText::_('Error: One or MoreGreetings Could not be Deleted');
}else{
$msg = JText::_('Greeting(s) Deleted');
}
$this->setRedirect('index.php?option=com_hello', $msg);
}
取消編輯操作
我們為了取消編輯操作,所要做的就是重定向返回到主視圖:
/**
* cancel editing arecord
* @return void
*/
function cancel()
{
$msg = JText::_('Operation Cancelled');
$this->setRedirect('index.php?option=com_hello', $msg);
}
結論
現在,我們已經實現了一個基本的組件后端。我們能夠編輯前端顯示的條目。我們也展示了模型、視圖和控制器之間的互動。我們還展示了如何擴展JTable類,來方便地訪問數據庫中的表。還可以看到如何使用JToolBarHelper來創建組件的按鈕欄,讓組件變得標準化。
(全部完)
轉載于:https://www.cnblogs.com/ikodota/articles/2220517.html
總結
以上是生活随笔為你收集整理的joomla插件开发入门(六)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: postgres使用dblink
- 下一篇: Java文件非法字符