1

I understand how to use get_post_metadata(), however this code in a custom RSS feed template:

while( have_posts()) : the_post();

    // Has a custom URL been supplied? Use that in preference.
    $feature_permalink = ‌‌get_post_meta(get_the_ID(), '_featureurl', true);

    [...]

is giving:

HP Fatal error: Uncaught Error: Call to undefined function ‌‌get_post_meta() in /srv/www/foo/htdocs/wp-content/themes/bar/feed-feature.php

(and indeed the PhpStorm editor highlights it accordingly, but with an xdebug breakpoint set, I can run it fine in the debug console. All the other various feed function calls - for the standard permalink, title, guid etc. - work fine.)

The template is in functions.php, called with:

function foo_custom_rss() {
    if ( in_array('feature', get_query_var('post_type')) ) {
        get_template_part( 'feed', 'feature' );
    } else {
        get_template_part( 'feed', 'rss2' );
    }
}

remove_all_actions( 'do_feed_rss2' );
add_action( 'do_feed_rss2', 'foo_custom_rss', 10, 1 );
  • What specifically are you trying to add/modify on the feature post type's RSS2 feed? – Dave Romsey Mar 4 '18 at 6:40
1

To modify an RSS item's <link> node value, use the the_permalink_rss filter. This is demonstrated in the code below where if a feature post has a value set for _featureurl, we will return the custom value. Otherwise, the default permalink is returned:

/**
 * Filters the permalink to the post for use in feeds.
 *
 * @param string $post_permalink The current post permalink.
 */
add_filter( 'the_permalink_rss', 'wpse_the_permalink_rss', 10, 1 );
function wpse_the_permalink_rss( $post_permalink ) {
    // Bail if this is not a feature.
    if ( 'feature' !== get_query_var( 'post_type') ) {
        return $post_permalink;
    }

    // Get the permalink URL.
    $feature_permalink = get_post_meta( 
            get_the_ID(),
            '_featureurl',
            true 
    );

    // If the the custom URL has been specified return it, otherwise, use default permalink.
    // Note: This is run through esc_url() via the_permalink_rss().
    if ( $feature_permalink  ) {
        return $feature_permalink; 
    } else {
        return $post_permalink;     
    }
}

Example RSS output for the feature post type, which has the following URL:

http://example.com/feed/?post_type=feature

Note that the <link> node under the <item> node contains the URL https://google.com, which is what I set for the _featureurl custom field:

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    >

<channel>
    <title>Features &#8211; WP Theme Testing</title>
    <atom:link href="http://localhost/wp-theme-testing/feed/?post_type=feature" rel="self" type="application/rss+xml" />
    <link>http://localhost/wp-theme-testing</link>
    <description>I &#60;3 testing themes!</description>
    <lastBuildDate>Sun, 04 Mar 2018 05:46:16 +0000</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <generator>https://wordpress.org/?v=4.9.1</generator>

<image>
    <url>http://localhost/wp-theme-testing/wp-content/uploads/2017/06/cropped-favicon-32x32.png</url>
    <title>Features &#8211; WP Theme Testing</title>
    <link>http://localhost/wp-theme-testing</link>
    <width>32</width>
    <height>32</height>
</image> 
    <item>
        <title>test feature</title>
        <link>https://google.com</link>


        <comments>http://localhost/wp-theme-testing/feartures/test-feature/#respond</comments>
        <pubDate>Sun, 04 Mar 2018 05:41:29 +0000</pubDate>
        <dc:creator><![CDATA[dave]]></dc:creator>

        <guid isPermaLink="false">http://localhost/wp-theme-testing/?post_type=feature&#038;p=3035</guid>
        <description><![CDATA[a test!]]></description>
                <content:encoded><![CDATA[<p>a test!</p>
]]></content:encoded>
            <wfw:commentRss>http://localhost/wp-theme-testing/feartures/test-feature/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>
        </item>
    </channel>
</rss>
  • Hello - thanks. I should clarify, I’m not adding a new node, only changing the value of the permalink if the post has that custom post meta value set. I did actually take a direct copy of feed-rss2.php and drop it in my theme folder (renamed), but I can’t call get_post_meta() in it for some reason, if you’ve any idea why that might be.. – William Turrell Mar 4 '18 at 8:10
  • Hi and thank you for the feedback. I've updated my answer. The values of the default nodes can be manipulated using various filters. get_post_meta() can be used within callbacks attached to these filters or within the rss2_item() action. If get_post_meta() is called within the RSS template directly, it will trigger an error because that portion of WP has not been loaded at that point. – Dave Romsey Mar 4 '18 at 8:50
  • 1
    This all makes sense (and I've up-voted) however I still get undefined for get_post_meta() when it's used in functions.php... – William Turrell Mar 4 '18 at 12:33
  • Hrmm, I think something is wrong on your end. I tested this code before posting it and it works. I added the output example to my answer. Try clearing your browser's cache and removing the foo_custom_rss() related code from your theme. – Dave Romsey Mar 4 '18 at 15:42
0

This is a workaround, but it did solve things for me.

First I moved this site from my vvv to vvv2 dev environment, to rule out anything odd there. Then I went through the WP config files and the rest of functions.php carefully looking for anything with the potential to break things.

No luck so far.

I traced get_post_meta() in the source, thinking I might only be able to solve this by rewriting an equivalent function myself (creating a DB query if necessary) - as readers may know it's simply a wrapper for get_metadata() - for some reason this does work.

So if anyone can suggest why get_post_meta() is undefined and get_metadata() isn't...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.