title: RegEx force retrieving an empty named group
body: <p>I'm implementing a router class resolving some URI patterns to route properly to a controller.</p>
  
  <p>Assuming following simple test cases and my expectations</p>
  
  <pre class="lang-none prettyprint-override"><code>/test                              -&gt; should match with ID ""
  /test/                             -&gt; should match with ID ""
  /test/some-id                      -&gt; should match with ID "some-id"
  /test/some-id/                     -&gt; should match with ID "some-id/"
  /test/some-id/trailing-id-data     -&gt; should match with ID "some-id/trailing-id-data"
  /test/some-id/trailing-id-data/    -&gt; should match with ID "some-id/trailing-id-data/"
  /test-someid                       -&gt; should not match
  </code></pre>
  
  <p>Important is to match the cases 1 and 2 with an optional trailing slash. Both should return an empty ID (I'm not really sure if it's possible with RegEx, my guts are saying otherwise). But if a trailing ID is present the cases 3 to 6 should match. The 7th case is a false one.</p>
  
  <p>I used the following script testing my RegEx</p>
  
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  $pattern = '...';
  $values = [
    '/test',
    '/test/',
    '/test/some-id',
    '/test/some-id/',
    '/test/some-id/trailing-id-data',
    '/test/some-id/trailing-id-data/',
    '/test-some-id'
  ];
  foreach ( $values as $value )
  {
    $matches = [];
    var_export( ( bool ) preg_match( $pattern, $value, $matches ) );
    echo "\n";
    var_export( $matches );
    echo "\n\n";
  }
  </code></pre>
  
  <p>First without expecting an empty ID I tried several RegEx and specified the following one as working</p>
  
  <pre class="lang-none prettyprint-override"><code>/^\/test(\/?|(\/(?&lt;id&gt;.*)))$/
  
  true
  array (
    0 =&gt; '/test',
    1 =&gt; '',
  )
  
  true
  array (
    0 =&gt; '/test/',
    1 =&gt; '/',
  )
  
  true
  array (
    0 =&gt; '/test/some-id',
    1 =&gt; '/some-id',
    2 =&gt; '/some-id',
    'id' =&gt; 'some-id',
    3 =&gt; 'some-id',
  )
  
  true
  array (
    0 =&gt; '/test/some-id/',
    1 =&gt; '/some-id/',
    2 =&gt; '/some-id/',
    'id' =&gt; 'some-id/',
    3 =&gt; 'some-id/',
  )
  
  true
  array (
    0 =&gt; '/test/some-id/trailing-id-data',
    1 =&gt; '/some-id/trailing-id-data',
    2 =&gt; '/some-id/trailing-id-data',
    'id' =&gt; 'some-id/trailing-id-data',
    3 =&gt; 'some-id/trailing-id-data',
  )
  
  true
  array (
    0 =&gt; '/test/some-id/trailing-id-data/',
    1 =&gt; '/some-id/trailing-id-data/',
    2 =&gt; '/some-id/trailing-id-data/',
    'id' =&gt; 'some-id/trailing-id-data/',
    3 =&gt; 'some-id/trailing-id-data/',
  )
  
  false
  array (
  )
  </code></pre>
  
  <p>Now in the second place I'm struggling with retrieving an empty ID.</p>
  
  <p>Is it generally possible and if so, how?</p>