输入
Joomla 输入 - 简介
Joomla 输入功能提供了一个易于使用的界面,用于获取和清理多个PHP 超全局变量的数据。
- HTTP GET 和 POST 参数
- 路由参数(“option”、“view”、“layout”等),这些参数是解析传入的 SEF URL 的结果。
- 与上传文件相关的信息。
- PHP
$_SERVER
数据 - 服务器和执行环境信息。
要开始使用,您必须获取 Joomla Input
类的实例。
use Joomla\CMS\Factory;
$input = Factory::getApplication()->getInput();
如果您的代码位于继承自 Joomla\CMS\MVC\Controller\BaseController 的控制器中,那么这已经为您完成了,并存储在一个受保护的变量 $input
中,因此您只需在下面的函数调用中使用 $this->input
即可,而无需先设置 $input
。
本文档说明了如何获取上面列出的数据项。
使用过滤器获取单个参数
要获取特定参数的值,请使用
$val = $input->get(param_name, default_value, filter);
其中
param_name
是一个包含要检索的参数名称的字符串。default_value
是如果未找到参数则要返回的值;它可以是字符串、整数、数组、null 等 - 任何您想要的值。filter
是一个指定以下列表中某个过滤器的字符串。如果您未指定此参数,则使用默认值“cmd”。
您可以使用此方法获取任何 GET、POST 或路由参数的值 - Input
为获取任何这些类型的参数提供了通用接口。获取特定 GET 或 POST 参数的方法在本文档后面进行了描述。
可用过滤器
下面列出了可用的过滤器,并在适当情况下进行了一些说明。过滤器可以用小写或大写指定,如果下面同一行上列出了 2 个过滤器,则表示它们是等效的。如果您需要过滤器方面更多详细信息,您可以检查 libraries/vendor/joomla/filter/src/InputFilter.php 中的源代码。
-
“INT”,“INTEGER” - 返回参数值中找到的第一个整数。例如,如果参数为“abc123def456”,则应用此过滤器后返回的值将为 123(作为整数)。
-
“UINT” - 返回一个无符号整数。例如,如果参数指定为
?p1=-2
,则此过滤器将丢弃减号,您将获得 2 作为p1
值的返回值。 -
“FLOAT”,“DOUBLE” - 返回找到的第一个浮点数。
-
“BOOL”,“BOOLEAN” - 注意这一点!如果您在 URL 中指定
?p1=false
,则p1
的值实际上是字符串“false”,并且由于这是一个非空字符串(布尔值),因此p1
将返回true
。 -
“WORD” - 过滤掉任何不是字母或下划线的字符。
-
“ALNUM” - 字母数字 - 过滤掉任何不是字母或数字的字符。
-
“CMD” - 过滤掉任何不是字母、数字、下划线、点或破折号的字符,并删除结果中的任何前导点。这是
get()
方法的默认过滤器,通常用于在 Joomla 组件中获取?option=controller.task
参数。 -
“BASE64” - 过滤掉任何不是字母、数字、正斜杠、加号或等号的字符。base64 可用于将 URL 编码为文本字符串,然后将其存储在请求参数中。例如,如果用户访问受保护的 URL,则他/她可能会被重定向到登录页面 URL,原始 URL 将被 base64 编码并作为重定向 URL 中的(返回)参数存储。用户正确登录后,将检索返回参数,并将其重定向回访问的原始 URL。(请注意,您仍然需要自己解码 base64,过滤器不会为您执行此操作)。
-
“STRING” - 将任何 HTML 实体转换为其对应的字符(例如
<
转换为<
,"
转换为双引号),然后删除任何 HTML 标签(包括属性)。例如,"<br><test>filter"
将返回“filter”。 -
“HTML” - 删除 HTML 标签,但无需事先转换 HTML 实体。例如,
"<br><test>filter"
将返回"<test>filter"
。 -
“ARRAY” - 不执行任何过滤,只是尝试将参数转换为数组。
-
“PATH” - 将输入转换为字符串并将其验证为文件路径(例如 path/to/file.png 或 path/to/dir),首先根据 Linux 路径模式进行检查,然后根据 Windows 路径模式进行检查。注意:不接受绝对路径或以尾部斜杠结尾的路径。如果它无法与有效路径匹配,则返回空字符串。
-
“RAW” - 不执行任何过滤;使用此方法时要小心,以避免对您的网站进行注入攻击!
-
“USERNAME” - 过滤掉 Joomla 用户名中不允许的字符。
或者,您可以使用特定于 Input 类型的函数,例如,而不是添加过滤器。
// Instead of:
$input->get('name', '', 'STRING');
// you can use:
$input->getString('name', '');
// Instead of:
$input->get('memberId', 0, 'INT');
// you can use:
$input->getInt('memberId', 0);
除了 getArray()
不同之外;见下文。
要检索对象,您可以使用
$obj = $input->get(param_name, null, null);
数组
只要以下情况,数组就会发挥作用。
- 数据以数组的形式从客户端发送 - 当您使用 Joomla 表单时,情况将如此,并且表单字段数据(默认情况下)以数组
jform[]
发送到服务器。 - 发送的数据以单个参数的形式,但您希望将其读入数组。
我们先考虑第二种类型。
将单个参数读入数组
有几种方法可以做到这一点,它们在应用的过滤器方面有所不同。
选项 1
$value = $input->get('p1', array(), "array");
如上所述,右侧将返回一个数组,$value[0]
将设置为 p1 的字符串值。不会对参数“p1”应用任何过滤。
选项 2
$values = $input->getArray();
这将返回所有参数作为关联数组,将参数名称映射到值。“STRING”过滤器将应用于所有参数,并且每个参数的值为
- 对于单个参数,为字符串,或者
- 对于作为数组的参数,为关联数组(同样,对每个元素应用“STRING”过滤器)。
虽然 get()
方法的默认过滤器为“CMD”,但 getArray()
方法的默认过滤器为“STRING”。
选项 3
您可以指定希望检索到数组中的参数。
$values = $input->getArray(array('p1' => '', 'p2' => '', 'p3' => ''));
这将返回一个关联数组,其中元素“p1”、“p2”和“p3”指向其值。“STRING”过滤器将应用于所有参数。这实际上与在选项 2 中调用 getArray()
相同,但限制了将返回的参数集。
选项 4
除了指定希望检索的参数外,您还可以指定要应用于每个参数的过滤器。
$values = $input->getArray(array('p1' => 'string', 'p2' => 'int', 'p3' => 'cmd'));
$values
将是一个关联数组,其中元素“p1”、“p2”和“p3”指向其值。每个参数都将根据请求的过滤器进行过滤,并且类型将设置为与过滤器匹配(例如 $value['p2]
将为 int
)。
您还可以嵌套数组以获取更复杂的值层次结构。
$values = $input->getArray(array(
'jform' => array(
'title' => 'string',
'quantity' => 'int',
'state' => 'int'
)
));
读取数组参数
如果要读取的参数已以数组的形式存在,则可以使用几种方法将其读入 PHP 数组,其中一些方法与上述方法重叠。同样,应用的过滤器可能会有所不同。在下面的选项中,假设 jform
是发送到服务器的一组值。
选项 1
$value = $input->get('jform');
$value
将是一个关联数组,其键与 jform
数组的键匹配。“CMD”过滤器将应用于所有数组元素的值,并且它们都将具有 string
类型。
选项 2
您可以定义应用于每个元素的过滤器,例如
$value = $input->get('jform', array(), "STRING");
与选项 1 一样,$value
将是一个关联数组,其键与“jform”数组的键匹配,但在这种情况下,“STRING”过滤器将应用于每个条目。
选项 3
您可以定义要捕获的 jform
数组的哪些元素,并为每个元素指定要应用的过滤器。
$values = $input->getArray(array(
'jform' => array(
'title' => 'string',
'quantity' => 'int',
'state' => 'int'
)
));
这与上一节相同。
GET 和 POST 参数
Input
的 get
和 post
属性允许您访问 HTTP GET 和 POST 参数。
$input->get // property to retrieve GET parameters
$input->post // property to retrieve POST parameters
您可以对这些属性调用get()
和 getArray()
方法来获取参数的值,如上所述,“CMD” 是 get()
的默认过滤器,“STRING” 是 getArray()
的默认过滤器。
如果您的网站使用 SEF URL,请注意这些 URL **不包含**由 Joomla 路由器解析 SEF URL 时生成的路由参数“option”、“view”等。仅返回真实的 GET 和 POST 参数。
例如,要检索 GET 参数 'p1',请使用以下代码
$value = $input->get->get('p1');
$value
将包含 GET 参数 'p1' 的值,该值使用“CMD”过滤器进行过滤。
要检索 GET 参数 'p1' 并使用“INT”过滤器,请使用(例如)以下代码
$value = $input->get->get('p1', 0, "int");
要检索所有 GET 参数
$value = $input->get->getArray();
$value
将包含 GET 参数的关联数组,其值使用“STRING”过滤器进行过滤。
要检索 POST 参数 'p1',请使用以下代码
$value = $input->post->get('p1');
$value
将包含 POST 参数 'p1' 的值,该值使用“CMD”过滤器进行过滤。
要检索所有 POST 参数
$value = $input->post->getArray();
$value
将包含 POST 参数的关联数组,其值使用“STRING”过滤器进行过滤。
要检索未应用任何过滤器数据的jform
的 POST 参数
$value = $input->post->get("jform", array(), "array");
此方法用于 Joomla 核心 MVC 代码中以检索原始表单数据。然后将数据数组传递给 Model 的validate
函数,该函数处理数据的过滤和验证。过滤使用在表单工作原理中描述的表单过滤器通过bind()
函数进行(请注意,这些过滤器与我们在此部分中讨论的Input
过滤器不同),然后根据服务器端验证中所述执行验证。
文件
您的 Joomla 表单中可能包含一个类型为“file”的 HTML 输入元素,以允许用户将文件上传到您的网站。在这种情况下,PHP 将 POST 请求的内容写入其临时目录中的文件,并提供有关上传的信息。Joomla 提供了一个易于使用的界面来访问此信息。(无法通过 GET/POST 参数获取信息)。
假设您有一个这样的表单
<form action="<?php echo Route::_('index.php?option=com_example&task=file.submit'); ?>" enctype="multipart/form-data" method="post">
<input type="file" name="jform1[test][]" />
<input type="file" name="jform1[test][]" />
<input type="submit" value="submit" />
</form>
然后您可以使用
$files = $input->files->get('jform1');
$files
然后变为类似以下内容
Array
(
[test] => Array
(
[0] => Array
(
[name] => youtube_icon.png // filename on local system
[type] => image/png // mime type
[tmp_name] => /tmp/phpXoIpSD // name given by PHP in tmp directory
[error] => 0 // should be 0 for no error
[size] => 34409 // in bytes
)
[1] => Array
(
[name] => Younger_Son_2.jpg
[type] => image/jpeg
[tmp_name] => /tmp/phpWDE7ye
[error] => 0
[size] => 99529
)
)
)
JSON
当您在 Ajax 请求的 POST 数据中以 json 字符串的形式发送数据时,您可以使用以下代码将数据检索为关联数组
$jsonArray = $input->json->get(param_name);
对于您有多个 POST 参数且其中一个是 json 字符串的情况,此方法将不起作用 - 整个主体必须是 json 字符串。Joomla 从php://input
捕获数据,并对数据调用json_decode()
。
此外,如果您使用此方法,建议将安全令牌作为 URL 中的 GET 参数之一发送。
有关工作示例,请查看 Joomla 如何处理全局配置中权限值的更新
- 在 js 文件 media/system/fields/joomla-field-permissions.js 中的
sendPermissions()
函数中 - 在 php 文件 administrator/components/com_config/src/Model/ApplicationModel.php 中的
storePermissions()
函数中。
服务器数据
您可以使用以下代码检索和清理 PHP $_SERVER 数据
$val = $input->server->get(param_name, default_value, filter);
设置值
函数set()
和def()
允许您设置输入参数及其值。
$input->set('p2', "someval");
将参数p2
的值设置为字符串“someval”(如果p2
不存在则创建它)。
$input->def('p2', "someval");
创建一个参数p2
并将其值设置为字符串“someval”,但前提是p2
不存在。如果p2
已存在,则def('p2', "someval");
不执行任何操作。
模块代码示例
以下是您可以安装和运行以演示参数值检索的简单 Joomla 模块的代码。
在文件夹mod_input
中创建以下 2 个文件
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
<name>Input demo</name>
<version>1.0.1</version>
<description>Code demonstrating use of Joomla Input class to obtain HTTP parameters</description>
<files>
<filename module="mod_input">mod_input.php</filename>
</files>
</extension>
<?php
defined('_JEXEC') or die('Restricted Access');
use Joomla\CMS\Factory;
$app = Factory::getApplication(); // equivalent of $app = JFactory::getApplication();
$input = $app->getInput();
if ($input->exists('p1'))
{
$v1 = $input->get('p1', 0, "INT"); // rhs equivalent to $input->getInt('p1', 0);
echo "<p>Int value of p1 is $v1</p>";
$v1 = $input->get('p1', 0, "UINT"); // uint
echo "<p>Uint value of p1 is $v1</p>";
$v1 = $input->get('p1', 0, "string");
echo "<p>String Value of p1 is $v1</p>";
}
else
{
echo "<p>Parameter p1 not specified</p>";
}
将 mod_input 目录压缩为mod_input.zip
。
在您的 Joomla 管理员中,转到“安装扩展”,然后通过“上传程序包文件”选项卡上传此 zip 文件以安装此示例模块。
通过编辑此模块使其可见(在“模块”页面中单击它),然后
- 将其状态设置为“已发布”
- 选择页面上要显示它的位置
- 在菜单分配选项卡上指定它应显示的页面
显示此模块出现的网页。然后将p1
参数添加到 URL 中
- 如果 URL 没有现有参数,则附加
?p1=123abc
- 如果 URL 有现有参数,则附加
&p1=123abc
您应该会看到检索p1
参数并将其传递给不同过滤器的结果。您可以尝试为p1
指定不同的值,应用不同的过滤器,并且可以使用诸如curl之类的实用程序发送 HTTP POST 参数以确认它也适用于这些参数。
组件代码示例
您还可以下载并使用此示例组件代码作为试验检索 POST 参数、文件等的依据。src/Controller/PostController.php 使用 Input 检索 POST 参数并将它们存储在会话数据中
// name of array 'jform' must match 'control' => 'jform' line in the model code
$data = $this->input->post->get('jform', array(), 'array');
// store this in the session so that we can display it in DisplayController
$app->setUserState('com_sample_form_field.post', $data);
重定向回显示表单后,View 在 src/View/Sample/HtmlView.php 中读取此存储的数据
// check if there's any POST data from the previous form submission
$this->postdata = Factory::getApplication()->getUserState('com_sample_form_field.post', null);
// and clear it, ready for the next submission
Factory::getApplication()->setUserState('com_sample_form_field.post', array());
然后在 tmpl/sample/default.php 文件中显示。
ob_start();
var_dump($this->postdata);
$post = ob_get_contents();
ob_end_clean();
...
<?php echo '<pre>' . htmlspecialchars($post, ENT_QUOTES) . '</pre>'; ?>
通过遵循此模式,您可以在 PostController 中尝试不同的方法和过滤器,然后将结果存储在会话中。然后在重定向后,您可以在 View 文件中从会话中提取数据,并在 tmpl default.php 文件中显示它。