get_the_content( string $more_link_text = null, bool $strip_teaser = false, WP_Post|object|int $post = null ): string

Retrieves the post content.

Parameters

$more_link_textstringoptional
Content for when there is more text.

Default:null

$strip_teaserbooloptional
Strip teaser content before the more text.

Default:false

$postWP_Post|object|intoptional
WP_Post instance or Post ID/object.

Default:null

Return

string

More Information

When used inside The Loop, this function will get the content of the current post.

If used outside The Loop, you must inform the post you want to get the content from using the optional $post parameter.

An important difference from the_content() is that get_the_content() does not pass the content through the the_content filter. This means that get_the_content() will not auto-embed videos or expand shortcodes, among other things.

Source

function get_the_content( $more_link_text = null, $strip_teaser = false, $post = null ) {
	global $page, $more, $preview, $pages, $multipage;

	$_post = get_post( $post );

	if ( ! ( $_post instanceof WP_Post ) ) {
		return '';
	}

	/*
	 * Use the globals if the $post parameter was not specified,
	 * but only after they have been set up in setup_postdata().
	 */
	if ( null === $post && did_action( 'the_post' ) ) {
		$elements = compact( 'page', 'more', 'preview', 'pages', 'multipage' );
	} else {
		$elements = generate_postdata( $_post );
	}

	if ( null === $more_link_text ) {
		$more_link_text = sprintf(
			'<span aria-label="%1$s">%2$s</span>',
			sprintf(
				/* translators: %s: Post title. */
				__( 'Continue reading %s' ),
				the_title_attribute(
					array(
						'echo' => false,
						'post' => $_post,
					)
				)
			),
			__( '(more&hellip;)' )
		);
	}

	$output     = '';
	$has_teaser = false;

	// If post password required and it doesn't match the cookie.
	if ( post_password_required( $_post ) ) {
		return get_the_password_form( $_post );
	}

	// If the requested page doesn't exist.
	if ( $elements['page'] > count( $elements['pages'] ) ) {
		// Give them the highest numbered page that DOES exist.
		$elements['page'] = count( $elements['pages'] );
	}

	$page_no = $elements['page'];
	$content = $elements['pages'][ $page_no - 1 ];
	if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
		if ( has_block( 'more', $content ) ) {
			// Remove the core/more block delimiters. They will be left over after $content is split up.
			$content = preg_replace( '/<!-- \/?wp:more(.*?) -->/', '', $content );
		}

		$content = explode( $matches[0], $content, 2 );

		if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) ) {
			$more_link_text = strip_tags( wp_kses_no_null( trim( $matches[1] ) ) );
		}

		$has_teaser = true;
	} else {
		$content = array( $content );
	}

	if ( str_contains( $_post->post_content, '<!--noteaser-->' ) && ( ! $elements['multipage'] || 1 == $elements['page'] ) ) {
		$strip_teaser = true;
	}

	$teaser = $content[0];

	if ( $elements['more'] && $strip_teaser && $has_teaser ) {
		$teaser = '';
	}

	$output .= $teaser;

	if ( count( $content ) > 1 ) {
		if ( $elements['more'] ) {
			$output .= '<span id="more-' . $_post->ID . '"></span>' . $content[1];
		} else {
			if ( ! empty( $more_link_text ) ) {

				/**
				 * Filters the Read More link text.
				 *
				 * @since 2.8.0
				 *
				 * @param string $more_link_element Read More link element.
				 * @param string $more_link_text    Read More text.
				 */
				$output .= apply_filters( 'the_content_more_link', ' <a href="' . get_permalink( $_post ) . "#more-{$_post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
			}
			$output = force_balance_tags( $output );
		}
	}

	return $output;
}

Hooks

apply_filters( ‘the_content_more_link’, string $more_link_element, string $more_link_text )

Filters the Read More link text.

Changelog

VersionDescription
5.2.0Added the $post parameter.
0.71Introduced.

User Contributed Notes

  1. Skip to note 9 content

    find out if the_content has content before output

    in functions.php and similar files:

    // write inside the loop
    $the_content = apply_filters('the_content', get_the_content());
    if ( !empty($the_content) ) {
      echo $the_content;
    }
    // with post object by id
    $post = get_post(12); // specific post
    $the_content = apply_filters('the_content', $post->post_content);
    if ( !empty($the_content) ) {
      echo $the_content;
    }

    as function

    // call inside the loop or with ID
    // taken from has_excerpt() 
    // https://developer.wordpress.org/reference/functions/has_excerpt
    function mytheme_has_content( $post = 0 ){
      $post = get_post( $post );
      return ( !empty(apply_filters('the_content', $post->post_content)) );
    }

    template inside the loop:

    <?php if ( $customQuery->have_posts() ) {?>
      <?php while ( $customQuery->have_posts() ) {
        $customQuery->the_post(); ?>
        <?php $the_content = apply_filters('the_content', get_the_content()); ?>
        <!-- html -->
        <?php if ( !empty($the_content) ) { ?>
          <div class="content">
            <?php echo $the_content; ?>
          </div>
        <?php } ?>
      <?php } ?>
      <?php wp_reset_postdata(); ?>
    <?php } ?>
  2. Skip to note 11 content

    If you use get_the_content() before the global $wp_query object is set, the postmeta are not well generated because generate_postdata() use $wp_query.
    To get around this issue, just construct a global $wp_query object before calling get_the_content()

    global $wp_query;
    $wp_query = new WP_Query();

You must log in before being able to contribute a note or feedback.