Building frontend URIs in backend modules with Extbase

Written in 2012 for TYPO3 4.x and Extbase 1.x. The APIs have changed since; the article stays online as an archive.

Hey guys,
quite a few month ago I had a very nice project where I needed to create frontend urls in a TYPO3 backend module. And I can tell you it’s not possible using the standard tools extbase comes with. But there’s hope because extbase brings the right tools we just have to change a little bit. Wait, you want to change Extbase itself? No, let’s say we just adopt a feature, put it into an abstract backend module controller and that’s it. And here we go with the code for it.

<?php

// Classes/Controller/AbstractModController.php

require_once(PATH_tslib . 'class.tslib_fe.php');
require_once(PATH_t3lib . 'class.t3lib_userauth.php');
require_once(PATH_tslib . 'class.tslib_feuserauth.php');
require_once(PATH_t3lib . 'class.t3lib_cs.php');
require_once(PATH_tslib . 'class.tslib_content.php');
require_once(PATH_t3lib . 'class.t3lib_tstemplate.php');
require_once(PATH_t3lib . 'class.t3lib_page.php');

class Tx_Test_Controller_AbstractModController extends Tx_Extbase_MVC_Controller_ActionController 
{

  public function initializeAction() 
  {
    $this->buildTSFE();
  }
  
  private function buildTSFE() 
  {
    if (!is_object($GLOBALS['TT'])) {
      $GLOBALS['TT'] = new t3lib_timeTrack;
      $GLOBALS['TT']->start();
    }
  
    $TSFEclassName = t3lib_div::makeInstance('tslib_fe');
  
    $GLOBALS['TSFE'] = new $TSFEclassName($GLOBALS['TYPO3_CONF_VARS'], $this->pid, '0', 1, '', '', '', '');
    $GLOBALS['TSFE']->connectToMySQL();
    $GLOBALS['TSFE']->initFEuser();
    $GLOBALS['TSFE']->fetch_the_id();
    $GLOBALS['TSFE']->getPageAndRootline();
    $GLOBALS['TSFE']->initTemplate();
    $GLOBALS['TSFE']->tmpl->getFileName_backPath = PATH_site;
    $GLOBALS['TSFE']->forceTemplateParsing = 1;
    $GLOBALS['TSFE']->getConfigArray();
  }
  
  private function uriFor($targetPageUid, $actionName = NULL, $controllerArguments = array(), $controllerName = NULL, $extensionName = NULL, $pluginName = NULL, $format = '', $argumentPrefix = NULL) 
  {
    if ($actionName !== NULL) {
      $controllerArguments['action'] = $actionName;
    }
    if ($controllerName !== NULL) {
      $controllerArguments['controller'] = $controllerName;
    } else {
      $controllerArguments['controller'] = $this->request->getControllerName();
    }
    if ($extensionName === NULL) {
      $extensionName = $this->request->getControllerExtensionName();
    }
    if ($pluginName === NULL  TYPO3_MODE === 'FE') {
      $pluginName = Tx_Extbase_Utility_Extension::getPluginNameByAction($extensionName, $controllerArguments['controller'], $controllerArguments['action']);
    }
    if ($pluginName === NULL) {
      $pluginName = $this->request->getPluginName();
    }
    if ($targetPageUid === NULL  TYPO3_MODE === 'FE') {
      $targetPageUid = Tx_Extbase_Utility_Extension::getTargetPidByPlugin($extensionName, $pluginName);
    }
    if ($format !== '') {
      $controllerArguments['format'] = $format;
    }
    if ($argumentPrefix !== NULL) {
      $prefixedControllerArguments = array($argumentPrefix => $controllerArguments);
    } else {
      $pluginNamespace = Tx_Extbase_Utility_Extension::getPluginNamespace($extensionName, $pluginName);
      $prefixedControllerArguments = array($pluginNamespace => $controllerArguments);
    }
  
    return $prefixedControllerArguments;
  }
  
  protected function buildFrontendUri($targetPageUid, $actionName = NULL, $controllerArguments = array(), $controllerName = NULL, $extensionName = NULL, $pluginName = NULL, $noCache = false, $useCacheHash = true, $createAbsoluteUri = true, $format = '', $argumentPrefix = NULL) 
  {
    $this->uriBuilder->reset();
    $this->uriBuilder->setNoCache($noCache)
        ->setUseCacheHash($useCacheHash)
        ->setCreateAbsoluteUri($createAbsoluteUri)
        ->setArguments(
      $this->uriFor($targetPageUid, $actionName, $controllerArguments, $controllerName, $extensionName, $pluginName, $format, $argumentPrefix)
    );
  
    return $this->uriBuilder->buildFrontendUri();
  }
}

So what exactly is the problem why extbase cannot build frontend uris in the backend? Short answer: Because extbase uses the TYPO3 core to build uris and the core has to have a fully functional TSFE to build frontend uris that does not exist in the backend. So the litte fix here is to build our own TSFE with the least configuration necessary. Having the TSFE globally available we are able to build frontend uris but still extbase behaves not the way we want. The usual uriFor function does not behave like the one in our controller. If you want to know more about it, compare it on your own. Important is, that we get the frontend uri params back so we can put them into the standard uriBuilder to build the frontend uri.

So, let’s see next how to actually use this in our backend module. Again some code:

// Classes/Controller/ModController.php

class Tx_Test_Controller_ModController extends Tx_Test_Controller_AbstractModController {
  public function indexAction() {
    return $this->buildFrontendUri(
      5,
      'action',
      array(),
      'controller',
      'tx_ext',
      'pi1',
      TRUE,
      FALSE,
      TRUE
    );
  }
}

So, this controller inherits all the methods from the first controller, means we can now access the buildFrontendUri action of the parent controller and build all needed uris. Just try it out, play around and have fun.

← All posts