如何将关联数组映射到HTML元素属性?

23

我正在构建一个基本的表单构建类,以加快我的工作流程,我希望能够像这样使用属性数组:

$attributes = array(
   "type"         => "text",
   "id"           => "contact-name",
   "name"         => "contact-name",
   "required"     => true
);

将其映射到HTML元素的属性:
<input type="text" id="contact-name" name="contact-name" required />

编辑:

如何以最简洁的方式实现上述内容?我相信我可以用循环和一些连接来拼凑出来,但我感觉printf或类似的方式可以更优雅地完成它。


那么问题是什么? - Łukasz Wojciechowski
所以如果你已经构建了这样一个类,你可能尝试过一些东西?还有@nostrzak说的;) - dbf
我不明白,问题出在哪里,或者你到底想做什么呢:] - Wiggler Jtag
问题是如何将数组映射到HTML元素,这不够清楚吗? - hamishtaplin
你想根据数组生成HTML吗? - Deepak Biswal
使用Zend Form http://framework.zend.com/manual/1.12/en/zend.form.quickstart.html 并开始进行其他有用的事情。 - Cups
13个回答

29
我觉得这样应该可以了。
$attrs = join(' ', array_map(function($key) use ($attributes){
    if(is_bool($attributes[$key])){
        return $attributes[$key]?$key:'';
    }
    return $key.'="'.$attributes[$key].'"';
}, array_keys($attributes)));

$result = '<input ' . $attrs . ' />';

2
另外,我想要注意的是,如果属性值来自不可信的来源(例如用户输入),则在输出之前应对它们进行转义处理。 - e1v
你可以使用 rtrim() 函数来删除最后一个属性处的空格 :D - Cas Bloem

13
$attr = array(
    'type'     => 'text',
    'id'       => 'contact-name',
    'name'     => 'contact-name',
    'required' => true,
    'value'    => '" <b>html</b> \'test\''
);

echo '<input '. implode(' ', array_map(
    function ($k, $v) { return $k .'="'. htmlspecialchars($v) .'"'; },
    array_keys($attr), $attr
)) .' />';

1
这个答案缺少教育性的解释。 - mickmackusa

5

以下是一种非常简单的方法(当然,您可以进行扩展以提供更多功能):

$output = "<input ";
foreach($attributes as $key => $value){
    $output .= $key.'="'.$value.'" ';
}
$output .= "/>";

我已经提交了一个编辑,添加了对布尔元素的支持,正如他的问题所展示的那样。 - Robadob
谢谢,布尔元素特别引人注目。 - hamishtaplin
根据您需要的HTML类型,布尔值可能不是必需的。HTML5就像您的示例一样,但XHTML必须为required="required" - Eduard Luca
关于布尔值的评论,如果您在上面的 foreach 循环中 $output 行的前面添加以下代码片段:if(is_bool($value)) { $value = ($value) ? "true" : "false"; } ,它将把布尔值转换为字符串以在属性中使用。请注意 EduardLuca 在上面所说的,可能不需要使用布尔值。 - War10ck

5

由于http_build_query是用于将关联数组转换为字符串的,我希望在这里找到这样的解决方案。 没有找到,因此这是我的“一行代码”:

$output = '<input ' . str_replace( '=', '="', http_build_query( $attributes, '', '" ') ) . '" />';

不幸的是:

  1. 它会把布尔值转换成1/0(而不是在为false时省略它们,这可以通过使用array_filter实现,但会导致函数调用两次);
  2. 不能以所需的方式处理数组;
  3. 需要在http_build_query之后进行urldecode才能获取编码的空格(例如,在属性中有多个html类时)。

因此,仅在特定情况下适用!


如果有多个类属性由于空格而失败;$attributes = str_replace( [ '=', '+' ], [ '="', ' ' ], http_build_query( $attributes, null, '" ') ); - Luke Snowden
1
这是正确的,就像我在脚注3中指出的那样,连同解决方案。 - gruneey85

3
$output = '<input ';

foreach ($attributes as $name => $value) {
    if (is_bool($value)) {
        if ($value) $output .= $name . ' ';
    } else {
        $output .= sprintf('%s="%s"', $name, $value);
    }
}

$output .= '>';

对于XHTML更改

    if ($value) $output .= $name . ' ';

to

    if ($value) $output .= sprintf('%s="%s"', $name, $name);

并且。
    $output .= '>';

to

    $output .= '/>';

2

这是我在项目中使用的一种解决方案:

function html_attributes($attributes)
{
    if(!$attributes) return '';

    $compiled = join('="%s" ', array_keys($attributes)).'="%s"';

    return vsprintf($compiled, array_map('htmlspecialchars', array_values($attributes)));
}

1
我几年前就点赞了这个答案,现在我又需要它了。在我看来,这仍然是这里最酷的答案。话虽如此,我认为你可以通过删除附加的 .'="%s"' 中的最后一个空格来省略 rtrim( - Ortho
@Ortho,你说得完全正确,我已经相应地更新了代码。 - Ian Pollak

1

这个方法基于关联数组生成Html属性。它还支持将数组作为值(用于多值属性,如class),布尔值,html特殊字符,修剪和删除空值。

function htmlAttributes($attributes)
{

    if (!$attributes) return '';

    // handle boolean, array, & html special chars
    array_walk($attributes, function (&$value, $key) {
        $value = is_bool($value) ? $value ? 1 : 0 : $value;
        $value = is_array($value) ? implode(' ', $value) : $value;
        $value = trim($value);
        $value = htmlspecialchars($value);
    });

    // remove empty elements
    $attributes = array_filter($attributes, function ($value) {
        return strlen($value) > 0;
    });

    if (!$attributes) return '';

    $compiled = implode('="%s" ', array_keys($attributes)) . '="%s"';
    return vsprintf($compiled, array_values($attributes));
}

$attributes = array(
   'type'         => 'text',
   'id'           => 'id',
   'name'         => 'contact-name',
   'required'     => true,
   'class'        => ['class-1', 'class-2'],
   'data-active'  => false,
   'data-markup   => '" <b>html</b> \'test\'',
   'data-value'   => '',
   'data-values'  => []

);

echo htmlAttributes($attributes);
 

1
$input_attrs = array(
    'type' => 'text',
    'placeholder' => 'Placeholder',
    'value' => 'the value'
);

//Use & for modify current item in array
array_walk($input_attrs, function (&$item, $key) {
    $item =  $key . '="' . $item . '"';
});

$input = '<input '. implode(' ', $input_attrs) .' />';    

1
一个代码块作为答案并不好,尤其是在已经有很多嘈杂的回答的情况下还是一道不完整的问题。能否提供一些上下文信息? - user1531971

0
我使用这个:
function html_attributes(array $array) {
    return implode(' ', array_map(function ($key, $value) {
        if (is_array($value)) {
            $value = implode(' ', $value);
        }

        return $key . '="' . htmlspecialchars($value) . '"';
    }, array_keys($array), $array));
}

这个允许使用属性值数组。例如:

$attrs = [
    'class' => ['foo', 'bar'],
    'id' => 'baz',
];

echo html_attributes($attrs);
// -> `class="foo bar" id="baz"`

希望能对某人有所帮助!;-)


0
function createDomElement($tag, $attributes, $inner = '', $closingTag = true)
{
    return '<' . $tag . ' ' . rtrim(join(' ', array_map(function ($key) use ($attributes) {
        return is_bool($attributes[$key]) ? $attributes[$key] : $key . '="' . $attributes[$key] . '"';
    }, array_keys($attributes)))) . '>' . $inner . ($closingTag ? '</' . $tag . '>' : '');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接