无法使用树枝访问对象(stdClass)

时间:2015-12-14 22:23:49

标签: php arrays mongodb object twig

我有这个对象从mongodb查询

object(stdClass)#22 (9) {
  ["_id"]=>
  object(MongoDB\BSON\ObjectID)#19 (1) {
    ["oid"]=>
    string(24) "56639b2aa18994f5398b4567"
  }
  ["Title"]=>
  string(76) "Example movie ..."
  ["ID"]=>
  string(10) "abc12345"
  ["Code"]=>
  string(8) "123456"
  ["Released"]=>
  string(10) "2015-11-27"
  ["Length"]=>
  string(10) "300 min(s)"
  ["Poster"]=>
  string(64) "http://example.net/84orea005pl.jpg"
  ["Episodes"]=>
  object(stdClass)#21 (1) {
    [1]=>
    object(stdClass)#20 (1) {
      ["URL"]=>
      string(38) "http://example.net/movie.e1.m3u8"
    }
  }
  ["View"]=>
  int(31)
}

通过树枝渲染

twig->render('movie.html',array('movie' => $movie));

我可以通过{{movie.Title}},{{movie.ID}}轻松访问标题,ID ... 然而,当我使用for循环遍历movie.Episodes时,我似乎无法从中获取任何东西。

{{ dump(movie.Episodes) }}

返回

object(stdClass)#21 (1) {
  [1]=>
  object(stdClass)#20 (1) {
    ["URL"]=>
    string(38) "http://example.net/movie.e1.m3u8"
  }
}

{% for episode in movie.Episodes %}
testing
{{ dump(episode) }}
{% endfor %}

返回空,它甚至不循环。 所以,我的问题是如何使用twig获取电影剧集的URL?

3 个答案:

答案 0 :(得分:0)

看起来Twig不知道如何处理StdClass,尤其是在嵌套时。我之前遇到过嵌套StdClass的问题(使用SoapClient)。我使用以下函数将嵌套的StdClass转换为嵌套数组,这些数组更容易处理,Twig会理解......

function objectToArray($data) {
    if (is_object($data))
        $data = get_object_vars($data);
    if (is_array($data))
        return array_map(__FUNCTION__, $data);
    return $data;
}

在将数据传递给Twig之前,您需要在数据(StdClass)上调用它。

(注意这个函数在array_map中递归调用自己以获得所有嵌套的StdClass)

答案 1 :(得分:0)

虽然PHP中的每个对象都是“可迭代的”,但并非所有对象都使用for循环“遍历”(参见http://php.net/manual/en/class.traversable.php)。

根据定义,数组是可遍历的,但不是stdClass对象。

var_dump(new stdClass() instanceof Traversable);

将产生:

bool(false)

我只能建议您将已转换的$movie var传递给TWIG,其Episodes密钥为array而不是stdClass。 这可以通过@BareNakedCoder

提出的功能完成

或者,如果您想更好地操作对象以获得更多功能,最好使用Movie中的参数传递的stdClass电影对象构建一个新的__construct()

class Movie
{
    public $id;
    public $oid;
    public $code;
    public $title;
    public $released;
    public $length;
    public $poster;
    public $views;

    /** @var Episode[] $episodes  */
    protected $episodes = [];

    function __construct(stdClass $object = null)
    {
        if (!is_null($object)) {
            $this->oid = $object->_id->oid;

            $this->id = $object->ID;
            $this->code = $object->Code;
            $this->title = $object->Title;
            $this->released = $object->Released;
            $this->length = $object->Length;
            $this->poster = $object->Poster;
            $this->views = $object->View;

            foreach(get_object_vars($object->Episodes) as $ep)
                $this->episodes[] = new Episode($ep);
        }
    }

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

class Episode
{
    public $url;

    function __construct(stdClass $object = null)
    {
        if (!is_null($object))
            $this->url = $object->URL;
    }
}

您的渲染线将是:

twig->render('movie.html', ['movie' => new Movie($movie)]);

以下是您在TWIG环境中的对象:

object(Movie)#5 (9) {
    ["id"]=>
    string(8) "abc12345"
    ["oid"]=>
    string(24) "56639b2aa18994f5398b4567"
    ["code"]=>
    string(6) "123456"
    ["title"]=>
    string(17) "Example movie ..."
    ["released"]=>
    string(10) "2015-11-27"
    ["length"]=>
    string(10) "300 min(s)"
    ["poster"]=>
    string(34) "http://example.net/84orea005pl.jpg"
    ["views"]=>
    int(31)
    ["episodes":protected]=>
    array(1) {
        [0]=>
        object(Episode)#6 (1) {
            ["url"]=>
            string(32) "http://example.net/movie.e1.m3u8"
        }
    }
}

循环剧集没问题

{% for episode in movie.getEpisodes() %}
  <br>{{ episode.url }}
{% endfor %}

这个新的Movie / Episode类在此示例中非常简单,但您现在可以添加新函数来操作数据,这些方法也可以从TWIG模板中调用。

答案 2 :(得分:0)

在将数据传递到树枝之前,请尝试以下操作:

$data_to_twig = json_encode($your_data);

$data_to_twig = json decode($data_to_twig, true); // the parameter "true" will convert all child objects including stdClass objects to array