构建重复的功能

时间:2016-06-18 18:21:36

标签: php function

我已经创建了以下函数来在PHP中打印HTML标记。

function div($attr = [], $child = []) {
    $div = "<div";
    if (is_array($attr)) {
        foreach ($attr as $key => $value) {
            $div .= " " . $key . '="' . $value . '"';
        }
    }
    $div .= ">";
    if (is_array($child)) {
        foreach ($child as $value) {
            $div .= $value;
        }
    }
    $div .= "</div>";
    return $div;
}

echo div(["class" => "container"], [
        div(["class" => "title"], ["Lorem Ipsum"]])
    ]);

现在,我将此函数与多个标签一起使用; div,table,tr,td等。

对于每个标签,我一遍又一遍地声明该功能,只需对身体进行少量修改。这似乎是多余的。我想创建一个返回实际函数的main函数。例如,

$div = construct("div");
$tr = construct("div");

当然,PHP与JS不同。在JS中,这将起作用:

function construct(tagName) {
    var elm = tagName;
    return function(value) {
        console.log(elm + ": " + value);
    }
}

var div = construct("div");
var tr  = construct("tr");

div("test"); // div: test
tr("test"); // tr: test

我该怎么办?

5 个答案:

答案 0 :(得分:0)

实际上与js类似: 只需使用函数的第一个参数将元素类型作为字符串传递。

function construct($elem, $attr = [], $child = []) {
    $out = "<".$elem;
    if (is_array($attr)) {
        foreach ($attr as $key => $value) {
            $out .= " " . $key . '="' . $value . '"';
        }
    }
    $out .= ">";
    if (is_array($child)) {
        foreach ($child as $value) {
            $out .= $value;
        }
    }
    $out .= "</".$elem.">";
    return $out;
}

echo construct("div",["class" => "container"], [
    div(["class" => "title"], ["Lorem Ipsum"]])
 ]);

答案 1 :(得分:0)

您可以通过函数的参数传递标记类型。

function ConstrucElement($tag, $attr, $body)
{
    $output = '<' . $tag;

    ....

    $output .= '</' . $tag . '>';
}

答案 2 :(得分:0)

这就是我如何解决手头的问题:

function element($elementName, $attr = [], $child = []) {
    $element = "<" . $elementName;

    ...

    return $element;
}

function div($attr = [], $child = []) {
    return element("div", $attr, $child);
}

这具有启用元素特定验证的附加好处等:(伪代码)

function a($attr = [], $child = []) {
    if(attr contains no href) return ERROR; 

    return element("div", $attr, $child);
}

答案 3 :(得分:0)

进行更多挖掘,我想出了一种让它以JS方式工作的方法。在PHP: Closure - Manual的示例中使用use完成了这项工作。

function construct($tag_name = "") {
    return function($attr = [], $child = []) use ($tag_name) {
        $element = "<$tag_name";
        if (is_array($attr)) {
            foreach ($attr as $key => $value) {
                $element .= " " . $key . '="' . $value . '"';
            }
        }
        $element .= ">";
        if (is_string($child)) {
            $element .= $child;
        }
        if (is_array($child)) {
            foreach ($child as $value) {
                $element .= $value;
            }
        }
        $element .= "</$tag_name>";
        return $element;
    };
}

$h2     = construct("h2");
$span   = construct("span");
$div    = construct("div");
$table  = construct("table");
$tr     = construct("tr");
$td     = construct("td");

使用通用函数打印标签似乎是一种更实用的方法,但不是那么理想,因为代码变得难以阅读。比较以下块。

while ($row = $albums->fetch_assoc()) {
    echo $div(["class" => "album"], [
        $h2([], [$row["album"] . " (" . $row["year"] . ")"]),
        $div(["class" => "album-cover"], [
            img(["src" => "covers/" . $row["cover"]]),
        ]),
        $div(["class" => "songs"], [
            $table([], [
                loop_songs($row["album"]),
            ]),
        ]),
    ]);
}

while ($row = $albums->fetch_assoc()) {
    echo construct("div", ["class" => "album"], [
        construct("h2", [], [$row["album"] . " (" . $row["year"] . ")"]),
        construct("div", ["class" => "album-cover"], [
            construct("img", ["src" => "covers/" . $row["cover"]]),
        ]),
        construct("div", ["class" => "songs"], [
            construct("table", [], [
                loop_songs($row["album"]),
            ]),
        ]),
    ]);
}

第一个对我来说似乎更具可读性。

答案 4 :(得分:0)

这是使用__callStatic的另一种方法:

现在您可以使用以下内容构建HTML:

Build::div(...)
Build::span(...)
Build::table(...)

像这样:

<?php

class Build {
    public static function __callStatic($name, $arguments) {
        $attr = $arguments[0];
        $child = $arguments[1];

        $div = "<" . $name;

        if (is_array($attr))
            foreach ($attr as $key => $value)
                $div .= " " . $key . '="' . $value . '"';

        $div .= ">";
        if (is_array($child))
            foreach ($child as $value)
                $div .= $value;

        $div .= "</" . $name . ">";
        return $div;
    }
}

echo Build::div(["class" => "container"], [
    Build::span(["class" => "title"], ["Lorem Ipsum"])
]);

Output

<div class="container"><span class="title">Lorem Ipsum</span></div>