6

I'm working on a website for a band where you can add gigs and add the songs played on that specific gig.

So I've created two custom post types: - gig - song

I got a custom field "Songs" of type "Relationship". This field is shown on the Custom Post Type. This way I can add songs to a specific gig. This works perfectly.

But I want to show some statistics on the homepage of that website: I want to count how many times a specific song is played and show the top 10. So I guess that I have to loop over the gig custom post type and count the relation with 'songs'.

I thought this would do the trick:

<?php 
    $args = array(
        'post_type' => 'gig'
    ); 
?>

<?php $loop = new WP_Query($args); ?>

<?php if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post(); ?>

    <?php 
    print_r(get_field('songs'))
    //$song_count = count(get_field('songs')); 
    //echo $song_count . " ";

    the_title(); 

    ?><br />

<?php endwhile; ?>

<?php else: ?>
    <!-- No gigs available -->
<?php endif; ?>
<?php wp_reset_postdata(); ?>

You can find the result of the print_r over here: http://snippi.com/s/njzg3uu

For example: the song "A memory" is on 2 gigs. That why you can find it twice in the array. The song "Wasted" can be found only once, because it's on 1 gig.

Krupal Panchal
  • 1,553
  • 2
  • 13
  • 26
Dennis
  • 528
  • 3
  • 24
  • try to `var_dump(get_field('songs'))` and see what is actually in your field. – Stender Nov 12 '19 at 11:22
  • @Stender I get NULL as a result. – Dennis Nov 13 '19 at 11:25
  • Okay, I'm getting closer. I've changed the post type in the loop. I don't have to look over the songs, but over gigs. Because I have to check how many times a song was in a gig. You can check out my var_dump output over here: http://snippi.com/s/njzg3uu The song "A Memory" is in 2 gigs. So you see that this song is shown twice in the array. – Dennis Nov 13 '19 at 11:42
  • @Stender What I eventually want to achieve is a list of the 10 most played songs. – Dennis Nov 13 '19 at 15:16

4 Answers4

5

You can use this code to create an array of all the songs:

<?php 
    $args = array(
        'post_type' => 'gig'
    ); 

    $countArray = []; //create an array where you can put all the song id's and the number of times played
?>

<?php $loop = new WP_Query($args); ?>

<?php if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post(); ?>

    <?php
        $posts = get_field('songs');

        if( $posts ): 
                foreach( $posts as $post):
                    setup_postdata($post); 

                    //if the song id already exists -> count + 1
                    if (array_key_exists($post->ID, $countArray)){
                        $countArray[$post->ID]++;
                    }
                    else { // otherwise the song is played 1 time
                        $countArray[$post->ID] = 1;    
                    } 
                endforeach;

            wp_reset_postdata();
        endif;
    ?>

<?php endwhile; ?>

The code above will create an array of post ID's of songs and the number of times it is used in the post_type "gig".

Now you can use the array $countArray and do whatever you want with it. In your example you want to sort it, so you have to do arsort($countArray); This way the array is sorted by it's value (the number of times played) from high to low.

Then you have to loop through the array: foreach ($countArray as $key => $value) { ?>

<?php echo get_post_permalink($key); //=the permalink of the song ?>
<?php echo get_the_title($key); //= the title of the song ?>
<?php echo $value; //number of times play in a gig ?>

<?php  
}

So the full code is:

<?php 
    $args = array(
        'post_type' => 'gig'
    ); 

    $countArray = [];
?>

<?php $loop = new WP_Query($args); ?>

<?php if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post(); ?>

    <?php
        $posts = get_field('songs');

        if( $posts ): 
                foreach( $posts as $post):
                    setup_postdata($post); 

                    if (array_key_exists($post->ID, $countArray)){
                        $countArray[$post->ID]++;
                    }
                    else {
                        $countArray[$post->ID] = 1;    
                    } 
                endforeach;

            wp_reset_postdata();
        endif;
    ?>

<?php endwhile; ?>

<?php
    arsort($countArray);

    foreach ($countArray as $key => $value) {
    ?>

        <?php echo get_post_permalink($key); //=the permalink of the song ?>
        <?php echo get_the_title($key); //= the title of the song ?>
        <?php echo $value; //number of times play in a gig ?>

    <?php  
    }
?>

<?php else: ?>
    <!-- No gigs available -->
<?php endif; ?>
<?php wp_reset_postdata(); ?>
Dennis
  • 528
  • 3
  • 24
3

You Could do like this in simple and short way:

$args = array(
    'post_type' => 'gig'
); 
$gigs =  get_posts($args);
$songsarr = array();
foreach($gigs  as $gig) {
   $posts = get_field('songs', $gig->ID);
   array_push($songsarr,$posts[0]);
}
//echo "<pre>;
//print_r($songsarr);

$countsongs = array_count_values($songsarr);
echo 'No. of Duplicate Items: '.count($countsongs).'<br><br>';
// print_r($countsongs);

foreach($countsongs as $songID => $songname){
    echo get_the_title( $songID );
    echo $songname;
}

I have Tried by making Two Custom Post Type(gig, songs) and I got count numbers of song this way that you can show in home page and also you can give condition in last foreach loop if song more than one etc..

Hope this will help you!

Krishna Savani
  • 919
  • 4
  • 10
1

Hope help:

<?php 
    $args = array(
        'post_type' => 'song'
    ); 
?>

<?php $loop = new WP_Query($args); ?>

<?php if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post(); ?>

    <?php 
    $song_count = count(get_field('songs', get_the_ID())); <-- add 
    echo $song_count . " ";

    the_title(); 

    ?><br />

<?php endwhile; ?>

<?php else: ?>
    <!-- No gigs available -->
<?php endif; ?>
<?php wp_reset_postdata(); ?>
Dmitry Leiko
  • 3,970
  • 3
  • 25
  • 42
  • Hi Dmitry, it still give 0 as the result. I've also tried to echo "count: " . get_field('songs', get_the_ID()); but this prints nothing. – Dennis Nov 11 '19 at 17:28
  • No, you have to loop over the cpt 'gig' instead of songs. Because you have to check how many times songs are played in a gig. – Dennis Nov 13 '19 at 15:27
1

My understanding of your question is you are seeking to generate a top 10 list of songs that have the most associated gigs. The best way to approach this would be to generate a set that would map a unique identifier and a count value of how many times that songs has been seen.

Here is an example:

 <?php

// Get all the posts
$gigs = get_posts([
    'post_type' => 'gigs',
    'numberposts' => -1
]);

// We will use this array to key a running tally of
$set = [];

// If the key doesn't exist yet on the array, then we will initialize it, otherwise, increment the count
function add_set_element(&$set, $key) {
    if (!isset($set[$key])) {
        $set[$key] = 1;
    } else {
        $set[$key]++;
    }
}

function iterate_songs($songs, &$set){
    /** @var WP_Post $song */
    foreach($songs as $song) {
        $key = $song->post_title;// This can be what ever unique identifier you want to get from $song object, such as ID or title
        add_set_element($set, $key);
    }
}

foreach($gigs as $gig) {
    setup_postdata($gig);
    $songs = get_the_field('songs');
    iterate_songs($songs, $set);
}

Afterwards you can sort and manipulate the $set variable however you feel to get the data you want from it.

Let me know if I misinterpreted your questions, and I can provide another answer.

Nick Lediet
  • 151
  • 1
  • 4
  • That's correct: I want to show the top x list (for example top 10 list) of songs that more most played over the gigs. I've copied you code and did a var_dump($set) and this is the result array(0) { } – Dennis Nov 16 '19 at 12:02
  • I've changed the get_posts query post_type to "gig", because "gigs" isn't the post_type :-) But then I get an error on this row: $songs = get_the_field('songs'); Fatal error: Uncaught Error: Call to undefined function get_the_field() – Dennis Nov 16 '19 at 12:11
  • It's not `get_the_field()`. It should be `get_field()`. That's why you are getting a fatal error to an undefined function. – Jarom Nov 17 '19 at 07:32
  • @Jarom I've changed that to get_field, but I get an error on the foreach in the iterate_songs() function. Warning: Invalid argument supplied for foreach() – Dennis Nov 17 '19 at 13:53
  • That's good. You are one step closer now. That error you are getting now means your `$songs = get_field('songs')` line in the bottom foreach loop is not an array. It needs to be an array of your songs (your relationship). Try `echo '
    '.print_r($songs,1).'
    ';` underneath that line. This will tell you if you have any data, and in what format. If you do not have any data, then check the name of your relationship in the CMS. If you have data, then what does it look like? It might need to be formatted before passing to iterate_songs().
    – Jarom Nov 17 '19 at 18:10