Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Menu links are now Content Entities!

Whenever a menu link's ID needs to be retrieved use $menu_link->id().

Loading menu links.

D7

<?php
$menu_link
= menu_link_load($mlid);
?>

D8

<?php
$menu_link
= entity_load('menu_link', $mlid);
?>

Note that loading a menu link through menu_link_load() or entity_load() does not return an access-checked menu link anymore. For now, _menu_link_translate() needs to be called on loaded entities in order to determine access and localized values.

Loading menu links with conditions.

D7

<?php
$links
= db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC))
  ->
leftJoin('menu_router', 'm', 'm.path = ml.router_path')
  ->
fields('ml')
 
// Weight must be taken from {menu_links}, not {menu_router}.
 
->addField('ml', 'weight', 'link_weight')
  ->
fields('m')
  ->
condition('ml.menu_name', $menu_name)
  ->
execute()
  ->
fetchAll();
foreach (
$links as &$link) {
 
$link['options'] = unserialize($link['options']);
}
?>

D8

<?php
$links
= entity_load_multiple_by_properties('menu_link', array('menu_name' => $menu_name));
?>

Creating new menu links.

D7

<?php
$item
= array(
 
'link_title' => t('Home'),
 
'link_path' => '<front>',
 
'menu_name' => 'main-menu',
);
menu_link_save($item);
?>

D8

<?php
$menu_link
= entity_create('menu_link', array(
 
'link_title' => t('Home'),
 
'link_path' => '<front>',
 
'route_name' => '<front>',
 
'route_parameters' => array(),
 
'menu_name' => 'main',
));
$menu_link->save();
?>

You should also set the route_name/route_parameters as it is used internally for various things.
Route names match the keys defined in .routing.yml files.
This values are determined automatically but better set them if they are known.

Saving menu links.

D7

<?php
$result
= db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path))->fetchAll(PDO::FETCH_ASSOC);
foreach (
$result as $link) {
 
$link['link_title'] = t('New link title');
 
$link['options'] = unserialize($link['options']);
 
menu_link_save($link);
}
?>

D8

<?php
$menu_links
= entity_load_multiple_by_properties('menu_link', array('link_path' => $link_path));
foreach (
$menu_links as $menu_link) {
 
$menu_link->link_title = t('New link title');
 
$menu_link->save();
}
?>

Menu bundles

Although menu items are not fieldable, they got bundles! The menu module handled items have bundles for each menu created.
#2177611: Store menu link bundle, fix EntityQuery for menu links might couple menu link bundles with menu names directly.

Note: In constrast to Drupal 7 neither shortcuts nor books are menu links.

Hook changes.

hook_menu_link_alter() has neen replaced by hook_menu_link_presave()

Impacts: 
Module developers
Themers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done