Make a custom loop inside single.php with pagination

As I far I know, get_posts() function can not be used to paginated results. It is intended to get an array of posts and it sets no_found_rows to true by default from WP 3.1. Pagination won’t work unless you set it to false, or better, use WP_Query.

numberposts is also a invalid argument.

$paged = ( get_query_var( 'page' ) ) ? get_query_var( 'page' ) : 1;

$args = array(
    'posts_per_page'   => 4,
    'post_type'       => array('temas', 'perfiles', 'udem-mundo', 'deportes', 'cultura'),
    'meta_query'    => array(
        'relation'      => 'AND',
         array(
            'key'       => 'contenido_relacionado_impreso',
            'value'     => 'si',
            'compare'   => '=',
         ),
         array(
             'key'       => 'contenido_relacionado_edicion',
             'value'     => $edicion_ID,
             'compare'   => '=',
         ),
     ),
     'paged'         => $paged,
 );

 $posts_relacionados_edicion = new WP_Query( $args );

 if ( $posts_relacionados_edicion->have_posts() ) :

     while( $posts_relacionados_edicion->have_posts() ) :

         $posts_relacionados_edicion->the_post(); ?>

         <div class="col-md-6 col-sm-6">
                 <a href="https://wordpress.stackexchange.com/questions/225024/<?php the_permalink(); ?>" class="blog-titulo-chico"><h3><?php the_title(); ?></h3></a>
              </div>

      <?php endwhile;

      echo paginate_links( array(
          'current' => $paged,
          'total' => $posts_relacionados_edicion->max_num_pages,
          'format' => '?page=%#%'
      ) );

       wp_reset_postdata();

  else : ?>

     <?php _e( 'No found posts.', 'textdomain' ); ?>

  <?php endif; ?>

The code above generates paginate links in the format example.com/{post-name}/{page-number} and it seems to be working.

The next code generates paginate links in the format example.com/{post-name}/page/{page-number}, but they are redirect to example.com/{post-name}/ and makes pagination not working. More work and test would be needed if you want to use URLs like example.com/{post-name}/page/{page-number}:

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

$args = array(
    'posts_per_page'   => 4,
    'post_type'       => array('temas', 'perfiles', 'udem-mundo', 'deportes', 'cultura'),
    'meta_query'    => array(
        'relation'      => 'AND',
         array(
            'key'       => 'contenido_relacionado_impreso',
            'value'     => 'si',
            'compare'   => '=',
         ),
         array(
             'key'       => 'contenido_relacionado_edicion',
             'value'     => $edicion_ID,
             'compare'   => '=',
         ),
     ),
     'paged'         => $paged,
 );

 $posts_relacionados_edicion = new WP_Query( $args );

 if ( $posts_relacionados_edicion->have_posts() ) :

     while( $posts_relacionados_edicion->have_posts() ) :

         $posts_relacionados_edicion->the_post(); ?>

         <div class="col-md-6 col-sm-6">
                 <a href="https://wordpress.stackexchange.com/questions/225024/<?php the_permalink(); ?>" class="blog-titulo-chico"><h3><?php the_title(); ?></h3></a>
              </div>

      <?php endwhile;

      echo paginate_links( array(
          'current' => $paged,
          'total' => $posts_relacionados_edicion->max_num_pages
      ) );

       wp_reset_postdata();

  else : ?>

     <?php _e( 'No found posts.', 'textdomain' ); ?>

  <?php endif; ?>

Or you could also build your own pagination endpoint:

$paged = ( get_query_var( 'my_page' ) ) ? get_query_var( 'my_page' ) : 1;

$args = array(
    'posts_per_page'   => 4,
    'post_type'       => array('post'),
    'paged'         => $paged,
 );

 $posts_relacionados_edicion = new WP_Query( $args );

 if ( $posts_relacionados_edicion->have_posts() ) :

     while( $posts_relacionados_edicion->have_posts() ) :

         $posts_relacionados_edicion->the_post(); ?>

         <div class="col-md-6 col-sm-6">
                 <a href="https://wordpress.stackexchange.com/questions/225024/<?php the_permalink(); ?>" class="blog-titulo-chico"><h3><?php the_title(); ?></h3></a>
              </div>

      <?php endwhile;

      echo paginate_links( array(
          'current' => $paged,
          'total' =>  $posts_relacionados_edicion->max_num_pages,
          'format' => '?my_page=%#%'
      ) );

       wp_reset_postdata();

  else : ?>

     <?php _e( 'No found posts.', 'textdomain' ); ?>

  <?php endif; ?>

Combined with the rewrite tag:

add_action('init', function() {
    add_rewrite_tag( 'my_page', '([0-9]+)' );
} );

error code: 523