跳至主要内容
版本:5.1

表单工作原理

简介

此页面描述了您如何与Joomla表单类进行一般交互,并提供了您可以安装以演示此API用法的简单组件的代码。借助下面的图表,我们将逐步介绍从显示表单到处理提交数据的每个阶段。

浅黄色的部分是Joomla库代码,特别是与表单类相关的代码。

白色背景的矩形包含您的扩展代码。

Basic Form

首先,您需要使用Joomla标准表单字段类型在XML中定义表单。请参阅下面的组件代码以了解示例。简单来说,XML文件中每个字段元素都映射到表单中的HTML(主要是“input”)元素,XML字段属性映射到(input)元素属性。许多可能的字段属性都列在文本表单字段类型中。

步骤1 加载表单

步骤1是用户导航到您显示表单的网页的地方。

您首先必须实例化Joomla表单类的实例,您可以通过从依赖注入容器中获取FormFactory并调用createForm来完成此操作。您可以使用以下代码

$form = Factory::getContainer()->get(FormFactoryInterface::class)->createForm("sample", array("control" => "myform"));

在上面的代码(取自下面的示例代码)中,我们创建了一个表单实例并为其命名为“sample”(您可以随意命名,它只需要唯一,以便它不会与同一网页上的任何其他Joomla表单冲突),并且还传递了一个包含"control" => "myform"的数组。然后HTML输入元素将具有设置为“myform[message]”,“myform[email]”等的名称属性。当用户提交表单时,数据项将以这种方式通过HTTP POST参数传递,然后非常容易将这些数据获取到PHP数组中。

接下来,我们让表单类加载包含表单定义的XML文件

$form->loadFile("sample_form.xml");  // pass the file path and name of the XML form definition

表单对象将文件读入内存(作为PHP SimpleXMLElement)并解析XML以确保其有效。SimpleXMLElement由图中带有“xml”的蓝色矩形表示。

步骤2 提供预填充数据

您可以为所需的任何表单元素提供值。例如,如果此表单用于编辑数据库中的记录,则您将使用数据库中现有的字段值对其进行预填充。您可以通过设置一个关联数组$data来提供值,其中对于数组的每个元素

  • 键是字段的name(在xml文件中)
  • 值是您想要预填充该字段的内容

您将$data数组作为参数传递给表单bind方法,然后Joomla表单将此数据存储在表单实例中——由图中的蓝色条表示。

步骤3 以HTML输出表单

您调用renderField

echo $form->renderField($name);

其中$name是XML文件中字段的name,并且您将返回可以回显到输出的HTML。Joomla处理其表单的XML表示以获取与传入的name相关的部分,生成此HTML元素的HTML并根据您在步骤2中传入的预填充数据包含html value属性。

输出表单时,您还需要将输入元素包含在<form>元素中并添加submit按钮。

步骤4 用户提交表单

用户在您的HTML表单中输入数据并单击submit按钮。浏览器会向<form>元素中指定的URL生成HTTP POST请求,并在名为myform(或您之前选择的任何option)的数组中传递给服务器,用户输入的值;数组中的每个元素都以HTML输入元素的name属性为键。

Joomla将此POST路由到您的组件。由于这是一个新的HTTP请求,因此先前的表单实例不再存在,因此您必须重复步骤1以创建表单实例并将XML表单定义文件加载到内存中。

步骤5 处理HTTP POST数据

在此步骤中,您处理提交的数据。这涉及4个部分

获取POST数据

您可以使用Joomla输入功能来获取用户输入的数据。例如

$app = Factory::getApplication();
$data = $app->input->post->get('myform', array(), "array");

将把POST myform参数读入关联数组。

过滤数据

对接收到的任何数据进行消毒以避免黑客的注入攻击至关重要。许多输入方法都应用了过滤,但如果您将它们直接读入数组(如上所示),则不会应用任何过滤,您必须使用例如显式执行此操作

$filteredData = $form->filter($data);

这会对每个输入值应用过滤。应用于字段的过滤器由表单XML文件中该字段上的“filter=…”属性控制,或者如果不存在,则默认过滤器将从数据值中删除HTML标记等。可能的过滤器是在libraries/src/Form/Filter中的类。请注意,这些表单字段过滤器与输入过滤器不同。

验证数据

您可以通过调用以下内容来验证用户输入的数据

$result = $form->validate($data);

Joomla将用户输入的数据与您在表单XML文件中定义的验证进行比较,并为验证失败的字段生成错误。

提供用户反馈

如果有验证错误,则应将这些错误显示给用户,并重新显示表单,并使用用户之前输入的(已过滤的)数据预填充字段。

如果没有错误,则可以向用户确认这一点,并显示下一个网页。

示例组件代码

下面是您可以安装以演示Joomla表单基本用法的少量组件的代码。将以下3个文件放入名为“com_sample_form1”的文件夹中。然后压缩文件夹以创建com_sample_form1.zip并将其作为组件安装到您的Joomla实例中。

为简单起见,此组件使用Joomla 3定义组件的方式,这在Joomla 5下不起作用。如果您想要一个在Joomla 5下也能工作的等效组件,则可以下载并安装此zip文件

com_sample_form1.xml 组件的清单文件

<?xml version="1.0" encoding="utf-8"?>
<extension type="component" version="3.1.0" method="upgrade">

<name>com_sample_form1</name>
<version>1.0.0</version>
<description>Sample form 1</description>

<administration>
</administration>

<files folder="site">
<filename>sample_form1.php</filename>
<filename>sample_form.xml</filename>
</files>
</extension>

sample_form.xml 包含表单定义的XML的文件

<?xml version="1.0" encoding="utf-8"?>
<form>
<field
name="message"
type="text"
label="Enter message"
size="40"
class="inputbox"
required="true" />
<field name="email"
type="email"
label="Enter email"
required="true"
size="40"
class="inputbox" />
<field name="telephone"
type="telephone"
label="Enter telephone number"
required="true"
size="40"
class="inputbox"
validate="tel" />
</form>

sample_form1.php 组件代码。

<?php
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Form\Form;
use Joomla\CMS\Factory;

$form = Form::getInstance("sample", __DIR__ . "/sample_form.xml", array("control" => "myform"));
$prefillData = array("email" => ".@.");

if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
$app = JFactory::getApplication();
$data = $app->input->post->get('myform', array(), "array");
echo "Message was " . $data["message"] .
", email was " . $data["email"] .
", and telephone was " . $data["telephone"] . "<br>";
$filteredData = $form->filter($data);
$result = $form->validate($filteredData);
if ($result)
{
echo "Validation passed ok<br>";
}
else
{
echo "Validation failed<br>";
$errors = $form->getErrors();
foreach ($errors as $error)
{
echo $error->getMessage() . "<br>";
}
// in the redisplayed form show what the user entered (after data is filtered)
$prefillData = $filteredData;
}
}

$form->bind($prefillData);
?>
<form action="<?php echo JRoute::_('index.php?option=com_sample_form1'); ?>"
method="post" name="sampleForm" id="adminForm" enctype="multipart/form-data">

<?php echo $form->renderField('message'); ?>

<?php echo $form->renderField('email'); ?>

<?php echo $form->renderField('telephone'); ?>

<button type="submit">Submit</button>
</form>

安装完成后,导航到您的站点并将以下参数添加到URL:?option=com_sample_form1。然后您应该会看到显示的表单,其中包含3个必填字段

  • 用于消息的通用文本输入字段
  • 电子邮件输入字段,预填充字符串“.@.”。
  • 电话号码输入字段。

并使用浏览器的开发工具,您可以将HTML属性与XML表单定义中的属性进行比较。

请注意,现代浏览器会对您输入的值进行一些验证,特别是它们会验证电子邮件地址,并会强制您在设置了“required”属性的字段中输入内容,但(目前)不会对电话号码字段进行验证。

一旦您在字段中输入有效数据并按下提交,数据将使用相同的 URL 发送到服务器(再次使用浏览器的开发工具查看参数),并且将运行示例代码的 POST 部分。这将运行过滤和验证例程。如果存在验证错误(电话字段有一些验证),则代码会输出错误消息,并在重新显示表单之前使用用户之前输入的数据预填充表单。通过在您输入的数据值中包含 html 标签,您可以看到过滤是如何删除它们的。