How to get the second slug of a page url?

This problem can be solved with the WordPress Rewrite API

The simplest way

I assume that you’ve created a page called year and the request is most probably matched to this rule (.+?)(/[0-9]+)?/?$, with the query rewritten to pagename=year.

However, you will notice from the regular expression that an additional / can be matched to with numbers following it.

Requesting /year/1999 will transform the query to pagename=year&page=%2F1999. Thus page is what will contain 1999. And you can get to it using get_query_var('page'); and feed it to your custom query by using use the simple get_posts() and feed it the extra meta_key and meta_value to retrieve your posts like so:

$args['meta_key'] = 'year';
$args['meta_value'] = get_query_var('page');
// ... other arguments
$posts_array = get_posts( $args );

But isn’t this wrong?

If using this unexpected result and behavior of taking page and feeding it in as year this feels wrong, you can go about achieving the same result in a different way by adding your own rewrite rule.

By adding a rule that will match ^year/([^/]\d+)/?' and rewrite to pagename=year&custom_year=$matches[1] you will be able to access custom_year via $wp global object.

// this has to be done only once!
add_rewrite_rule('^year/([^/]\d+)/?',
    'index.php?pagename=year&custom_year=$matches[1],
    'top');
flush_rewrite_rules();

The code above should be wrapped to be hooked into the init action. The query itself can be accessed retrieved from the $wp->matched_query property and has to be parsed:

global $wp; // may be required to bring into scope

$q_args = array();
parse_str($wp->matched_query, $q_args);
$custom_year = $q_args['custom_year'];

$args['meta_key'] = 'year';
$args['meta_value'] = get_query_var('custom_year');
// ... other arguments
$posts_array = get_posts( $args );

Note how you pick the name of your custom query field and make sure it’s not in danger of collision with any of the reserved terms.

Another way of looking at it

You may be better off looking at the whole situation from an archive’s perspective rather than a page. If you register your own custom taxonomy for your posts instead of a custom field, you’ll be able to query for posts based on that taxonomy without the manually adding additional rewrite rules.

The register_taxonomy() function will allow you to add your custom_year taxonomy and query for it getting archive pages back, without additional parsing, queries, etc.

You may have to flush_rewrite_rules() once after registering the taxonomies in order to flush some new rules WordPress automatically generates when registering taxonomies.

Take note of the rewrite argument you supply to register_taxonomy(), set it to custom_year and you should be able to query for posts in the taxonomy without further modifications.