I am using Gdata API to get Youtube video and comments. The reply is in XML which contains an array inside it.

For video ID and comments the XML response are different. For example I am getting array ID as video ID array and for one ID one or many comments in array.

Array of both video ID and comments is as follow:

foreach ($array as $entry) 
{
    $videoid = basename($entry);
    $video[] = $videoid;

    $logger->info('Response From Youtube:videoid=>' . $videoid);
}

$this->view->videoid = $video;

$author   = array();
$content  = array();
$arraycnt = array();

foreach ($video as $id)
{
    $comment = "http://gdata.youtube.com/feeds/api/videos/".$id."/comments";
    $sxml1   = simplexml_load_file($comment);
    $entries = $sxml1->entry;

    foreach ($entries as $a)
    {
        $author[]  = $a->author->name;
        $content[] = $a->content; 
    }
}

And the particular view as follow:

    <table>
   <tr>
            <td>
                <?php
                for($i=0;$i<$length;$i++)
                {
                ?> 
                <embed

                width="420" height="345"
                src="http://www.youtube.com/v/<?php echo $videoid[$i];?>"
                type="application/x-shockwave-flash">
            </embed>
            <?php
            }
            ?>
        </td>

        <td>
            <?php   
            foreach($content as $cont) 
            {
            ?>
            <p>Comment:<?php echo $cont;?></p>
            <?php 
            }
            ?>
        </td>
        <td>
            <?php   
            foreach($author as $auth) 
            {
            ?>
            <p>Commented By:<?php echo $auth;?></p>
            <?php 
            }
            ?>
        </td>
    </tr>
</table>

How can I show the video and comments in the view like:

videoA1 commentA1 commentA2

videoB1 commentB1 commentB2 commentB3

有帮助吗?

解决方案

You can keep the id of the video in $author and $content arrays.

foreach ($video as $id)
{
  foreach ($entries as $a)
  {
    $author[$id][]  = $a->author->name;
    $content[$id][] = $a->content; 
  }
}

So you can get comment's authors from specific video id:

foreach ($video as $id)
{
  echo $id;
  foreach($author[$id] as $auth) {
    echo ' ', $auth;
  }
}

The same goes with comment's content.

Of course you can extend this solution if you want to have just one array for comment's authors and content, but the logic stays the same.

其他提示

What you actually have here is that you first iterate over the videos and then per each video you iterate over the comments.

So you have a nested iteration: Level 1: Videos, Level 2: Comments.

As I commented earlier you can create a data-structure that is able to have data that can be iterated that way in a multi-dimensional array. Let's take two Youtube videos here in the following example:

  1. -FRm3VPhseI: The Clean Code Talks - "Global State and Singletons"
  2. RlfLCWKxHJ0: The Clean Code Talks - Don't Look For Things!

So if you would want to create a multi-dimenstional array over these two videos with all their comments, you could choose the following format:

$videos = array(
    '-FRm3VPhseI' => array(
        'id'       => '-FRm3VPhseI',
        'title'    => 'The Clean Code Talks - "Global State and Singletons"',
        'href'     => 'http://www.youtube.com/watch?v=-FRm3VPhseI&feature=youtube_gdata',
        'comments' => array(
            array(
                'author'  => 'Nelson ThePrimate',
                'content' => 'There is a cost for r...',
            ),
            array(
                'author'  => 'dennisdegreef',
                'content' => 'That is also a global...',
            ),
            array(
                'author'  => 'MorleyCode',
                'content' => 'State is unavoidable,...',
            ),

            // ...

            array(
                'author'  => 'Jacob Jensen',
                'content' => 'I don\'t quite underst...',
            ),
            array(
                'author'  => 'unity20000',
                'content' => 'Testing is not the on...',
            ),
            array(
                'author'  => 'drummist180',
                'content' => 'Turing machine > line...',
            ),
        ),
    ),
    'RlfLCWKxHJ0' => array(
        'id'       => 'RlfLCWKxHJ0',
        'title'    => 'The Clean Code Talks - Don\'t Look For Things!',
        'href'     => 'http://www.youtube.com/watch?v=RlfLCWKxHJ0&feature=youtube_gdata',
        'comments' =>
        array(
            array(
                'author'  => 'Nikolai Paul',
                'content' => 'this guy sometimes so...',
            ),
            array(
                'author'  => 'Madrid Softwaree',
                'content' => 'Learn Selenium , QTP ...',
            ),
            array(
                'author'  => 'Roger Keulen',
                'content' => 'Di: Great as a FXCop ...',
            ),

            // ...

            array(
                'author'  => 'michaeldeng1981',
                'content' => 'if I do outsourcing p...',
            ),
            array(
                'author'  => 'Rico Lelina',
                'content' => 'How about loggers? Is...',
            ),
            array(
                'author'  => 'twistedbydsign99',
                'content' => '11:55 it should defin...',
            ),
        ),
    ),
);

It first contains all videos keyed/indexed by the Youtube ID and then inside all the comments. To output this, you only have to nest two foreach clauses:

foreach ($videos as $videoId => $video)
{
    printf("%s: %s\n", $videoId, $video['title']);

    printf("  Comments (%d):\n", count($video['comments']));

    foreach ($video['comments'] as $i => $comment)
    {
        printf("    #%d %s: %s\n", $i + 1, $comment['author'], $comment['content']);
    }

    echo "\n";
}

Which will create the following output:

-FRm3VPhseI: The Clean Code Talks - "Global State and Singletons"
  Comments (6):
    #1 Nelson ThePrimate: There is a cost for r...
    #2 dennisdegreef: That is also a global...
    #3 MorleyCode: State is unavoidable,...
    #4 Jacob Jensen: I don't quite underst...
    #5 unity20000: Testing is not the on...
    #6 drummist180: Turing machine > line...

RlfLCWKxHJ0: The Clean Code Talks - Don't Look For Things!
  Comments (6):
    #1 Nikolai Paul: this guy sometimes so...
    #2 Madrid Softwaree: Learn Selenium , QTP ...
    #3 Roger Keulen: Di: Great as a FXCop ...
    #4 michaeldeng1981: if I do outsourcing p...
    #5 Rico Lelina: How about loggers? Is...
    #6 twistedbydsign99: 11:55 it should defin...

Note that in this output the number of comments are limited to 6 each time because I reduced the amount of comments for the example array. Now compare closely how the structure of the nested, multi-dimensional array is read from with the nested foreach clauses. The outer foreach is reading the video, the inner foreach is reading the comments.

This btw. is the same with building that array, it works as well with two nested iterations. To make this more simple I first create a caching variable and some helper functions:

$gdataFetchCache = [];

$gdataFetch = function ($url) use (&$gdataFetchCache)
{
    if (!isset($gdataFetchCache[$url]))
    {
        $gdataFetchCache[$url] = simplexml_load_file($url);
    }
    return $gdataFetchCache[$url];
};

$gdataNamed = function ($pattern) use ($gdataFetch)
{
    return function ($value) use ($pattern, $gdataFetch)
    {
        return $gdataFetch(sprintf($pattern, $value));
    };
};


$ytVideo    = $gdataNamed('http://gdata.youtube.com/feeds/api/videos/%s');
$ytComments = $gdataNamed('http://gdata.youtube.com/feeds/api/videos/%s/comments');

These functions allow to fetch Youtube data more easily inside the nested foreach-es:

$videoIds = ['-FRm3VPhseI', 'RlfLCWKxHJ0'];

$videos = [];

foreach ($videoIds as $videoId)
{
    $video = $ytVideo($videoId);

    $videoArray = [
        'id'       => (string)$videoId,
        'title'    => (string)$video->title,
        'href'     => (string)$video->link['href'],
        'comments' => [],
    ];

    $videos[$videoId] = $videoArray;

    foreach ($ytComments($videoId)->entry as $comment)
    {
        $videos[$videoId]['comments'][] = [
            'author'  => (string)$comment->author->name,
            'content' => (string)$comment->content,
        ];
    }
}

If you compare closely again, it has the same structure as the output code.

This is how you can read and create multi-dimensional arrays for which the count is not known in advance. By iterating you create the code for one element but use it as often as you have elements.

This also works nested.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top