22

我正在构建一个基本的表单构建类来加快我的工作流程,我希望能够采用如下属性数组:

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

并将其映射到 html 元素的属性:

<input type="text" id="contact-name" name="contact-name" required />

编辑:

实现上述目标的最干净方法是什么?我确信我可以用循环和一些连接来拼凑一些东西,但我觉得 printf 或类似的东西可以以更优雅的方式完成。

4

12 回答 12

25

我认为应该这样做:

$result = '<input '.join(' ', array_map(function($key) use ($attributes)
{
   if(is_bool($attributes[$key]))
   {
      return $attributes[$key]?$key:'';
   }
   return $key.'="'.$attributes[$key].'"';
}, array_keys($attributes))).' />';
于 2013-08-06T13:35:07.330 回答
12
$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
)) .' />';
于 2015-12-03T10:39:50.477 回答
5

沿着这些思路(一个非常简单的方法——当然你可以扩展它,但这将为你提供基本功能):

$output = "<input ";
foreach($attributes as $key => $value){
    $output .= $key.'="'.$value.'" ';
}
$output .= "/>";
于 2013-08-06T13:31:48.543 回答
5

由于 http_build_query 用于字符串化关联数组,我希望在这里偶然发现这样的解决方案。没有找到,所以这是我的“单线”:

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

很遗憾:

  1. 它将布尔值转换为 1/0(而不是在 false 时省略它们,这可以通过使用 array_filter 来实现,但会导致双重函数调用);
  2. 没有以期望的方式处理数组;
  3. 需要urldecodeafterhttp_build_query来取回编码的空格(例如,当一个属性中有多个 html-classes 时)。

所以,只适用于某些情况!

于 2017-04-02T11:38:43.450 回答
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 . ' ';

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

    $output .= '>';

    $output .= '/>';
于 2013-11-16T07:03:27.467 回答
2

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

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

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

    return vsprintf($compiled, array_map('htmlspecialchars', array_values($attributes)));
}
于 2017-10-27T18:52:59.553 回答
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) .' />';    
于 2019-02-26T19:02:25.870 回答
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 . '>' : '');
}
于 2018-08-03T23:58:27.027 回答
0

老派 PHP 4 - 5.2 版本。这也允许class属性的数组。

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

printf(
    '<input %s />', 
    join(' ', array_map('mapAttr', array_keys($attr), array_values($attr)))
);

function mapAttr($key, $value) {
   if (is_array($value)) {
      return mapAttr($key, join(' ', $value));
   }
   if (is_bool($value)) {
      return $value ? $key : '';
   }
   return sprintf('%s="%s"', $key, $value);
}
于 2016-11-18T18:53:16.643 回答
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"`

'希望它可以帮助某人!;-)

于 2018-02-15T13:20:37.900 回答
0

这将是我的解决方案,希望对您有所帮助!

  • 使用 === 来检查布尔值,并且在一次检查中它是真的
  • 使用 addlashes 来转义放在双引号内的值的双引号
  • 在数组本身上循环并更新自己的值以准备内爆
  • 将值与空格一起内爆,这意味着无需修剪任何空白。由于布尔检查而变成 '' 的任何值都不会显示。

也显得更短了。

foreach($attr as $k=>$v){
    $attr[$k] = $v===true?$k:"$k=\"".addslashes($v)."\"";
}
echo "<input ".implode(" ",$attr)." />";
于 2019-04-08T11:59:17.147 回答
0

我还没有看到的东西,使用php 的array_reduce.

    <?php
    $attributeCollection = [
        'speed' => 'slow',
        'ball' => false,
        'globe' => true,
    ];
    $attributes = array_reduce(
            array_keys( $attributeCollection ) ,
            fn( $carry , $name ) => vsprintf(
                '%s %s="%s"' , [
                    $carry ,
                    $name ,
                    $attributeCollection[ $name ] ,
                ])
        )
    $markup = '<marquee' . $attributes . '></blink>';
    echo $markup;

使用函数

    <?php
    function attributes (?array $in = null): string
    {
        $in ??= [];
        $out = '';
        $out .= array_reduce(
            array_keys( $in ) ,
            fn( $carry , $name ) => vsprintf(
                    '%s %s="%s"' ,
                    [
                        $carry ,
                        $name ,
                        $in[ $name ] ,
                    ]
                )
        );
        return $out;
    }

    $attributes = [
        'speed' => 'slow',
        'ball' => false,
        'globe' => true,
    ];
    $markup = '<marquee' . attributes( $attributes ) . '></blink>';
    echo $markup;

支持布尔值

    <?php
    function attributes (?array $in = null): string
    {
        $in ??= [];
        $out = '';
        $out .= array_reduce(
            array_keys( $in ) ,
            fn( $carry , $name ) => is_bool($in[$name]) && true !== $in[$name]
            # fn( $carry , $name ) => !$in[$name]
               ? $carry
               : vsprintf(
                    '%s %s="%s"' ,
                    [
                        $carry ,
                        $name ,
                        is_bool($in[$name]) ? $name : $in[ $name ] ,
                    ]
                )
        );
        return $out;
    }

    $attributes = [
        'speed' => 'slow',
        'ball' => false,
        'globe' => true,
    ];
    $markup = '<marquee' . attributes( $attributes ) . '></blink>';
    echo $markup;
于 2020-07-30T14:13:06.530 回答