Wildcard Loader Arguments (Menu upcasting)

In Drupal 7 we could have wildcard loader arguments in a menu path so the value at the position of the loader is passed to the wildcard loader function as the first argument. Something like this:

$items['something/%something/edit'] = array(
  [...]
);

and then in the module you would do a wildcard loader function like this:

function something_load($arg) {
  // return what you would like passed as the argument
}

This gave the page callback whatever was returned in the wildcard loader function as an argument. In Drupal 8 it's similar but instead of a wildcard loader function we create a service.

The wildcard in module.routing.yml

my_module.something_edit:
  path: '/something/{something}/edit'
  defaults:
    _controller: '\Drupal\my_module\Controller\ControllerName::build'
    _title: 'My title'
  requirements:
    _permission: 'access content'
  options:
    parameters:
      something:
        type: something

Note: The name of the parameter in the controller method must be the same as the wildcard (i.e. $something)

Create the service in module.services.yml

  my_module.something:
    class: Drupal\my_module\AliasParamConverter
    tags:
      - { name: paramconverter }

Create the service Class

<?php

/**
 * @file
 * Argument loader for something.
 */

namespace Drupal\my_module;

use Drupal\Core\ParamConverter\ParamConverterInterface;
use Drupal\node\Entity\Node;
use Symfony\Component\Routing\Route;

/**
 * Class AliasParamConverter.
 *
 * @package Drupal\my_module
 */
class AliasParamConverter implements ParamConverterInterface {

  public function convert($value, $definition, $name, array $defaults) {
    // Return here whatever you want as a loaded argument or return FALSE if
    // $value is not valid.
  }

  public function applies($definition, $name, Route $route) {
    return (!empty($definition['type']) && $definition['type'] == 'something');
  }

}

And that's it. Drupal 8 knows when to convert the wildcard due to the $definition['type'] == 'something' match in the applies() method in the server.