具有受保护数组属性的php继承让我非常头疼


php inheritance with protected array property is giving me a serious headache

所以我决定在PHP中创建一些类,这样我就可以使用<ul>,<li>和<a> 标签。原因是我想在项目中重用它。

首先是代码块,注意我在代码中添加了一些调试信息,因为我实际上是一个。NET开发人员和我还不知道如何体面地调试:s

<?php
// Menu Items <li><a href='"$target'">$itemName</a></li>
class MenuItem {
    public $order;
    public $target;
    public $itemName;
function __construct($itemName="", $target="", $order=0) {
    $this->order = $order;
    $this->target = $target;
    $this->itemName = $itemName;
}
public function Build() {
    //if $target is empty or $itemName is empty then return empty string (both must be present to generate an item)
    if(strcasecmp($target,"") == 0 || strcasecmp($itemName,"") == 0) { 
        return "";
    }
    return "<li><a href='"" . $target . "'">" . $itemName . "</a></li>";
}
}
//<li><a>$FirstMenuItem</i>
// Submenu Root Head Item: <li><a href='"$(optional)Target'">$ItemName</a><ul>
// Holds a list of MenuItems and SubmenuRootItems
// Submenu Root End Item: </ul>
class SubMenu extends MenuItem {
    protected $itemArray;
    function __construct($itemName = "", $target = "", $order = 0) {
        parent::__construct($itemName, $target, $order);
        $this->itemArray = array();
    }
    public function Items() {
        return $this->itemArray;
    }
    public function AddSubMenuItem ($subMenuItem) {
        $retval = strcasecmp( get_class ($subMenuItem), "submenu") == 0 ? self::AddItem($subMenuItem) : false;
       echo"<br>second dump<br>";
        var_dump($this->itemArray); echo "<br>";
        return $retval;
    }
    public function AddMenuItem ($menuItem) {
        $retval =  strcasecmp( get_class ($menuItem), "menuitem") == 0 ? self::AddItem($menuItem) : false;
        echo"<br>second dump<br>"; //debug code
        var_dump($this->itemArray); echo "<br>"; //debug code
        return $retval;
    }
    protected function AddItem($item) {
        $itemArray[$item->itemName] = $item;
        echo "AddItem <br />"; //ugly debug code
        var_dump($itemArray); //even more of it
        return true;
    }
    public function Build() {
        $buildHtml = "<li>";
        $buildHtml .= strcasecmp($target, "") == 0 ?  "<a>" : "<a href='"" . $target . "'">";
        $buildHtml .= $itemName . "</a><ul>";
        $buildHtml .= BuildSubMenu(Items());
        $buildHtml .= "</ul></li>";
    }
    public function BuildSubMenu($menuItems) {
        $buildHtml = "";
        echo "for each start". var_dump($menuItems) ;
        foreach($menuItems as $menuItem) {
            echo $menuItem;
            $buildHtml .= $menuItem->Build();
        }
        return $buildHtml;
    }
}
// Menu Root Element <ul id='"menu'">
// holds a list of MenuItems and SubmenuRootItems
// Menu Root Closing Element </ul>
class MenuBuilder extends SubMenu {
    function __construct() {
        parent::__construct(); 
    }
    public function Build() {  echo "<br><br><br>". var_dump($this->itemArray); echo "<br><br><br>".var_dump(parent::$this->itemArray);echo "<br><br><br>";//ugly debug code
        $buildHtml = "<ul id='"menu'">";
        $buildHtml .= parent::BuildSubMenu($this->itemArray);
        $buildHtml .= "</ul>";
        return $buildHtml;
    }
}
?>

问题是整个事情都不起作用,php显然不起作用。NET,但我真的不知道以下怎么可能是真的。为了测试,我制作了这个小php页面,它对我的新类进行了一些调用。

Write("Create menuBuilder...");
$menuBuilder = new MenuBuilder();
WriteLine("Done!");
Write("Create subMenu1...");
$subMenu1 = new SubMenu("Sub Menu 1");
WriteLine("Done!");
Write("Execute subMenu1->AddMenuItem...");
$subMenu1->AddMenuItem(new MenuItem("Menu Item 1.1", "#1.1"));
WriteLine("Done!");
Write("Create menuItem2...");
$menuItem2 = new MenuItem("Menu Item 2","#2");
WriteLine("Done!");
Write("Execute menuBuilder->AddSubMenuItem...");
$menuBuilder->AddSubMenuItem($subMenu1);
WriteLine("Done!");
Write("Execute menuBuilder->AddMenuItem...");
$menuBuilder->AddMenuItem($menuItem2);
WriteLine("Done!");

然后在$subMenu和$menuBuilder 上都有Items属性的转储

这些调用在我的浏览器中的输出让我完全困惑:

Create menuBuilder...Done!
Create subMenu1...Done!
Execute subMenu1->AddMenuItem...AddItem 
array(1) { ["Menu Item 1.1"]=> object(MenuItem)#4 (3) { ["order"]=> int(0) ["target"]=>    string(4) "#1.1" ["itemName"]=> string(13) "Menu Item 1.1" } } 
second dump
array(0) { } 
Done!
Create menuItem2...Done!
Execute menuBuilder->AddSubMenuItem...AddItem 
array(1) { ["Sub Menu 1"]=> object(SubMenu)#3 (4) { ["itemArray":protected]=> array(0) { } ["order"]=> int(0) ["target"]=> string(0) "" ["itemName"]=> string(10) "Sub Menu 1" } } 
second dump
array(0) { } 
Done!
Execute menuBuilder->AddMenuItem...AddItem 
array(1) { ["Menu Item 2"]=> object(MenuItem)#4 (3) { ["order"]=> int(0) ["target"]=> string(2) "#2" ["itemName"]=> string(11) "Menu Item 2" } } 
second dump
array(0) { } 
Done!

因此AddItem函数起作用,一个项被添加到$itemArray中,并成功转储。然后,当函数返回到它的调用方"AddMenuItem",并且我再次转储相同的$itemArray时,它是空的?我真的不明白这是怎么回事:s

也许您不会更改AddItem方法中的class itemArray属性?

你有这个:

protected function AddItem($item) {
    $itemArray[$item->itemName] = $item;
    echo "AddItem <br />"; //ugly debug code
    var_dump($itemArray); //even more of it
    return true;
}

试试这个:

protected function AddItem($item) {
    // $this will change the class property :)
    $this->itemArray[$item->itemName] = $item;
    echo "AddItem <br />"; //ugly debug code
    var_dump($this->itemArray); //even more of it
    return true;
}

你不会在很多地方使用$this,比如在MenuItem->Build方法中:

class MenuItem {
    public $order;
    public $target;
    public $itemName;
function __construct($itemName="", $target="", $order=0) {
    $this->order = $order;
    $this->target = $target;
    $this->itemName = $itemName;
}
public function Build() {
    // The $target and $itemName variables aren't inicialized
    //if $this->target is empty or $this->itemName is empty then return empty string (both must be present to generate an item)
    if(strcasecmp($this->target,"") == 0 || strcasecmp($this->itemName,"") == 0) { 
        return "";
    }
    return "<li><a href='"" . $this->target . "'">" . $this->itemName . "</a></li>";
}
}