无法从子对象访问父变量

时间:2016-08-19 18:49:54

标签: php oop

我试图找出控制器类无法访问其扩展的父级属性的原因。

使用$ this检索送货方法不输出任何内容。 Var_dump表示它是一个字符串长度为0的数组。

使用parent ::返回错误"未定义的类常量' shipinfo'"

对我做错了什么的任何想法?我认为在扩展父类时可以访问公共/受保护的变量吗?

$data = trim(file_get_contents('php://input'));  
$link = new OrderLink($data);
$controller = new OrderLinkController();

class OrderLink{

protected $shipinfo = [
'name'      => '',
'address'   => '',
'unit'      => '',
'city'      => '',
'state'     => '',
'country'   => '',
'zip'       => '',
'phone'     => '',
'email'     => '',
'method'    => ''
];

protected $items;

function __construct($postdata)
{
    $xml = simplexml_load_string($postdata);

    $xml = $xml->Order;

    $billinfo = $xml->AddressInfo[1];
    $this->shipinfo['name']     =  strval($billinfo->Name->Full);
    $this->shipinfo['address']  =  strval($billinfo->Address1);
    $this->shipinfo['unit']     =  strval($billinfo->Address2);
    $this->shipinfo['city']     =  strval($billinfo->City);
    $this->shipinfo['state']    =  strval($billinfo->State);
    $this->shipinfo['country']  =  strval($billinfo->Country);
    $this->shipinfo['zip']      =  strval($billinfo->Zip);

  }
}

class OrderLinkController extends OrderLink
{

    function __construct(){

        echo 'Shipping Method: ' . $this->shipinfo['method'];
        echo parent::shipinfo['method'];

        if ($this->shipinfo['method']    == 'Local Pickup'){
            $this->shipinfo['method']    = 'Pickup';

        }
    }
}

2 个答案:

答案 0 :(得分:4)

一些小问题:

  • 您需要调用父构造函数,因此您应该通过子项将所需的$ postdata传递给父项(或在子构造函数中创建它)
  • 您可以使用$ this->对于shipinfo

    class OrderLinkController extends OrderLink
    {
    
        function __construct($postdata){
    
            parent::__construct($postdata);
    
            echo 'Shipping Method: ' . $this->shipinfo['method'];
            echo $this->shipinfo['method'];
    
            if ($this->shipinfo['method']    == 'Local Pickup'){
               $this->shipinfo['method']    = 'Pickup';
    
            }
        }
    }
    

进一步说明:您不需要像在前几行中那样实例化父对象和子对象:

$link = new OrderLink($data);
$controller = new OrderLinkController();

你应该只实例化子进程,通过child的构造函数发送数据,一旦child的构造函数与父进程匹配,允许数据流动(参见我上面提供的代码,了解其工作原理):

$controller = new OrderLinkController($data);

答案 1 :(得分:1)

我还想补充一下Katie的答案,除了代码本身的问题,类结构也存在问题。

您拥有的类是Web应用程序的典型类,OrderLinkController是一个负责传入请求处理的类 - 获取输入数据,验证它并将执行传递给业务逻辑对象Model。 / p>

在这种情况下,OrderLink是模型,它与控制器之间不应存在父子关系。他们应该保持独立,我会开始以这种方式修改代码:

// it may extend some BaseController class, but not the model class
class OrderLinkController 
{

    function run() {
        // get and parse the input data
        $data = trim(file_get_contents('php://input'));  
        $xml = simplexml_load_string($data);
        $xml = $xml->Order;
        // validate the data
        if ($xml->method == 'Local Pickup'){
            $xml->method = 'Pickup';
        }
        // pass the data to the model
        $model = new OrderLink($xml);
        // save the data or do something else with it
        $model->save(); 

        echo $model->getShippingInfo();
    }
}


class OrderLink{

    // it is usually better to have explicitly defined fields
    // rather than an array
    protected $name;
    protected $address;
    protected $unit;
    protected $city;
    protected $state;
    protected $country;
    protected $zip;
    protected $phone;
    protected $email;
    protected $items;

    // model gets already parsed data
    function __construct($data)
    {
        $billinfo = $data->AddressInfo[1];
        $this->shipinfo['name']     =  strval($billinfo->Name->Full);
        $this->shipinfo['address']  =  strval($billinfo->Address1);
        $this->shipinfo['unit']     =  strval($billinfo->Address2);
        $this->shipinfo['city']     =  strval($billinfo->City);
        $this->shipinfo['state']    =  strval($billinfo->State);
        $this->shipinfo['country']  =  strval($billinfo->Country);
        $this->shipinfo['zip']      =  strval($billinfo->Zip);
    }

    public function getShippingInfo() {
        return 'Shipping Method: ' . $this->method;
    }
}

// create and run the controller
$controller = new OrderLinkController();
$controller->run();