Is there a way to make this kind of loop shorter and nicer?

Yes, there are a few improvements.

  • Needlessly opening and closing PHP tags is a timewaster, makes it harder to read, and means more typing
  • PHP Alt/short style syntax isn’t going to play as nicely with the editor. Use {} instead, and your IDE may even help you type out the closing brace automagically.
  • Query_posts, never, ever use it. There is no valid use case that isn’t covered by WP_Query or the pre_get_posts filter
  • Dont put a trailing ?> at the end of a PHP file
  • Use PHP comments not HTML comments
  • get_template_part should be used instead of include
  • You made no attempt to do cleanup after your query
  • You never checked to see if any pages were found at all
  • You’re using page in your template names, this could cause clashes with the template heirarchy and may not load the template you think in some circumstances

So lets begin:

<?php

// grab pages
$args = array( 'post_type' => 'page' );
$query = new WP_Query( $args );

// did we actually find posts?
if ( $query->have_posts() ) {

    // while there are still posts
    while ( $query->have_posts()) {
        // setup the current post data/globals
        $query->the_post();

        // grab its ID
        $id = get_the_ID();
        if ($id == 5) {
            get_template_part( 'page_special' );
        } else {
            get_template_part( 'page_all' );
        }
    }
    // cleanup after ourselves
    wp_reset_postdata();
} else {
    // no pages were found!
}

Now, you can use get_template_part to further extend this.

First, I would swap this out to use ‘content’ rather than ‘page’ as the main identifier. So:

  • page_all.php becomes content.php
  • page_special.php becomes content-special.php

Note the use of – not _.

Then, I would modify the code that loads the content template, like so:

get_template_part( 'content', get_the_ID() );

If you land on page 4 for example, it will attempt to load content-4.php, and if that doesn’t exist, it will load content.php. You can pass in anything you want as the second parameter, and it’ll also look in child/parent themes. Tie this to a custom field/post meta and you can extend it further