简体   繁体   English

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

[英]Can't access object(stdClass) with twig

I have this object query out from mongodb 我有这个对象从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)
}

render by twig 由树枝渲染

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

I can access to Title, ID ... easily by doing {{ movie.Title }}, {{ movie.ID }} ... However when I use for loop to loop through movie.Episodes I can't seem to get anything out of it. 我可以通过执行{{movie.Title}},{{movie.ID}}来轻松访问Title,ID ...但是,当我使用for循环遍历movie.Episodes时,我似乎无法任何东西。

{{ dump(movie.Episodes) }}

return 返回

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

but

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

return empty and it doesn't even loop. 返回空,它甚至不会循环。 So, my question is how can I get the movie episode URL out using twig? 因此,我的问题是如何使用树枝获取电影剧集的URL?

Looks like Twig doesn't know how to handle StdClass, especially when nested. 看起来Twig不知道如何处理StdClass,尤其是在嵌套时。 I've had trouble with nested StdClass's before (using SoapClient). 我以前在嵌套StdClass上遇到过麻烦(使用SoapClient)。 I used the following function to convert the nested StdClass's to nested arrays, which are easier to handle and which Twig will understand ... 我使用以下函数将嵌套的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;
}

You'll need to call this on your data (StdClass) before passing it to and invoking Twig. 您需要在数据(StdClass)上调用它,然后再传递给Twig并调用它。

(Note this function calls itself recursively in the array_map in order to get all the nested StdClass's) (请注意,此函数在array_map中递归调用自身,以获取所有嵌套的StdClass。)

Whereas each object in PHP is "iterable", not all of them are "traversable" using for loop (see http://php.net/manual/en/class.traversable.php ). 尽管PHP中的每个对象都是“可迭代的”,但使用for循环并不是所有对象都是“可遍历的”(请参阅http://php.net/manual/en/class.traversable.php )。

An array is by definition traversable but not a stdClass object. 根据定义,数组是可遍历的,但不是stdClass对象。

var_dump(new stdClass() instanceof Traversable);

will produce: 将产生:

bool(false)

I could only suggest you to pass to TWIG a transformed $movie var where its Episodes key is an array and not an stdClass . 我只能建议您将一个经过转换的$movie var传递给TWIG,其中其Episodes键是array而不是stdClass This could be done with a function like the one above proposed by @BareNakedCoder 可以使用@BareNakedCoder提出的上述功能完成此操作

Or if you want to manipulate better your object for further features, it could be preferable to construct a new Movie class with this stdClass movie object passed in parameter in __construct() 或者,如果您想更好地操纵对象以获得更多功能,则最好使用此stdClass电影对象构造一个新的Movie类,该对象在__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;
    }
}

Your render line will be: 您的渲染线将为:

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

and here is the object you will have in your TWIG context: 这是您在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"
        }
    }
}

and no problem to loop the episodes 循环播放情节也没有问题

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

These new Movie / Episode classes are quite simple in this example but you could now add new functions to manipulate your data and theses methods will also be callable from you TWIG templates. 在此示例中,这些新的Movie / Episode类非常简单,但是您现在可以添加新函数来处理数据,并且这些方法也可以从TWIG模板中调用。

Before pass the data into the twig, try the following: 在将数据传递到树枝之前,请尝试以下操作:

$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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM