2016-06-18 162 views
1

我已經創建了以下函數來在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等。

對於每個標籤,我都會一遍又一遍地聲明函數,而對body進行很少的修改。這似乎是多餘的。我想創建一個返回實際功能的主函數。例如,

$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 

我應該如何繼續?

+1

爲什麼不創建通用功能這會將標籤名稱作爲參數之一? – ShiraNai7

回答

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"]), 
      ]), 
     ]), 
    ]); 
} 

第一次似乎更具可讀性給我。

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"]]) 
]); 
0

您可以通過函數的參數傳遞標記類型。

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

    .... 

    $output .= '</' . $tag . '>'; 
} 
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); 
} 
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>