문제

Let's say I have this:

class "classname"
{

    ....

    public function section($id)
    {
        // variable method name
        $this->section->$id = new stdClass();
        return $this;
    }

    public function subsection()
    {
        // $id is not available here
        $this->section->$id->subsection = array();
        return $this;
    }

    ....

}

When I call:

$classname->section("test")
    ->subsection();

It is not working because $id is not global nor set in the second chainlink. Do I have to pass it manually to ->subsection($id) or is there a more generic/cleaner way to get it there?

What I try to accomplish here is to create an (big) object with multiple sections. In these sections objects and/or array's so there are more (chained) methods involved.

도움이 되었습니까?

해결책

You can act like this way:

class Foo
{
    protected $section;
    private $lastUsedId = null;

    public function __construct()
    {
       $this->section = new StdClass();
    }

    public function section($id)
    {
        // variable method name
        $this->section->$id = new StdClass();
        $this->lastUsedId = $id;
        return $this;
    }

    public function subsection()
    {
        // $id is not available here
        $this->section->{$this->lastUsedId}->subsection = array();
        return $this;
    }
}

so

$obj = (new Foo())
   ->section('one')
   ->subsection()
   ->section('two')
   ->subsection();

will produce valid result like

object(Foo)#1 (2) {
  ["section":protected]=>
  object(stdClass)#2 (2) {
    ["one"]=>
    object(stdClass)#3 (1) {
      ["subsection"]=>
      array(0) {
      }
    }
    ["two"]=>
    object(stdClass)#4 (1) {
      ["subsection"]=>
      array(0) {
      }
    }
  }
  ["lastUsedId":"Foo":private]=>
  string(3) "two"
}

Note, that it isn't a good idea to use chaining like this way - it's difficult to read, and, besides, having method that actually changes data, but looks like getter, is confusing.

다른 팁

The problem you're facing is not because of chaining methods. It occurs either because you haven't declared the property $section or if you've declared it it has no property $id.

One possibility would be to define $section on the fly in the same way you're doing it with $id, i.e.

public function section($id) {
    $this->section = new stdClass();
    $this->section->id = new stdClass();
    return $this;
}

or

class Classname {
    private $section;

    public function __construct() {
        $this->section = new stdClass();
    }

    public function section($id) {
        $this->section->id = new stdClass();
        return $this;
    }
}

or

class Classname {

    private $section;

    public function __construct() {
        $this->section = new B();
    }

    public function section($id) {
        $this->section->id = new stdClass();
        return $this;
    }
}

class B {

    private $id;

}

Consider using 2 classes to accomplish what you want. Here is an example

class Document
{
    private $sections = array();

    public function addSection(Section $section)
    {
        $this->sections[] = $section;
    }

    public function getSections()
    {
        print_r($this->sections);
    }   
}

class Section {

    private $id;

    private $subsection;

    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    public function setSubsection()
    {
        $this->subsection = array();

        return $this;
    }   
}

$section1 = new Section;

$section1->setId(1)->setSubsection();

$section2 = new Section;

$section2->setId(2)->setSubsection();

$document = new Document;

$document->addSection($section1);

$document->addSection($section2);

$document->getSections();

will output

Array ( 

  [0] => Section Object ([id:protected] => 1 [subsection:protected] => Array( )) 

  [1] => Section Object ([id:protected] => 2 [subsection:protected] => Array( )))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top