8

I am working on a typo3 extension and I want to generate an url from the page id. Currently I create the url by appending index.php?id=ID to $GLOBALS['TSFE']->baseURL.

Is there any other way to create a readable url from the page id, and if yes, how it can be done?

cweiske
  • 30,033
  • 14
  • 133
  • 194
  • What kind of extension are you developing? Extbase or piBase/AbstractPlugin? Please share the code you're currently using. – lorenz Jan 06 '15 at 10:58
  • i am using extbase extension –  Jan 06 '15 at 11:15
  • Please share your code. You can build links in Fluid - do you have a Fluid view? – lorenz Jan 06 '15 at 11:27
  • $page_id = ***"ID of page from another function";*** $url = $GLOBALS['TSFE']->baseURL .'index.php?id=' .$page_id; this->view->assign('url', $url); –  Jan 06 '15 at 11:33
  • For Extbase extension @lorenz gave you valid answer, `typolink` method is _inherited_ from pre-MVC ext development – biesior Jan 06 '15 at 12:10

5 Answers5

16

Since Extbase controllers have an UriBuilder object, you should use it:

$uri = $this->uriBuilder->reset()
    ->setTargetPageUid($pageUid)
    ->setCreateAbsoluteUri(TRUE)
    ->build();

You can also set an array of arguments if you need to:

$arguments = array(
    array('tx_myext_myplugin' =>
        array(
            'article' => $articleUid,
        )
    )
);

Or, if you don't need an extension prefix:

$arguments = array(
    'logintype' => 'login'
);

(Of course you can mix the two variants.)

And then use:

$uri = $this->uriBuilder->reset()
    ->setTargetPageUid($pageUid)
    ->setCreateAbsoluteUri(TRUE)
    ->setArguments($arguments)
    ->build();
cweiske
  • 30,033
  • 14
  • 133
  • 194
lorenz
  • 4,538
  • 1
  • 27
  • 45
7

In case you are not in extbase controller context, you can use the standard TYPO3 functionality:

$url = $GLOBALS['TSFE']->cObj->typoLink_URL(
    array(
        'parameter' => $pageUid,
        'forceAbsoluteUrl' => true,
    )
);
cweiske
  • 30,033
  • 14
  • 133
  • 194
1

Some answers already exist but they do not consider some of the other methods. In particular, it is very simple to do it in Fluid. Sometimes, it also depends what you have available (e.g. if a service object is already initialized. For example, I needed to resolve the URL in a middleware and $GLOBALS['TSFE']->cObj was not available there, neither Extbase, so I used method 4).

TL;DR:

  • if using Fluid, use Fluid (method 1)

  • in PHP in Extbase Controller (FE): use $this->uriBuilder (method 2)

  • in PHP, non Extbase (FE): use $site->getRouter()->generateUri (method 4)

  • in PHP, non Extbase (BE): use BackendUtility::getPreviewUrl (method 5)

decision diagram:

.
├── Fluid
│   ├── BE
│   │   └── method1-fluid-vh-link.
│   └── FE
│       └── method1-fluid-vh-link.
└── PHP
    ├── BE
    │   ├── in-extbase-controller
    │   │   └── method2-extbase-uriBuilder
    │   └── non-extbase
    │       └── method5-getPreviewUrl
    └── FE
        ├── in-extbase-controller
        │   └── method2-uriBuilder
        └── non-extbase
            ├── method3-typo3link_URL
            └── method4-site-router-generateUri

  1. If you are using Fluid, this is usually the most straightforward way to render a URL or a link, e.g. use link.page to get a link to a page or use link.action to get a link to a page with Extbase plugins - considering other query parameters as well.

    <f:link.page pageUid="1">link</f:link.page>
    <f:link.action pageUid="1" action="display" controller="Profile" arguments="{studyid: id}">link</f:link.action>
    

  1. If you are in an Extbase Controller (FE) and $this->uriBuilder is initialized (as proposed in other answer by lorenz). Important: There are 2 classes UriBuilder, an Extbase one (\TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder) and a non Extbase one (\TYPO3\CMS\Backend\Routing\UriBuilder), use the Extbase one in FE only, see TYPO3 documentation: Extbase UriBuilder.

    $this->uriBuilder->uriFor($actionName, $arguments, $controllerName, $extensionName);
    
    // or
    
    $uri = $this->uriBuilder->reset()
       ->setTargetPageUid($pageUid)
       ->build();
    

  1. If you are not in Extbase context, but in Frontend, you can use $GLOBALS['TSFE']->cObj->typoLink_URL (as proposed in other answer by cweiske). Important: $GLOBALS['TSFE']->cObj must be initialized which may not be the case in BE or CLI context or in preview mode in FE. See documentation on TypoScript typolink for more parameters.

    // slightly paranoid double-checking here, feel free to leave out if you know what you are doing  
    if (!$GLOBALS['TSFE'] || !$GLOBALS['TSFE'] instanceof TypoScriptFrontendController
         || !$GLOBALS['TSFE']->cObj
         || !$GLOBALS['TSFE']->cObj instanceof ContentObjectRenderer
     ) {
         return '';
     }
    
     $params = [
         'parameter' => $pageId
     ];
    
     return $GLOBALS['TSFE']->cObj->typoLink_URL($params);
    

  1. In FE, but not in Extbase context (same as 3, but using $site, not typoLink_URL, since TYPO3 >= v9):

    $queryParameters = [
        '_language' = 0,
    ];
    
    $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
    $site = $siteFinder->getSiteByPageId($pageId);
    return (string)$site->getRouter()->generateUri(
         $pageId,
         $queryParameters
    );
    

  1. If you are in Backend context, but not in an Extbase module

    BackendUtility::getPreviewUrl($pid)
    
  2. See also Backend class (not Extbase UriBuilder!): TYPO3\CMS\Backend\Routing\UriBuilder to create backend links to edit records (TYPO3 Documentation: Links to Edit Records)

Sybille Peters
  • 2,832
  • 1
  • 27
  • 49
0

In case that you don't have initialized $GLOBALS['TSFE'] and would you like to avoid this bug https://forge.typo3.org/issues/71361 you have to initialize $GLOBALS['TSFE'] in this way:

if (!isset($GLOBALS['TSFE'])) {

            $pid = (int)GeneralUtility::_POST('pid');
            $rootline =
                \TYPO3\CMS\Backend\Utility\BackendUtility::BEgetRootLine($pid);

            foreach ($rootline as $page) {
                if ($page['is_siteroot']) {
                    $id = (int)$page['uid'];
                    break;
                }
            }

            $type = 0;

            if (!is_object($GLOBALS['TT'])) {
                $GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker;
                $GLOBALS['TT']->start();
            }

            $GLOBALS['TSFE'] =
                GeneralUtility::makeInstance('TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController',
                                             $GLOBALS['TYPO3_CONF_VARS'], $id, $type);
            $GLOBALS['TSFE']->connectToDB();
            $GLOBALS['TSFE']->initFEuser();
            $GLOBALS['TSFE']->determineId();
            $GLOBALS['TSFE']->initTemplate();
            $GLOBALS['TSFE']->getConfigArray();

            if
            (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('realurl')
            ) {
                $host =
                    \TYPO3\CMS\Backend\Utility\BackendUtility::firstDomainRecord($rootline);
                $_SERVER['HTTP_HOST'] = $host;
            }
        }
Bjørson Bjørson
  • 1,583
  • 1
  • 17
  • 31
-1

Generate frontend plugin / extension link from Backend Module with cHash parameter

NOTE : Dont forget to include below lines on the top your controller

use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\Page\CacheHashCalculator;

$siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . 'index.php?';
$query = array(
    'id' => 57, // Target page id
    'tx_event_eventfe' => array(
        'controller' => 'Event',
        'action' => 'show',
        'eventId' => 15 // Record uid
    )
);

$cacheHasObj = GeneralUtility::makeInstance(CacheHashCalculator::class);
$cacheHashArray = $cacheHasObj->getRelevantParameters(GeneralUtility::implodeArrayForUrl('', $query));
$query['cHash'] = $cacheHasObj->calculateCacheHash($cacheHashArray);
$uri = $siteUrl . http_build_query($query);