---
title: "Frontend link factory"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:link-factory@main"
source: "ApiOverview/LinkHandling/LinkFactory.rst"
rendered: "2026-09-17T18:20:57+00:00"
---

# Frontend link factory {#frontend-link-factory}

The `\TYPO3\CMS\Frontend\Typolink\LinkFactory` class is the main entry point
for generating links in the TYPO3 frontend from PHP. It creates any kind of link:
to a page, a file, a folder, an external URL, an email address, a telephone
number or a database record, such as a news entry.

This functionality previously resided in
`\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer->typoLink()` and
`\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer->typoLink_URL()`.
It has been extracted into a dedicated class that only deals with generating
links.

**Table of contents**

-   [Methods of the LinkFactory](https://docs.typo3.org/permalink/t3coreapi:methods-of-the-linkfactory@main)
-   [Obtaining a LinkFactory instance](https://docs.typo3.org/permalink/t3coreapi:obtaining-a-linkfactory-instance@main)
-   [Working with the LinkResult](https://docs.typo3.org/permalink/t3coreapi:working-with-the-linkresult@main)
-   [Examples per link type](https://docs.typo3.org/permalink/t3coreapi:examples-per-link-type@main)
-   [Adding query parameters to a page link](https://docs.typo3.org/permalink/t3coreapi:adding-query-parameters-to-a-page-link@main)
-   [How the link is built by the link builders](https://docs.typo3.org/permalink/t3coreapi:how-the-link-is-built-by-the-link-builders@main)

> [!NOTE]
> For rendering links in [Fluid](https://docs.typo3.org/permalink/t3coreapi:fluid@main) templates or TypoScript, the
> established path is still recommended: the ViewHelper
> [Link.typolink ViewHelper \<f:link.typolink>](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Link/Typolink.html#typo3-fluid-link-typolink) or the TypoScript function
> [typolink](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/Functions/Typolink.html#typolink). Use
> `LinkFactory` when an extension needs
> the raw result programmatically, with access to more than just the anchor
> tag.

## Methods of the `LinkFactory` {#methods-of-the-linkfactory}

`LinkFactory` provides two public
methods, both returning a
`\TYPO3\CMS\Frontend\Typolink\LinkResultInterface`:

-   **class LinkFactory**

    -   *Fully qualified name:* `\TYPO3\CMS\Frontend\Typolink\LinkFactory`

    Creates links in the TYPO3 frontend from a TypoLink configuration.

    -   **create(string $linkText, array $linkConfiguration, ContentObjectRenderer $contentObjectRenderer)**

        Creates a link from a link text and a TypoLink configuration array. The
        `$linkConfiguration` uses the same keys as a TypoScript
        [typolink](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/Functions/Typolink.html#typolink), most importantly `parameter`, and
        optionally `target`, `class`, `title`, `additionalParams` and
        [queryParameters](https://docs.typo3.org/permalink/t3coreapi:link-factory-query-parameters@main). Throws an
        `\TYPO3\CMS\Frontend\Typolink\UnableToLinkException` if the link
        cannot be built.

        -   *param $linkText:* the text to be used as the link text
        -   *param $linkConfiguration:* the TypoLink configuration array
        -   *param $contentObjectRenderer:* the current content object renderer

        *Returns:* `TYPO3CMSFrontendTypolinkLinkResultInterface`

    -   **createUri(string $urlParameter, ?ContentObjectRenderer $contentObjectRenderer = null)**

        Creates a link result for a single TypoLink parameter string, for
        example `'t3://page?uid=42 _blank css-class "My title"'`.
        Convenient when only the URL is needed. The
        `ContentObjectRenderer` is
        optional here, so this method can also be used outside a typical content
        rendering context, including in the TYPO3 backend.

        -   *param $urlParameter:* the TypoLink parameter string
        -   *param $contentObjectRenderer:* the current content object renderer, optional

        *Returns:* `TYPO3CMSFrontendTypolinkLinkResultInterface`

## Obtaining a `LinkFactory` instance {#obtaining-a-linkfactory-instance}

Inject `LinkFactory` through
[dependency injection](https://docs.typo3.org/permalink/t3coreapi:dependencyinjection@main) and call it from your own
service:

**EXT:my_extension/Classes/Service/MyLinkService.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Service;

use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Typolink\LinkFactory;
use TYPO3\CMS\Frontend\Typolink\LinkResultInterface;
use TYPO3\CMS\Frontend\Typolink\UnableToLinkException;

readonly class MyLinkService
{
  public function __construct(
    protected LinkFactory $linkFactory,
  ) {}

  /**
   * Build a link to a page and return the ready-to-use URL.
   */
  public function pageUrl(int $pageUid, ContentObjectRenderer $contentObjectRenderer): string
  {
    try {
      $linkResult = $this->linkFactory->create(
        'Read more',
        ['parameter' => 't3://page?uid=' . $pageUid],
        $contentObjectRenderer,
      );
    } catch (UnableToLinkException) {
      return '';
    }

    return $linkResult->getUrl();
  }

  /**
   * Return the full anchor tag instead of just the URL.
   */
  public function pageLink(int $pageUid, ContentObjectRenderer $contentObjectRenderer): LinkResultInterface
  {
    return $this->linkFactory->create(
      'Read more',
      [
        'parameter' => 't3://page?uid=' . $pageUid,
        'target' => '_blank',
        'title' => 'Opens in a new window',
      ],
      $contentObjectRenderer,
    );
  }
}

```

## Working with the `LinkResult` {#working-with-the-linkresult}

Both methods return a
`\TYPO3\CMS\Frontend\Typolink\LinkResultInterface`. It gives programmatic
access to the individual parts of the generated link, rather than only the
rendered anchor tag: the resolved URL, the link type, the link text, the link
target and the HTML attributes. Immutable `with*()` methods each return a
modified copy of the result. The concrete
`\TYPO3\CMS\Frontend\Typolink\LinkResult` additionally renders the result
as a complete anchor tag or as JSON, which is useful for headless or API output.

See the API documentation of
[LinkResultInterface](https://api.typo3.org/main/classes/TYPO3-CMS-Frontend-Typolink-LinkResultInterface.html)
and
[LinkResult](https://api.typo3.org/main/classes/TYPO3-CMS-Frontend-Typolink-LinkResult.html)
for the complete list of available methods.

**Rendering the result in different ways**

```php
$linkResult = $this->linkFactory->createUri('t3://page?uid=42');

$url = $linkResult->getUrl();       // "/the/page/path"
$html = $linkResult->getHtml();     // '<a href="/the/page/path">...</a>'
$json = $linkResult->getJson();     // '{"href":"/the/page/path", ...}'
```

## Examples per link type {#examples-per-link-type}

The link type is determined by the `parameter` value. The following
examples show the configuration for each type. They all use
`create()`; the same `parameter` values work with
`createUri()` as the first part of the parameter string.

### Link to a page {#link-to-a-page}

**Link to the page with the uid 42**

```php
$linkResult = $this->linkFactory->create(
    'Read more',
    ['parameter' => 't3://page?uid=42'],
    $contentObjectRenderer,
);
```

### Link to a file {#link-to-a-file}

**Link to a file by its file uid**

```php
$linkResult = $this->linkFactory->create(
    'Download the file',
    ['parameter' => 't3://file?uid=17'],
    $contentObjectRenderer,
);
```

### Link to an email address {#link-to-an-email-address}

**Link to an email address**

```php
$linkResult = $this->linkFactory->create(
    'Write us',
    ['parameter' => 'mailto:info@example.org'],
    $contentObjectRenderer,
);
```

### Link to a telephone number {#link-to-a-telephone-number}

**Link to a telephone number**

```php
$linkResult = $this->linkFactory->create(
    'Call us',
    ['parameter' => 'tel:+1234567890'],
    $contentObjectRenderer,
);
```

### Link to a record {#link-to-a-record}

**Link to a record, for example a news entry**

```php
$linkResult = $this->linkFactory->create(
    'Read the article',
    ['parameter' => 't3://record?identifier=tx_news&uid=1'],
    $contentObjectRenderer,
);
```

## Adding query parameters to a page link {#adding-query-parameters-to-a-page-link}

<!-- TODO: no Markdown rendering for "versionadded" -->

The queryParameters configuration key has been added. See Feature: #109370 - Array-based queryParameters for page links.

Query parameters are appended to a page link either as a URL-encoded string
via `additionalParams` or as an array via `queryParameters`. The array form
also accepts nested arrays and saves the manual encoding:

**EXT:my_extension/Classes/Service/MyLinkService.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Service;

use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Typolink\LinkFactory;
use TYPO3\CMS\Frontend\Typolink\LinkResultInterface;

readonly class MyLinkService
{
  public function __construct(
    protected LinkFactory $linkFactory,
  ) {}

  /**
   * Build a page link with nested query parameters.
   */
  public function articleLink(
    ContentObjectRenderer $contentObjectRenderer,
  ): LinkResultInterface {
    return $this->linkFactory->create(
      'Read the article',
      [
        'parameter' => 't3://page?uid=42',
        'queryParameters' => [
          'tx_news' => [
            'action' => 'show',
            'id' => 123,
          ],
        ],
      ],
      $contentObjectRenderer,
    );
  }
}

```

If both keys are set, they are merged with `array_replace_recursive()`,
so the values of `queryParameters` take precedence.

## How the link is built by the link builders {#how-the-link-is-built-by-the-link-builders}

Once `LinkFactory` has determined the
link type, the actual link is built by the matching
[link builder](https://docs.typo3.org/permalink/t3coreapi:link-builder@main), and the
[AfterLinkIsGeneratedEvent](https://docs.typo3.org/permalink/t3coreapi:afterlinkisgeneratedevent@main) is dispatched so
the result can still be modified. To learn how the individual link types are
resolved, continue with the [frontend link builder](https://docs.typo3.org/permalink/t3coreapi:link-builder@main).
