表单工作原理
简介
此页面描述了您如何与Joomla表单类进行一般交互,并提供了您可以安装以演示此API用法的简单组件的代码。借助下面的图表,我们将逐步介绍从显示表单到处理提交数据的每个阶段。
浅黄色的部分是Joomla库代码,特别是与表单类相关的代码。
白色背景的矩形包含您的扩展代码。
首先,您需要使用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 标签,您可以看到过滤是如何删除它们的。