第三章
后端开发 (续)
我们的 editReview() 函数根据传过来的数据表行对象,结合了HTML来输出内容。所以editReview() 函数总是用来显示外观,输出内容之前函数包含了一组帮助函数来增强UI元素。
说明:
JHTML::_() 做了什么?
Joomla!提供了很多自动生成HTML元素的函数,如下拉列表、复选框等。为了提供执行的效率,这些函数只有在需要的时候才会读到内存里。这个工作有 _() 函数来完成。
首先,JFactory::getEditor() 函数返回 HTML 编辑器,JHTML::_(‘behavior.calendar’) 函数会在header 中加入JavaScript 和 CSS ,这是用在评论日期字段中弹出日历的代码:
class HTML_reviews
{
function editReview( $row, $lists, $option )
{
$editor =& JFactory::getEditor();
JHTML::_('behavior.calendar');
编辑器对象的成员函数display() 返回选择的富文本编辑器的HTML ,如果富文本编辑器不存在就返回<textarea> 元素。
<td>
<?php
echo $editor->display( 'quicktake',
$row->quicktake ,
'100%', '150', '40', '5' ) ;
?>
</td>
display() 函数带有以下的参数:表单变量名、值、宽、高、列数和行数。当没有使用HTML编辑器,最后两个参数是 <textarea> 的大小。
处理数据
管理员填完表单并且当即保存按钮后,我们需要保存信息到数据库里。开始,在admin.reviews.php中创建 saveReview() 函数:
function saveReview( $option ) { global $mainframe; $row =& JTable::getInstance('review', 'Table'); if (!$row->bind(JRequest::get('post'))) { echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n"; exit(); } $row->quicktake = JRequest::getVar( 'quicktake', '', 'post', 'string', JREQUEST_ALLOWRAW ); $row->review = JRequest::getVar( 'review', '', 'post', 'string', JREQUEST_ALLOWRAW ); if(!$row->review_date) $row->review_date = date( 'Y-m-d H:i:s' ); if (!$row->store()) { echo "<script> alert('".$row->getError()."'); window.history.go(-1); </script>\n"; exit(); } $mainframe->redirect('index.php?option=' . $option, 'Review Saved'); }
首先,将全局变量 $mainframe 传进来, $mainframe 对象提供很多成员函数来控制 session 变量和headers。然后将 TableReview 类的一个实例赋值给 $row,类的名字由第一个参数和第二个参数组合而成,第二个参数是第一个参数的前缀。第二步,使用bind() 成员函数来加载表单中所有变量到 $row中。
bind() 函数传一个关联数组参数并且要数组的所有元素都要和对象的成员变量完全匹配。为了减少SQL注入的风险,我们使用 Jrequest::get() 来清除 $_POST 的值,这个过程会过滤掉所有能够控制SQL的字符。
如果 bind() 失败了会弹出一个JavaScript的警告对话框并返回到前一个页面。绑定后就可以直接操作 $row 的成员变量。既然quicktake 和 review 字段都接受HTML内容,那么它们需要对 bind() 函数进行清除 HTML的特殊处理。要做这样处理,可以使用 Jrequest 的成员函数 getVar()并传递表单的变量名、默认值、请求的数组、期望的格式和各自JREQUEST_ALLOWRAW标识。以防评论没有选择日期,我们赋了当前日期给评论日期。
最后,调用 store() 函数,把所有的成员变量都转化成 UPDATE 和 INSERT语句(由id的值决定是UPDATE还是INSERT)。因为是第一次创建记录,id没有值,所以会构建INSERT查询语句。如果有SQL错误就返回上一页,通常这一类的SQL错误都是由于 $row额外的成员变量而没有在数据表类中引起的。那么如果发现有SQL错误,第一时间就是要检查确保你的成员变量的拼写要与数据表的列一致。否则,如果SQL执行成功,将使用 $mainframe 的redirect() 函数返回组件的页面。
此时,admin.review.php 中的 switch() 语句只是执行添加任务。既然我们已经有了表单和函数,那么添加一个分支来保存我们的数据。添加以下粗体的代码:
switch($task)
{
case 'add':
editReview( $option );
break;
case 'save':
saveReview( $option );
break;
}
保存文件后访问这个地址:http://localhost/joomla/administrator/index.
php?option=com_reviews&task=add
你填好表单后点击保存,你能看到类似以下的页面:
暂时不提供图片显示,请参考《Joomla! extension development》
说明:
为什么我们不能点击“新建”按钮?
工具栏的按钮需要有名字为 adminForm 的表单才能有效,既然现在没有表单,那么点击任何的按钮都产生JavaScript错误的。当你加上 adminForm 表单后,按钮马上就生效了。
如果一切正常,那么你可以在 phpMyAdmin 中找到类似以下的数据:
暂时不提供图片显示,请参考《Joomla! extension development》
创建列表
既然我们的管理员不会有访问phpMyAdmin 的权限,我们需要创建显示评论的列表。开始我们在admin.reviews.php中添加以下函数:
function showReviews( $option )
{
$db =& JFactory::getDBO();
$query = "SELECT * FROM #__reviews";
$db->setQuery( $query );
$rows = $db->loadObjectList();
if ($db->getErrorNum()) {
echo $db->stderr();
return false;
}
HTML_reviews::showReviews( $option, $rows );
}
这个函数加载了将被显示的数据,我们得到了一个当前数据库连接的引用,然后调用它的成员函数 setQuery() ,setQuery()函数带一个 SQL 语句的字符串为参数,但只做存储之后使用而不是立即执行。当调用 loadObjectList() 函数,之前设置的SQL语句就会执行并返回记录到一个数组中。如果运行过程出现错误,那么将显示错误和停止组件运行。
如果一切正常,那么把记录结果的数组传给 admin.reviews.htlm.php 中的成员函数 showReviews(),如下:
function showReviews( $option, &$rows )
{
?>
<form action="index.php" method="post" name="adminForm">
<table class="adminlist">
<thead>
<tr>
<th width="20">
<input type="checkbox" name="toggle"
value="" MsoNormal">
count( $rows ); ?>);" />
</th>
<th class="title">Name</th>
<th width="15%">Address</th>
<th width="10%">Reservations</th>
<th width="10%">Cuisine</th>
<th width="10%">Credit Cards</th>
<th width="5%" nowrap="nowrap">Published</th>
</tr>
</thead>
<?php
$k = 0;
for ($i=0, $n=count( $rows ); $i < $n; $i++)
{
$row = &$rows[$i];
$checked = JHTML::_('grid.id', $i, $row->id );
$published = JHTML::_('grid.published', $row, $i );
?>
<tr class="<?php echo "row$k"; ?>">
<td>
<?php echo $checked; ?>
</td>
<td>
<?php echo $row->name; ?>
</td>
<td>
<?php echo $row->address; ?>
</td>
<td>
<?php echo $row->reservations; ?>
</td>
<td>
<?php echo $row->cuisine; ?>
</td>
<td>
<?php echo $row->credit_cards; ?>
</td>
<td align="center">
<?php echo $published;?>
</td>
</tr>
<?php
$k = 1 - $k;
}
?>
</table>
<input type="hidden" name="option"
value="<?php echo $option;?>" />
<input type="hidden" name="task" value="" />
<input type="hidden" name="boxchecked" value="0" />
</form>
<?php
} |