RealURL: Remove Controller and Action from URL
Asked Answered
S

2

7

I have an extension with a list and show action. Currently this extension can appear on multiple pages:

/page-1/
/page-2/subpage/

I have configured realurl like that:

$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']=array (
    'encodeSpURL_postProc' => array('user_encodeSpURL_postProc'),
    'decodeSpURL_preProc' => array('user_decodeSpURL_preProc'),
    '_DEFAULT' => array (
        …
        'postVarSets' => array(
            '_DEFAULT' => array(
                'controller' => array(
                    array(
                        'GETvar' => 'tx_extension_plugin[controller]',
                        'noMatch' => 'bypass',
                    ),
                ),
                'extension' => array(
                    array(
                        'GETvar' => 'tx_extension_plugin[action]',
                    ),
                    array(
                        'GETvar' => 'tx_extension_plugin[controller]',
                    ),
                    array(
                        'GETvar' => 'tx_extension_plugin[value]',
                        'lookUpTable' => array(
                            'table' => 'table',
                            'id_field' => 'uid',
                            'alias_field' => 'name',
                            'addWhereClause' => ' AND NOT deleted AND NOT hidden',
                            …
);

function user_decodeSpURL_preProc(&$params, &$ref) {
    $params['URL'] = str_replace('page-1/', 'page-1/extension/', $params['URL']);
}

function user_encodeSpURL_postProc(&$params, &$ref) {
    $params['URL'] = str_replace('page-1/extension/', 'page-1/', $params['URL']);
}

Now I get URLs like:

/page-1/ /* shows list */
/page-1/Action/show/name-of-single-element /* single view */

What I actually want is this:

/page-1/name-of-single-element /* single view */

How do I get rid of the action and controller?

If I remove:

array('GETvar' => 'tx_extension_plugin[action]'),
array('GETvar' => 'tx_extension_plugin[controller]'),

it appends the parameters to the URL.

Storytelling answered 1/10, 2014 at 13:30 Comment(2)
It requires another approach, is it your extension ? can you change it's code? show me how do you build your links/urlsAsuncionasunder
@Asuncionasunder Yes, it's my own extension and yes, I can change everything. The links are build like this: <f:link.action action="show" arguments="{article : article}" class="more" title="{article.name}">show article</f:link.action>Storytelling
A
7

You can't avoid adding all the stuff when using f:link.action VH, instead you need to use f:link.page and pass only required params, sample:

<f:link.page additionalParams="{article : article.uid}" class="more" title="{article.name}">show article</f:link.page>

it will generate url like

/current/page/?article=123

or

/current/page/we-added-realurl-support-for-article

next in your first action of plugin (probably list) you just need to forward request to show action if given param exists:

public function listAction() {
    if (intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('article'))>0) $this->forward('show');

    // Rest of code for list action...
}

and probably change signature of show

public function showAction() {

    $article = $this->articleRepository->findByUid(intval(\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('article')));

    if ($article == null) {
        $this->redirectToUri($this->uriBuilder->reset()->setTargetPageUid($GLOBALS['TSFE']->id)->build());
    }


    // Rest of code for show action...
}
Asuncionasunder answered 1/10, 2014 at 15:38 Comment(5)
+1 - works like a charm. Thanks a lot. I changed the code a bit to make it more versatile. I changed the signature to: public function showAction(\namespace $article = null) and wrapped the newly added part into this: if (!$article) { … }.Storytelling
I am using an @transient property in my extension (see #27274977) - can it be that it fails with the above method? When I got it working, all that "transient" data wasn't output anymoreJewbaiting
Seems that extbase was less strict towards the type of property (which I had set wrong) when using the "action" link than now with the alternative procedure. It had nothing to do with "transient"Jewbaiting
That solution works really good. Thank you very much, in some cases it might be better to use the standard get variables like tx_yourext['article']Fuddyduddy
This answer is violating the aspects of domain-driven design and separation of concerns in may ways. Each action shall be called directly with the accordant and valid set of arguments - this is the job of the request-handler, not the job of any controller logic. By-passing the request/response separation and fetching GET parameters directly is another violation - and dangerous in terms of working with non-validated user submitted data (SQLi, XSS et al). Even if it works, it's still hacky...Opportunism
R
7

If the URIbuilder is used you can also use the configuration:

features.skipDefaultArguments = 1

for example;

# if enabled, default controller and/or action is skipped when creating URIs through the URI Builder 
plugin.tx_extension.features.skipDefaultArguments = 1

I use this configuration in combination with the realurl bypass

'postVarSets' => array(
  '_DEFAULT' => array(
    'extbaseParameters' => array(
      array(
        'GETvar' => 'tx_extension_plugin[action]',
        'noMatch' => 'bypass',
      ),
    ),
  ),
),
Rattler answered 26/10, 2015 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.