跳至主要内容
版本:5.1

服务器端验证

简介

Joomla提供了一个框架,用于实现客户端和服务器端的验证。

客户端验证是在浏览器中使用JavaScript执行的,JavaScript与网页一起下载。

服务器端验证是在HTTP POST请求发送表单字段时,在服务器上的PHP中执行。

其中,服务器端验证更为重要,因为黑客可以使用curl等工具直接向您的Web服务器发送HTTP POST请求,从而绕过您的HTML表单及其客户端验证。

本节概述了Joomla中的服务器端验证:以下内容描述了客户端验证。

服务器端验证

这是通过在表单定义中指定validate=...属性触发的。在前面各节中使用的示例表单中,电话号码字段存在验证

<field name="telephone"
type="telephone"
label="Enter telephone number"
required="true"
size="40"
class="inputbox"
validate="tel" />

validate="tel"行触发此字段上的验证,它将使用libraries/src/Form/Rule中的TelRule中的test函数检查字段值是否有效。

您可以通过查看libraries/src/Form/Rule目录中的类文件来查看Joomla提供的验证规则列表,并选择要对表单中的字段运行的验证例程。例如,要使用EmailRule,您需要在表单定义中的电子邮件字段中包含validate="email"

自定义服务器端验证

您可以通过编写自定义验证规则来定义字段的自定义验证。

com_exampleform示例组件(可从这里下载)提供了另一个服务器端验证的工作示例。

在本节中,我们将以一个名为“custom”的自定义规则为例,我们将使用它来替换Joomla提供的电话号码验证。您当然可以根据需要命名自己的规则。然后您需要执行3件事

  • 在字段定义中,针对该字段添加属性validate="custom"
  • 编写您的CustomRule.php文件 - 我们很快就会讲到它
  • 通过addruleprefix属性告诉Joomla在哪里可以找到您的CustomRule类

假设您的com_example组件在您的XML清单文件中定义了

<namespace path="src">Mycompany\Component\Example</namespace>

并且您决定将您的规则存储在管理员区域中的src/Rule/CustomRule.php中,那么您将拥有

<field 
addruleprefix="Mycompany\Component\Example\Administrator\Rule"
name="telephone"
type="telephone"
label="Enter telephone number"
required="true"
size="40"
class="inputbox"
validate="custom"
message="The telephone number field is wrong" />

并在您的CustomRule.php内部

namespace Mycompany\Component\Example\Administrator\Rule;
class CustomRule

如果您可以将自定义验证规则指定为正则表达式,那么最简单的选择是重用Joomla FormRule类,该类使用受保护的变量$regex验证值

namespace Mycompany\Component\Example\Administrator\Rule;
use Joomla\CMS\Form\FormRule;
class CustomRule extends FormRule
{
protected $regex = '^[0-9\*\#]+$';
}

然后,Joomla FormRule将根据覆盖的$regex值验证字段,在本例中,检查电话号码是否仅包含字符0到9、*和#。

如果您的验证不能表示为正则表达式,那么您将必须自己提供test函数,遵循libraries/src/Form/Rule中其他验证规则的示例

/**
* Method to test the range for a number value using min and max attributes.
*
* @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control value. This acts as an array container for the field.
* For example if the field has name="foo" and the group value is set to "bar" then the
* full field name would end up being "bar[foo]".
* @param Registry $input An optional Registry object with the entire data set to validate against the entire form.
* @param Form $form The form object for which the field is being tested.
*/
public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null) {}

从注释中可以看出,您被传递了很多信息,以防您的验证例程需要访问它!例如,Joomla NumberRule测试值是否在XML表单中字段定义中设置的“min”和“max”属性之间,它从$element参数中获取这些限制。同样,您可以在字段定义中指定自己的属性,从$element参数中提取它们,并在对用户输入的值进行验证时使用它们。您只需要从test函数返回truefalse即可。

其他验证

除了针对字段的任何指定验证外,Joomla还将对数据执行两次检查

  • 如果设置了属性required,则它将验证是否已输入值
  • 如果设置了属性disabled,则它将验证是否未输入值(默认值除外)

验证错误消息

默认情况下,当字段验证失败时,Joomla会输出“无效字段”错误消息。要使Joomla输出自定义消息,您可以将message="错误的电话号码"属性包含到字段属性中,就像在本页前面电话字段定义中所做的那样。

由于字段属性包含在传递给验证test函数的XML元素中,因此您可以从test方法设置此属性。以下是电话号码验证规则的示例。

<?php
namespace Mycompany\Component\SampleForm2\Site\Rule;
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Form\FormRule;
use Joomla\Registry\Registry;
use Joomla\CMS\Form\Form;

class TelephoneRule extends FormRule
{
protected $regex = '^[0-9\#\*]+$'; // just numbers plus * plus #

public function test(\SimpleXMLElement $element, $value, $group = null, Registry $input = null, Form $form = null)
{
if (preg_match(\chr(1) . $this->regex . \chr(1) . $this->modifiers, $value)) {
return true;
}

$attr = $element->attributes();
$error_message = 'The telephone number ' . $value . ' is wrong';
// how you write the message attribute to the XML element depends on whether it's already set
if (isset($attr['message'])) {
$element->attributes()->message = $error_message;
} else {
$element->addAttribute('message', $error_message);
}
return false;
}
}