我有一系列HTML标记:
class sampleHTML {
public function __construct( $tag = [] ) {
$html = [
[
'type' => 'p',
'class' => '.sample-class',
'content' => 'Sample content'
],
[
'type' => 'div',
'class' => '.sample-class-2',
'content' => 'Sample content 2'
],
];
foreach( $html as $tag ) {
new Tag( $tag );
}
}
}
我想从数组中生成HTML。到目前为止,我有以下类来生成HTML。
class Tag {
public $tag;
public function __construct( $tag = [] ) {
$this->tag = $tag;
switch ($tag['type']):
case 'p':
$this->render_p();
break;
case 'div':
$this->render_div();
break;
endswitch;
}
private function render_p() {
echo '<p class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</p>';
}
private function render_div() {
echo '<div class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</div>';
}
}
没关系,但我想通过使用子类和删除开关来改善我的代码。类似于以下内容:
class Tag {
public $tag;
public function __construct( $tag = [] ) {
$this->tag = $tag;
$this->render()
}
public function render() {};
}
class P extends Tag {
public function render() {
echo '<p class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</p>';
}
}
class Div extends Tag {
public function render() {
echo '<div class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</div>';
}
}
问题:
render
方法。答案 0 :(得分:1)
您可以使用new $var()
制作动态实例,然后移除您的开关。
foreach( $html as $tag ) {
$class = ucfirst($tag['type']);
$obj = new $class($tag); // will calls new P() or new Div()
//$obj->render();
}
完整代码:
class sampleHTML {
public function __construct() {
$html = [
[
'type' => 'p',
'class' => '.sample-class',
'content' => 'Sample content'
],
[
'type' => 'div',
'class' => '.sample-class-2',
'content' => 'Sample content 2'
],
];
foreach( $html as $tag ) {
$class = ucfirst($tag['type']);
new $class( $tag );
}
}
}
class Tag {
public $tag;
public function __construct( $tag = [] ) {
$this->tag = $tag;
$this->render();
}
public function render() {}
}
class P extends Tag {
public function render() {
echo '<p class="' . $this->tag['class'] . '">' . $this->tag['content'] . '</p>';
}
}
class Div extends Tag {
public function render() {
echo '<div class="' . $this->tag['class'] . '">' . $this->tag['content'] . '</div>';
}
}
new sampleHTML();
输出:
<p class=".sample-class">Sample content</p><div class=".sample-class-2">Sample content 2</div>
答案 1 :(得分:1)
首先,我要说为每种标签类型创建类是一种开销(直到它只是一个学习的程序)。
基本上,您可以使用某种模式,例如Factory或Strategy。
所以我会选择这样的东西:
interface TagInterface
{
public function render();
}
class TagFactory
{
public static function createTag($tag)
{
$class = ucfirst($tag['type']) . 'Tag';
return new $class($tag);
}
}
abstract class Tag implements TagInterface
{
protected $tag;
public function __construct(array $tag)
{
$this->tag = $tag;
}
}
class PTag extends Tag
{
public function render()
{
echo '<p class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</p>';
}
}
class DivTag extends Tag
{
public function render()
{
echo '<div class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</div>';
}
}
然后在你的代码中:
foreach($html as $tag ) {
/** @var TagInterface $tag */
$tag = TagFactory::createTag($tag);
$tag->render();
}
对于像您这样的任务,这是一个正确的架构。但是,我再说一遍,它只适合学习。在现实生活中,事情会简单得多,所以@Syscall的答案实际上应该是它的样子。
答案 2 :(得分:1)
是否可以在没有开关的情况下使用子类?
是的!你甚至可以在没有子类的情况下进行切换和 您已经将标记类型作为字符串,因此您可以使用它:
class Tag {
public $tag;
public function __construct( $tag = [] ) {
$this->tag = $tag;
$this->render();
}
private function render() {
echo '<'.$this->tag['type'].' class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</'.$this->tag['type'].'>';
}
}
这样,就不需要像Div extends Tag
这样的子类。
如何基于标签动态调用子类的render方法 类型?
虽然我的解决方案你不需要子类,但我也会回答这个问题 如果要从子类调用特定的渲染函数,请在该子类本身中定义/覆盖该函数
class Tag {
// constructor
// render
function render(){
// standard tag html
echo '<'.$this->tag['type'].' class"' . $this->tag['class'] . '">' . $this->tag['content'] . '</'.$this->tag['type'].'>';
}
}
class Table extends Tag {
// render (this overrides the render function of Tag)
function render(){
echo '<table class"' . $this->tag['class'] . '"><th><td>Column 1</td><td>Column 2</td><td>Column 3</td></th><tbody></tbody></table>';
}
}
class Div extends Tag {
// no render function here
// this way Div uses the render function of Tag
}
修改强>
如果您需要子类(因为某些标签以完全不同的方式构建)但您仍然拥有基本标签,例如p
od div
,您可以定义覆盖render()
- 仅适用于那些的人一个不同的HTML。如果它是带有标准html的标记,则可以省略该子类中的render()
函数,以便它将使用Tag类的render()
函数。我编辑了上面的代码来代表这个想法。