php动态HTML单元格意外生成

php动态HTML单元格意外生成,php,html,oop,Php,Html,Oop,我目前正在开发接口部分a框架,以生成HTML标记。我面临的问题是为嵌套表和单元格生成标记时。 为此,我有一个html类,它定义了标签的常见期望。另一个类是htmlTable,它继承自hrml类,并为table、TR、TD定制。虽然我想在特定单元格上添加嵌套表,但结果却出乎意料。它生成数百个TDs和TR 下面的代码是定制发布在这里的,因为放置所有的代码会导致冗长和混乱。 还有一件事,我只专注于解决逻辑错误,以获得HTML标记的确切父元素、子元素和嵌套元素 我已经尽了最大努力,但没能把这个修好。这对

我目前正在开发接口部分a框架,以生成HTML标记。我面临的问题是为嵌套表和单元格生成标记时。 为此,我有一个html类,它定义了标签的常见期望。另一个类是htmlTable,它继承自hrml类,并为table、TR、TD定制。虽然我想在特定单元格上添加嵌套表,但结果却出乎意料。它生成数百个TDs和TR

下面的代码是定制发布在这里的,因为放置所有的代码会导致冗长和混乱。 还有一件事,我只专注于解决逻辑错误,以获得HTML标记的确切父元素、子元素和嵌套元素

我已经尽了最大努力,但没能把这个修好。这对你们中的一些人来说可能很容易。所以请告诉我你的解决方案。我得去上班了,所以我一回来就会回复。 谢谢

<?php
// scHTML.php
class HTML
{
    protected $tag;
    protected $id;

    protected $values;
    protected $childList;

    protected $body;

    public function __construct($tag,$id)
    {
        $this->tag=$tag;
        $value= array('id'=>$id);
        $this->setValues($value);
    }

    // to add nested tag
    public function addChildTag(HTML $child)
    {
        $this->childList[]=$child;
    }

    // to add key and value on opening tag
    public function setValues($values)
    {
        if(count($values)>0)
        {
            foreach($values as $key=>$value)
            {
                $this->values[$key]=$values;
            }
        }
    }

    // value inside tag
    public function setBody($body)
    {
        $this->body=$body;
    }

    // generate HTML code
    public function getHTML()
    {
        $return= '<'.$this->tag;
        if(count($this->values)>0)
        {
            foreach($this->values as $key=>$value)
            {
                $return.=' '.$key.'= "'.$value.'" ';
            }
        }
        $return.= '> 
        ';
        if(count($this->childList)>0)
        {
            $return.=
                            $this->body
                            ;
            foreach($this->childList as $child)
            {
                $return.=
                                $child->getHTML();
            }
        }
        $return.=' </'.$this->tag.'>';
        return $return;
    }

    public function __toString()
    {
        return $this->getHTML();
    }   
}
?>

下面是表的继承类

<?php
//scHTMLTable.php
include_once("scHTML.php");
class HTMLTable extends HTML
{
    protected $cells; // logical grid of cells for current table
    protected $row;
    protected $column;

    public function __construct($row,$column,$id)
    {
        $this->row=$row;
        $this->column=$column;
        $this->initiateTable();
        $values['border']='1px';
        $this->setValues($values);

        parent::__construct("table",$id);

    }

    // initaite table cells according to row and column provided
    private function initiateTable()
    {
        $td=new HTML("td",NULL);
        $td->setBody('&nbsp;');
        for($i=1;$i<=$this->row;$i++)
        {
            for($j=1;$j<=$this->column;$j++)
            {
                $this->addCell($i,$j,$td);
            }
        }
    }

    // set child element as body on a cell
    public function addChildOnCell($row,$column,HTML $child)
    {
        $td=$this->cells[$row][$column];
        $td->addChildTag($child);
        $this->addCell($row,$column,$child);
    }

    // set cell 
    public function addCell($row,$column,HTML $cell)
    {
        $this->cells[$row][$column]=$cell;
    }

    // set TR as child and call parent method to generate html code.
    public function getHTML()
    {
        for($i=1;$i<=$this->row;$i++)
        {
            $tr=new HTML("tr",NULL);
            for($j=1;$j<=$this->column;$j++)
            {
                $td=$this->cells[$i][$j];
                $tr->addChildTag($td);
            }
            $this->addChildTag($tr);
        }
        return parent::getHTML();
    }

    public function __toString()
    {
        return $this->getHTML();
    }
}

?>

这里是实现

<?php
include_once("scHTML.php");
include_once("scHTMLTable.php");


$html= new HTML("html",NULL); 
$body=new HTML("body",NULL); 

// three table to be tested
$a= new HTMLTable(3,3,"grandparent");
$b=new HTMLTable(3,3,"parent");
$c=new HTMLTable(1,1,"child");

$b->addChildOnCell(2,2,$c);
$a->addChildOnCell(2,2,$b);

$body->addChildTag($a);
$html->addChildTag($body);

echo $html;  
?>

我正在寻找的输出源代码就在这附近

<html>


<body>
<table border="1">
 <tr>
  <td>&nbsp;</td>
  <td>&nbsp;</td>
  <td>&nbsp;</td>
 </tr>
 <tr>
  <td>&nbsp;</td>
  <td><table border="1">
   <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
   </tr>
   <tr>
    <td>&nbsp;</td>
    <td><table border="1">
     <tr>
      <td>&nbsp;</td>
     </tr>
    </table></td>
    <td>&nbsp;</td>
   </tr>
   <tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
   </tr>
  </table></td>
  <td>&nbsp;</td>
 </tr>
 <tr>
  <td>&nbsp;</td>
  <td>&nbsp;</td>
  <td>&nbsp;</td>
 </tr>
</table>
</body>
</html>

现在是2015年,你不应该手动包含文件;有明确的编码标准,所以您应该有名称空间,并在主应用程序中注册自动加载程序

此外,只要您打算以这种方式进行字符串构建,在表示表的对象上使用_-toString()方法,您就应该为嵌套部分提供其他类,每个类都有自己的_-toString方法;所以您可以拥有HtmleElement类(您已经拥有)、table(您已经拥有,但它并不理想)、table行、table单元格

扩展它,如果您采取这条路线,您应该扩展所有HtmleElement,并为您想要以鹦鹉学舌的方式完成事情的时候提供一个rawString HtmleElement扩展类

  • 表row uu-toString方法只需迭代包含的单元格并返回它们的u-toString方法
  • 表将对行进行迭代,并调用它们的_toString方法
  • table cell(最难/最不难的部分)将获取实现HtmleElement的实例,并通过调用其_toString方法对其进行迭代
这是一种比当前更干净的工作方法,当每种方法都输出自己的DOM时,您应该不会有现在的讨厌的bug


如果表变得太大,您会希望您刚刚编写了一系列视图,这些视图使用一个级别的XYdata,或者以另一种方式简化;但是这种嵌套视图的数据结构,除非您正在使用JSON或XML(对于XML,只需使用XSL);从SQL Server、MySQL、search On中检索,或者真的用…做那么多有用的事情,都不是件好事。

我同意mrmeses的观点,我认为您的表类做得太多了,每个节点类型只负责生成自己的DOM表示。但是,任何到字符串/到html的递归应该只在DOM中向下移动(不需要调用父级以获得渲染帮助)。下面是一个使用一些自定义API方法名称的快速演示:

  class HTML
  {
    private $tagName;
    protected $attributes = [];
    protected $children = [];
    private $text = '';

    public function __construct($tagName, $text='') {
      $this->tagName = strtolower($tagName);
      $this->text = $text;
    }

    public function addChildTag(HTML $n) {    
      $this->children[] = $n;
      return $this;
    }

    public function getHTML($depth=0) {
      $padding = str_repeat("\t", $depth);
      $result = "$padding<$this->tagName";
      foreach($this->attributes as $k => $v) {
        $result .= " $k=\"".htmlspecialchars($v)."\"";
      }
      if (count($this->children) == 0 && strlen($this->text) == 0) {
        $result .= " />\n";
      }      
      else {
        $result .= ">";
        $result .= $this->text;
        if (count($this->children) > 0) $result .= "\n";
        foreach($this->children as $c) {
          $result .= $c->getHTML($depth+1);
        }
        $result .= "$padding</$this->tagName>\n";
      }
      return $result;
    }

    public function tagName() { return $this->tagName; }

    public function findChild($tagName, $index=0) {
      $nodes = array_filter($this->children, function($e) use ($tagName) {  return $e->tagName() == $tagName;  });
      return count($nodes) ? $nodes[$index] : null;
    }

    public function __toString() { return $this->getHTML(); }
  }

  class HTMLTable extends HTML {
    public function __construct($rows, $cols, $id) {
      parent::__construct("table");
      $this->attributes['id'] = $id;
      $this->attributes['border'] = '1px';
      for($r=0; $r<$rows; $r++) {
        $row = new HTML("tr");
        for($c=0; $c<$cols; $c++) {
          $cell = new HTML("td");
          $row->addChildTag($cell);
        }
        $this->addChildTag($row);
      }
    }

    public function addChildOnCell($row, $col, HTML $child) {
      return $this->findChild("tr", $row-1)->findChild("td", $col-1)->addChildTag($child);
    }
  }

  $html= new HTML("html"); 
  $body=new HTML("body"); 

  // three table to be tested
  $a= new HTMLTable(3,3,"grandparent");
  $b=new HTMLTable(3,3,"parent");
  $c=new HTMLTable(1,1,"child");

  $b->addChildOnCell(2,2,$c);
  $a->addChildOnCell(2,2,$b);

  $body->addChildTag($a);
  $html->addChildTag($body);

  echo $html;
类HTML
{
私有$标记名;
受保护的$attributes=[];
受保护的$children=[];
私人$text='';
公共函数构造($tagName,$text=''){
$this->tagName=strtolower($tagName);
$this->text=$text;
}
公共函数addChildTag(HTML$n){
$this->children[]=$n;
退还$this;
}
公共函数getHTML($depth=0){
$padding=str_repeat(“\t”,$depth);
$result=“$paddingtagName”;
foreach($此->属性为$k=>$v){
$result.=“$k=\”.htmlspecialchars($v)。“\”;
}
如果(计数($this->children)==0&&strlen($this->text)==0){
$result.=“/>\n”;
}      
否则{
$result.=“>”;
$result.=$this->text;
如果(计数($this->children)>0)$result.=“\n”;
foreach($this->children as$c){
$result.=$c->getHTML($depth+1);
}
$result.=“$paddingtagName>\n”;
}
返回$result;
}
公共函数标记名(){return$this->tagName;}
公共函数findChild($tagName,$index=0){
$nodes=array_filter($this->children,function($e)use($tagName){return$e->tagName()=$tagName;});
返回计数($nodes)$nodes[$index]:null;
}
公共函数_toString(){return$this->getHTML();}
}
类HTMLTable扩展了HTML{
公共函数构造($rows、$cols、$id){
父项::_构造(“表”);
$this->attributes['id']=$id;
$this->attributes['border']='1px';
对于($r=0;$raddChildTag($row));
}
}
公共函数addChildOnCell($row,$col,HTML$child){
返回$this->findChild($tr',$row-1)->findChild($td',$col-1)->addChildTag($child);
}
}
$html=新html(“html”);
$body=新HTML(“body”);
//需要测试的三个表
$a=新HTMLTable(3,3,“祖父母”);
$b=新HTMLTable(3,3,“父项”);
$c=新HTMLTable(1,1,“子”);
$b->addChildOnCell(2,2,$c);
$a->addChildOnCell(2,2$b);
$body->addChildTag($a);
$html->addChildTag($body);
echo$html;
这将导致输出:

<html>
    <body>
        <table id="grandparent" border="1px">
            <tr>
                <td />
                <td />
                <td />
            </tr>
            <tr>
                <td />
                <td>
                    <table id="parent" border="1px">
                        <tr>
                            <td />
                            <td />
                            <td />
                        </tr>
                        <tr>
                            <td />
                            <td>
                                <table id="child" border="1px">
                                    <tr>
                                        <td />
                                    </tr>
                                </table>
                            </td>
                            <td />
                        </tr>
                        <tr>
                            <td />
                            <td />
                            <td />
                        </tr>
                    </table>
                </td>
                <td />
            </tr>
            <tr>
                <td />
                <td />
                <td />
            </tr>
        </table>
    </body>
</html>