简体   繁体   中英

Merging and ordering XML feeds with PHP - Very slow to load

Within wordpress and using ACF Pro, I'm merging multiple Songkick XML feeds with PHP, attaching an artist name to them (annoyingly each feed doesn't include the artist name), and ordering them by the event date.

I've managed to put this all together (with help from different questions on here) using separate steps, but the page is loading very slowly, so I wondered if there was a way of streamlining or merging some of the steps?

With the code below I am:

  • Fetching multiple XML feeds (sing an ACF fields from other pages on the site)

  • Attaching an artist name to each feed

  • Merging the feeds (whilst removing some of the data to try and speed up the processing time)

  • Outputting the information into a table while ordering by date

My code below:

<?php

$args = array(
    'post_type'      => 'page',
    'posts_per_page' => -1,
    'post_parent'    => 'artists'
 );


$parent = new WP_Query( $args );

if ( $parent->have_posts() ) : $artistFeedCount = 0; while ( $parent->have_posts() ) : $parent->the_post(); if( get_page_template_slug() == 'template-artist.php' && 'publish' === get_post_status()  ) { 
$singleArtistName = get_the_title();
$singleArtistSongkickRSS = 'https://api.songkick.com/api/3.0/artists/' . get_field('artist_songkick_id') . '/calendar.xml?apikey=XXXXXXXXXXXXXXXX';
$SongkickEvents[]=$singleArtistName;
$SongkickEvents[$singleArtistSongkickRSS] = $SongkickEvents[$artistFeedCount];
unset($SongkickEvents[$artistFeedCount]);
$artistFeedCount++;
?>
<?php }; endwhile; ?>
<?php endif; wp_reset_postdata(); ?>

<?php

$eventsDom = new DOMDocument();
$eventsDom->appendChild($eventsDom->createElement('events'));

foreach ($SongkickEvents as $artist_dates => $artist_name ) {
  $eventsAddDom = new DOMDocument();
  $eventsAddDom->load($artist_dates);

    $events = $eventsAddDom->getElementsByTagName('event');

  if ($eventsAddDom->documentElement) {
    foreach ($events as $event) {


      $eventsDom->documentElement->appendChild(
        $eventsDom->importNode($event, TRUE)
      );
      $artistName = $eventsDom->createElement('mainartist', $artist_name);
        foreach($eventsDom->getElementsByTagName('event') as $singleEvent) { 
        $singleEvent->appendChild($artistName);
        } 
        foreach($eventsDom->getElementsByTagName('performance') as $singlePerformance) {
            $singlePerformance->parentNode->removeChild($singlePerformance);
        }

  }
    }
}

$newXML = $eventsDom->saveXml();

$LiveDates = simplexml_load_string($newXML); 
$eventsArr=array();
foreach($LiveDates->event as $eventsArrSingle)
{
    $eventsArr[]=$eventsArrSingle;
}

usort($eventsArr,function($dstart,$dend){
    return strtotime($dstart->start['date'])-strtotime($dend->start['date']);
});
foreach($eventsArr as $eventsArrSingle) { ?>
    <div class="event-row <?php $eventStatus = $eventsArrSingle['status']; if($eventStatus == 'cancelled' || $eventStatus == 'postponed'): echo 'cancelled'; endif; ?>">
    <div class="event-block event-date">
        <span><?php $eventDate=$eventsArrSingle->start['date']; echo date("d", strtotime($eventDate)); ?></span>
        <?php echo date("M", strtotime($eventDate)); ?>
    </div>
    <div class="event-block event-info">
        <span><?php echo $eventsArrSingle->mainartist; ?></span>
        <?php if($eventsArrSingle->venue['displayName'] != 'Unknown venue'): echo $eventsArrSingle->venue['displayName'] . ', '; endif; ?><?php echo $eventsArrSingle->venue->metroArea['displayName']; ?>
    </div>
    <div class="event-block event-button">
    <a href="<?php echo $eventsArrSingle['uri']; ?>" target="_blank"><span><?php if($eventStatus == 'cancelled'): echo 'Cancelled'; elseif($eventStatus == 'postponed'): echo 'Postponed'; else: echo 'Tickets'; endif; ?></span> <i class="fas fa-arrow-right"></i></a>
    </div>

    </div>

<?php };?>

Any help would be greatly appreciated, I'm sure there's a way of merging everything in fewer steps!

For anyone coming across the same issue, this is the solution I used. Using the Transient API to store the feed for 3 hours at a time.

<?php
function eventsFunction() {

  // Do we have this information in our transients already?
  $eventTransient = get_transient( 'eventsTransientData' );

  // Yep!  Just return it and we're done.
  if( ! empty( $eventTransient ) ) {
   echo $eventTransient;

  } else {

$single_artist_ids = array(
    'post_type'      => 'page',
    'posts_per_page' => -1,
    'post_parent'    => 'artists'
 );


$parent = new WP_Query( $single_artist_ids );

if ( $parent->have_posts() ) : $artistFeedCount = 0; while ( $parent->have_posts() ) : $parent->the_post(); if( get_page_template_slug() == 'template-artist.php' && 'publish' === get_post_status()  ) { 
$singleArtistName = get_the_title();
$singleArtistSongkickRSS = 'https://api.songkick.com/api/3.0/artists/' . get_field('artist_songkick_id') . '/calendar.xml?apikey= XXXXXXXXXXXXXXXX';
$SongkickEvents[]=$singleArtistName;
$SongkickEvents[$singleArtistSongkickRSS] = $SongkickEvents[$artistFeedCount];
unset($SongkickEvents[$artistFeedCount]);
$artistFeedCount++;
?>
<?php }; endwhile; ?>
<?php endif; wp_reset_postdata(); ?>

<?php

$eventsDom = new DOMDocument();
$eventsDom->appendChild($eventsDom->createElement('events'));

foreach ($SongkickEvents as $artist_dates => $artist_name ) {
  $eventsAddDom = new DOMDocument();
  $eventsAddDom->load($artist_dates);

    $events = $eventsAddDom->getElementsByTagName('event');

  if ($eventsAddDom->documentElement) {
    foreach ($events as $event) {


      $eventsDom->documentElement->appendChild(
        $eventsDom->importNode($event, TRUE)
      );
      $artistName = $eventsDom->createElement('mainartist', $artist_name);
        foreach($eventsDom->getElementsByTagName('event') as $singleEvent) { 
        $singleEvent->appendChild($artistName);
        } 
        foreach($eventsDom->getElementsByTagName('performance') as $singlePerformance) {
            $singlePerformance->parentNode->removeChild($singlePerformance);
        }

  }
    }
}

$eventsXML = $eventsDom->saveXml();
$LiveDates = simplexml_load_string($eventsXML); 






$eventsArr=array();
foreach($LiveDates->event as $eventsArrSingle)
{
    $eventsArr[]=$eventsArrSingle;
}


usort($eventsArr,function($dstart,$dend){
    return strtotime($dstart->start['date'])-strtotime($dend->start['date']);
});

$eventsStored = '';
foreach($eventsArr as $eventsArrSingle) { 
    $eventsStored .= '<div class="event-row ';
    $eventStatus = $eventsArrSingle['status']; if($eventStatus == 'cancelled' || $eventStatus == 'postponed'): $eventsStored .= 'cancelled'; endif;
    $eventsStored .= '">
    <div class="event-block event-date">
        <span>';
    $eventDate=$eventsArrSingle->start['date']; $eventsStored .= date("d", strtotime($eventDate));
    $eventsStored .= '</span>';
    $eventsStored .= date("M", strtotime($eventDate));
    $eventsStored .= '</div>
    <div class="event-block event-info">
        <span>';
    $eventsStored .= $eventsArrSingle->mainartist;
    $eventsStored .= '</span>';
    if($eventsArrSingle->venue['displayName'] != 'Unknown venue'): $eventsStored .= $eventsArrSingle->venue['displayName'] . ', '; endif;
    $eventsStored .= $eventsArrSingle->venue->metroArea['displayName'];
    $eventsStored .= '</div>
    <div class="event-block event-button">
    <a href="' . $eventsArrSingle['uri'] . '" target="_blank"><span>';
    if($eventStatus == 'cancelled'): $eventsStored .= 'Cancelled'; elseif($eventStatus == 'postponed'): $eventsStored .= 'Postponed'; else: $eventsStored .= 'Tickets'; endif;
    $eventsStored .= '</span> <i class="fas fa-arrow-right"></i></a>
    </div>

    </div>';

};
      set_transient( 'eventsTransientData', $eventsStored, 3*HOUR_IN_SECONDS ); 
      echo $eventsStored;
  }

}

    eventsFunction();
?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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