diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index aef6209..5749533 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1760,10 +1760,7 @@ function template_preprocess_comment(&$variables) {
   $variables['user_picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', array('account' => $comment)) : '';
   $variables['signature'] = $comment->signature;
 
-  $uri = $comment->uri();
-  $uri['options'] += array('attributes' => array('class' => 'permalink', 'rel' => 'bookmark'));
-
-  $variables['title'] = l($comment->subject, $uri['path'], $uri['options']);
+  $variables['title'] = entity_l($comment, NULL, array('attributes' => array('class' => 'permalink', 'rel' => 'bookmark')));
   $variables['permalink'] = l(t('Permalink'), $uri['path'], $uri['options']);
   $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' => $variables['author'], '!datetime' => $variables['created']));
 
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index 2c54daa..a699362 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -371,6 +371,56 @@ function entity_prepare_view($entity_type, $entities) {
 }
 
 /**
+ * Returns the URL of an entity.
+ *
+ * @param Drupal\entity\EntityInterface $entity
+ *   The entity for which to generate a path.
+ * @param array $options
+ *   An associative array of additional options to pass to the url() function.
+ *
+ * @return string|NULL
+ *   The URL of the entity, or NULL if this value is unavailable.
+ *
+ * @see Drupal\entity\EntityInterface::uri()
+ */
+function entity_url(EntityInterface $entity, array $options = array()) {
+  $uri = $entity->uri();
+
+  if (isset($uri)) {
+    $options += $uri['options'];
+    return url($uri['path'], $options);
+  }
+}
+
+/**
+ * Format the URL of an entity as a HTML anchor tag.
+ *
+ * @param Drupal\entity\EntityInterface $entity
+ *   The entity for which to generate a path.
+ * @param $text
+ *   The link text for the anchor tag. Default to entity label.
+ * @param array $options
+ *   An associative array of additional options to pass to the l() function.
+ *
+ * @return string|NULL
+ *   The HTML markup for a link to the entity, or NULL if the value is
+ *   unavailable.
+ *
+ * @see Drupal\entity\EntityInterface::uri()
+ */
+function entity_l(EntityInterface $entity, $text = NULL, array $options = array()) {
+  $uri = $entity->uri();
+
+  if (isset($uri)) {
+    $options += $uri['options'];
+    if (!isset($text)) {
+      $text = $entity->label();
+    }
+    return l($text, $uri['path'], $options);
+  }
+}
+
+/**
  * Returns the label of an entity.
  *
  * This is a wrapper for Drupal\entity\EntityInterface::label(). This function
diff --git a/core/modules/entity/lib/Drupal/entity/EntityInterface.php b/core/modules/entity/lib/Drupal/entity/EntityInterface.php
index ef95cc2..3a6d539 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityInterface.php
@@ -107,6 +107,9 @@ interface EntityInterface {
    *   An array containing the 'path' and 'options' keys used to build the URI
    *   of the entity, and matching the signature of url(). NULL if the entity
    *   has no URI of its own.
+   *
+   * @see entity_url()
+   * @see entity_l()
    */
   public function uri();
 
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php
index e8d979f..7ea5532 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php
@@ -94,4 +94,24 @@ class EntityApiTest extends WebTestBase {
     $value = $entity->get('uid', 'en');
     $this->assertNull($value, 'Language neutral property has been retrieved.');
   }
+
+  /**
+   * Tests Entity uri functions.
+   */
+  function testEntityLabelUrlHelpers() {
+    $user1 = $this->drupalCreateUser();
+
+    // Make sure that the entity_url() returns the expected path.
+    $uri = $user1->uri();
+    $this->assertEqual(url($uri['path'], $uri['options']), entity_url($user1), 'Expected entity URL returned.');
+
+    $label = $user1->label();
+    $this->assertEqual(l($label, $uri['path'], $uri['options']), entity_l($user1), 'Expected entity link returned.');
+
+    $text = $this->randomName();
+    $this->assertEqual(l($text, $uri['path'], $uri['options']), entity_l($user1, $text), 'Expected entity link returned using custom text.');
+
+    $query_option = array('query' => array($this->randomName() => $this->randomName()));
+    $this->assertEqual(l($label, $uri['path'], $uri['options'] + $query_option), entity_l($user1, NULL, $query_option), 'Expected entity link returned using custom options.');
+  }
 }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 349aab5..a9d9fe8 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1334,8 +1334,7 @@ function template_preprocess_node(&$variables) {
     'link_attributes' => array('rel' => 'author'),
   ));
 
-  $uri = $node->uri();
-  $variables['node_url']  = url($uri['path'], $uri['options']);
+  $variables['node_url']  = entity_url($node);
   $variables['title']     = check_plain($node->title);
   $variables['page']      = $variables['view_mode'] == 'full' && node_is_page($node);
 
@@ -1572,9 +1571,8 @@ function node_search_execute($keys = NULL, $conditions = NULL) {
     $extra = module_invoke_all('node_search_result', $node, $item->langcode);
 
     $language = language_load($item->langcode);
-    $uri = $node->uri();
     $results[] = array(
-      'link' => url($uri['path'], array_merge($uri['options'], array('absolute' => TRUE, 'language' => $language))),
+      'link' => entity_url($node, array('absolute' => TRUE, 'language' => $language)),
       'type' => check_plain(node_type_get_name($node)),
       'title' => $node->label($item->langcode),
       'user' => theme('username', array('account' => $node)),
@@ -2565,11 +2563,10 @@ function node_page_view(Node $node) {
   // of the active trail, and the link name becomes the page title.
   // Thus, we must explicitly set the page title to be the node title.
   drupal_set_title($node->label());
-  $uri = $node->uri();
   // Set the node path as the canonical URL to prevent duplicate content.
-  drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE);
+  drupal_add_html_head_link(array('rel' => 'canonical', 'href' => entity_url($node)), TRUE);
   // Set the non-aliased path as a default shortlink.
-  drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
+  drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => entity_url($node, array('alias' => TRUE))), TRUE);
   return node_show($node);
 }
 
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index a61760c..4056e0f 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -598,30 +598,30 @@ function rdf_preprocess_field(&$variables) {
  */
 function rdf_preprocess_user_profile(&$variables) {
   $account = $variables['elements']['#account'];
-  $uri = $account->uri();
+  $url = entity_url($account);
 
   // Adds RDFa markup to the user profile page. Fields displayed in this page
   // will automatically describe the user.
   if (!empty($account->rdf_mapping['rdftype'])) {
     $variables['attributes']['typeof'] = $account->rdf_mapping['rdftype'];
-    $variables['attributes']['about'] = url($uri['path'], $uri['options']);
+    $variables['attributes']['about'] = $url;
   }
   // Adds the relationship between the sioc:UserAccount and the foaf:Person who
   // holds the account.
   $account_holder_meta = array(
     '#tag' => 'meta',
     '#attributes' => array(
-      'about' => url($uri['path'], array_merge($uri['options'], array('fragment' => 'me'))),
+      'about' => entity_url($account, array('fragment' => 'me')),
       'typeof' => array('foaf:Person'),
       'rel' => array('foaf:account'),
-      'resource' => url($uri['path'], $uri['options']),
+      'resource' => $url,
     ),
   );
   // Adds the markup for username.
   $username_meta = array(
     '#tag' => 'meta',
     '#attributes' => array(
-      'about' => url($uri['path'], $uri['options']),
+      'about' => $url,
       'property' => $account->rdf_mapping['name']['predicates'],
       'content' => $account->name,
     )
@@ -695,8 +695,7 @@ function rdf_preprocess_comment(&$variables) {
     // the URI of the resource described within the HTML element, while the
     // typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document,
     // and so on.)
-    $uri = $comment->uri();
-    $variables['attributes']['about'] = url($uri['path'], $uri['options']);
+    $variables['attributes']['about'] = entity_url($comment);
     $variables['attributes']['typeof'] = $comment->rdf_mapping['rdftype'];
   }
 
diff --git a/core/modules/search/search.api.php b/core/modules/search/search.api.php
index 4c24475..0b9546b 100644
--- a/core/modules/search/search.api.php
+++ b/core/modules/search/search.api.php
@@ -236,9 +236,8 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
     $extra = module_invoke_all('node_search_result', $node, $item->langcode);
 
     $language = language_load($item->langcode);
-    $uri = $node->uri();
     $results[] = array(
-      'link' => url($uri['path'], array_merge($uri['options'], array('absolute' => TRUE, 'language' => $language))),
+      'link' => entity_url($node, array('absolute' => TRUE, 'language' => $language)),
       'type' => check_plain(node_type_get_name($node)),
       'title' => $node->label($item->langcode),
       'user' => theme('username', array('account' => $node)),
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index a772e02..b10081c 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -629,8 +629,7 @@ function template_preprocess_taxonomy_term(&$variables) {
   $variables['term'] = $variables['elements']['#term'];
   $term = $variables['term'];
 
-  $uri = $term->uri();
-  $variables['term_url']  = url($uri['path'], $uri['options']);
+  $variables['term_url']  = entity_url($term);
   $variables['term_name'] = check_plain($term->name);
   $variables['page']      = $variables['view_mode'] == 'full' && taxonomy_term_is_page($term);
 
diff --git a/core/modules/taxonomy/taxonomy.tokens.inc b/core/modules/taxonomy/taxonomy.tokens.inc
index c7847b3..eeb8e4b 100644
--- a/core/modules/taxonomy/taxonomy.tokens.inc
+++ b/core/modules/taxonomy/taxonomy.tokens.inc
@@ -110,8 +110,7 @@ function taxonomy_tokens($type, $tokens, array $data = array(), array $options =
           break;
 
         case 'url':
-          $uri = $term->uri();
-          $replacements[$original] = url($uri['path'], array_merge($uri['options'], array('absolute' => TRUE)));
+          $replacements[$original] = entity_url($term, array('absolute' => TRUE));
           break;
 
         case 'node-count':
