I want my news article URLs to be of the following form: http://domain.com/news/news-title-for-seo-and-usability-324/
And I want only the news id to be used in decoding, and title to be added only for SEO purposes.
How can I acomplish it with either RealURL, CoolURI or anything else?
edit: so far I managed to do what I wanted with the following two userfuncs:
array(
'GETvar' => 'tx_news_pi1[news]',
'userFunc' => 'EXT:speciality/Classes/Hooks/RealUrlUserFunc.php:&Tx_Speciality_Hooks_RealUrlUserFunc->main',
'lookUpTable_fake' => array(
'table' => 'tx_news_domain_model_news',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted AND NOT hidden',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
'encodeTitle_userProc' => 'EXT:speciality/Classes/Hooks/RealUrlUserFunc.php:&Tx_Speciality_Hooks_RealUrlUserFunc->user_newsid',
),
),
),
And the userfuncs:
class Tx_Speciality_Hooks_RealUrlUserFunc {
public function main(array $params, $parent) {
$this->pObj = $parent;
if($params['decodeAlias']) {
return $this->alias2id($params);
} else {
return $this->id2alias($params);
}
}
function alias2id($params){
return array_pop(explode('-', $params['value']));
}
function id2alias($params){
return $this->pObj->lookUpTranslation($params['setup']['lookUpTable_fake'], $params['value'], FALSE);
}
function user_newsid($params) {
if($params['pObj']->orig_paramKeyValues['tx_news_pi1[news]'])
return $params['processedTitle'] ."-". $params['pObj']->orig_paramKeyValues['tx_news_pi1[news]'];
else
return $params['processedTitle'];
}
}
The only problem so far is that lookUpTranslation is a protected function, so I had to temporary hack Realurl to make that fucntion public.
So how do I encode a title from my userfunc the right way?
Perhaps there is a easier way to do this but it's definitly possible with RealUrl by using a hook. Keyword is "encodeTitle_userProc", see here:
http://docs.typo3.org/typo3cms/extensions/realurl/1.12.7/Realurl/ClasstxRealurlAdvancedphp/Configuration/Index.html?highlight=encodetitle_userproc
Here's a simple example to remove the registered sign from a URL:
RealUrlConfig:
'product' => array(
array(
'GETvar' => 'tx_myextension[product]',
'lookUpTable' => array(
....
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
'encodeTitle_userProc' => 'EXT:tx_myextension/Classes/Hooks/RealUrlUserFunc.php:&Tx_Myextension_Hooks_RealUrlUserFunc->user_productsTitle',
),
...
),
),
),
And the hook class:
class Tx_Myextension_Hooks_RealUrlUserFunc {
function user_productsTitle($params) {
return preg_replace('/[R]{1}/', '', $params['processedTitle']);
}
}
Related
I have TYPO3 7.6.10.
I have tx_news.
I want to configure my page with news by category.
Now i have:
'newsCategoryConfiguration' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][categories]',
'lookUpTable' => array(
'table' => 'sys_category',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-'
)
)
)
),
It works and the result is:
/domain/page-With-List-Of-News-By-Category/Category
If have a sub category the result is:
/domain/-page-With-List-Of-News-By-Category/Category
Ho can i get:
/domain/page-With-List-Of-News-By-Category/Parent-Category/Sub-Category
Maybe there's a faster or better way. But if you won't find, try this and build it yourself using userfunc in that way:
'useUniqueCache_conf' => [
'strtolower' => 1,
'spaceCharacter' => '-',
'encodeTitle_userProc' => 'My\Ext\Hooks\News\RealUrlCategories->buildCategoryPath'
];
and the class something like:
class RealUrlCategories {
function buildCategoryPath($parameters) {
$categoriesPath = '';
// find category rootline
// you can find the uid somewhere in $parameters, then iterate for parent categories and read db for the titles to build final string
...
// return generated string like "Parent-Category/Sub-Category"
return $categoriesPath;
}
}
The problem is, that realURL parses the result of the userFunc with rawurlencode. So Parent-Category/Sub-Category would be transformed to Parent-Category%252FSub-Category.
You could return Parent-Category-Sub-Category. This would also be stored in the cache.
Also your UserFunc could return Parent-Category~~~Sub-Category and you replace the ~~~ with a / in a $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['encodeSpURL_postProc'] hook, but the ~~~ will be stored in the cache.
You could also add another parameter like parent_category, but this optional parameter doesn't work in the fixesPostVars section because here the parameter is required and so if it is empty, you have an double slash //category in your URL.
Could you find any other solution beside to use the format parent-category-sub-category?
I try to change my generated url from http://www.example.com/page/extensionname/MyArticleNumber/ to http://www.example.com/page/MyArticleNumber/ using Realurl 1.12.8 and TYPO3 6.2.27.
My realurl_conf.php:
'postVarSets' => array(
'_DEFAULT' => array(
'extensionname' => array(
array(
'GETvar' => 'extensionname_plugin[article]',
'lookUpTable' => array(
'table' => 'tx_extensionname_domain_model_article',
'id_field' => 'uid',
'alias_field' => 'CONCAT(short_title, \'-\', juq)',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'spaceCharacter' => '-',
),
),
),
),
),
What and and where do I have to edit to solve this problem?
Thank you in advance.
If you use your extension at one specific page you can use 'fixedPostVars'
'fixedPostVars' => array(
# extension configuration
'extensionname' => array(
array(
'GETvar' => 'extensionname_plugin[article]',
'lookUpTable' => array(
'table' => 'tx_extensionname_domain_model_article',
'id_field' => 'uid',
'alias_field' => 'CONCAT(short_title, \'-\', juq)',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'spaceCharacter' => '-',
),
),
),
),
# PID for extension configurations
'99' => 'extensionname',
),
I have make use of the encodeSpURL_postProc and decodeSpURL_preProc functions of realUrl.
The following code have I added to my realurl_conf.php file:
<?php
$GLOBALS['realURLEncodeSpURLArray'] = array(
'url/by/realurl/' => 'new/url/',
'page/extensionname/' => 'page/'
);
function user_encodeSpURL_postProc(&$params, &$ref)
{
$params['URL'] = str_replace(array_keys($GLOBALS['realURLEncodeSpURLArray']), array_values($GLOBALS['realURLEncodeSpURLArray']), $params['URL']);
}
function user_decodeSpURL_preProc(&$params, &$ref)
{
$params['URL'] = str_replace(array_values($GLOBALS['realURLEncodeSpURLArray']), array_keys($GLOBALS['realURLEncodeSpURLArray']), $params['URL']);
}
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl'] = array(
'encodeSpURL_postProc' => array('user_encodeSpURL_postProc'),
'decodeSpURL_preProc' => array('user_decodeSpURL_preProc'),
'_DEFAULT' => array(
...
);
Please ensure that the new/url/should be unique so that there is no conflict.
By example: If you want to map txnews you got an url like mynewspage/details/txnews/article you should replace mynewspage/details/txnews/ with mynewspage/details/. Do not replace txnews/ with /!
The realurl config with tx_news works fine for me, but I have one problem. I dont need the detail-name in the address.
www.domain.org/news-list/news-detail/test-news-name-here/
and now i dont need the "news-detail".
Here the PHP code realurl.php
<?php
$TYPO3_CONF_VARS['FE']['addRootLineFields'].= ',tx_realurl_pathsegment';
$TYPO3_CONF_VARS['EXTCONF']['realurl']['_DEFAULT'] = array(
'pagePath' => array(
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => '3',
'rootpage_id' => 1,
'firstHitPathCache'=>1
),
'init' => array(
'enableCHashCache' => TRUE,
'enableCHashCache' => 1,
'respectSimulateStaticURLs' => 0,
'enableUrlDecodeCache' => 1,
'enableUrlEncodeCache' => 1
),
'preVars' => array(
array(
'GETvar' => 'L',
'valueMap' => array(
//'de' => '0',
//'en' => '1',
),
'noMatch' => 'bypass',
),
array(
'GETvar' => 'no_cache',
'valueMap' => array(
'nc' => 1,
),
'noMatch' => 'bypass',
),
),
'fileName' => array(
'index' => array(
'sitemap.xml' => array(
'keyValues' => array(
'type' => 1234,
),
),
),
),
'fixedPostVars' => array(
'newsDetailConfiguration' => array(
array(
'GETvar' => 'tx_news_pi1[action]',
'valueMap' => array(
'detail' => '',
),
'noMatch' => 'bypass',
),
array(
'GETvar' => 'tx_news_pi1[controller]',
'valueMap' => array(
'News' => '',
),
'noMatch' => 'bypass',
),
array(
'GETvar' => 'tx_news_pi1[news]',
'lookUpTable' => array(
'table' => 'tx_news_domain_model_news',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
),
'languageGetVar' => 'L',
'languageExceptionUids' => '',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'autoUpdate' => 1,
'expireDays' => 180,
),
),
),
'6' => 'newsDetailConfiguration',
// For additional detail pages, add their uid as well
//'13' => 'newsDetailConfiguration',
//'22' => 'newsDetailConfiguration',
//'4' => 'newsTagConfiguration',
//'4' => 'newsCategoryConfiguration',
),
'postVarSets' => array(
'_DEFAULT' => array(
'controller' => array(
array(
'GETvar' => 'tx_news_pi1[action]',
'noMatch' => 'bypass',
),
array(
'GETvar' => 'tx_news_pi1[controller]',
'noMatch' => 'bypass',
),
),
'stadt' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][categories]',
'lookUpTable' => array(
'table' => 'sys_category',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
),
),
),
),
'tags' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][tags]',
'lookUpTable' => array (
'table' => 'tx_news_domain_model_tag',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => 'AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array (
'strtolower' => 1,
'spaceCharacter' => '-',
),
),
),
),
'seite' => array(
array(
'GETvar' => 'tx_news_pi1[#widget_0][currentPage]',
),
),
// news archive parameters
'archiv' => array(
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][year]',
),
array(
'GETvar' => 'tx_news_pi1[overwriteDemand][month]',
'valueMap' => array(
'january' => '01',
'february' => '02',
'march' => '03',
'april' => '04',
'may' => '05',
'june' => '06',
'july' => '07',
'august' => '08',
'september' => '09',
'october' => '10',
'november' => '11',
'december' => '12',
),
),
),
),
),
// configure filenames for different pagetypes
'fileName' => array(
'defaultToHTMLsuffixOnPrev' => 0,
),
);
?>
I need that typoscript?
plugin.tx_news {
settings {
link {
skipControllerAndAction = 1
}
}
}
In the Detail-Page I check the realurl:
tx_realurl_exclude = 1
You can use detail & list plugin on the same page. Check this url: https://forge.typo3.org/issues/50489
lib.news = USER
lib.news {
userFunc = tx_extbase_core_bootstrap->run
pluginName = Pi1
extensionName = News
controller = News
settings =< plugin.tx_news.settings
persistence =< plugin.tx_news.persistence
view =< plugin.tx_news.view
}
lib.news_list< lib.news
lib.news_list {
action = list
switchableControllerActions.News.1 = list
}
lib.news_detail < lib.news
lib.news_detail {
action = detail
switchableControllerActions.News.1 = detail
}
[globalVar = GP:tx_news_pi1|news > 0]
lib.field_news_single < lib.news_detail
[else]
lib.field_news_list < lib.news_list
[end]
Answer: it is not possible to exclude the current (=last) page from speaking URL.
If you are interested in technical details, you can read more in the RealURL's notes for integrators.
Just an additional followup with another solution:
Use a TypoScript condition to render dynamically the detail plugin at the list page.
[globalVar = GP:tx_news_pi1|news > 0]
page.10 >
page.10 < lib.news
[global]
Of course you can do a lot more fancy stuff if you need to render e.g. other content elements as well!
[globalVar = GP:tx_news_pi1|news > 0]
page.10 >
page.10 = CONTENT
page.10 {
table = tt_content
pidInList = <page ID of your detail page>
orderBy = sorting
}
[global]
This will render you all content elements of the detail page on the list page.
If you want to have list and single view on separate pages then extension singleview at https://github.com/sourcebroker/singleview does exactly what you want.
This extension uses TYPO3 build in feature "Show content from pid" which you can find in page properties. In this extension value for "Show content from pid" field is set dynamically based on $_GET parameter. When TYPO3 renders page with list view then ext:singleview checks if $_GET parameter has single view request. If this is true then it sets "content_from_pid" field with value of single view page uid. This way single view page with its content and layout is shown on list view page.
For TYPO3 7.6 use ext:singlenews version 1.3.
I'm runnning Typo3 6.2.4 with RealURL 1.12.8 and News (tx_news) 3.0.1. Using the automatic configuration from RealURL rewrites the URLs for "normal" pages, but not for news. The generated links look like this:
index.php?id=5&tx_news_pi1%5Bnews%5D=4&tx_news_pi1%5Bcontroller%5D=News&tx_news_pi1%5Baction%5D=detail&cHash=706379a0ef43d4020448c5193f865bf1
This is what automatic configuration gives me. I've just inserted the part from http://docs.typo3.org/typo3cms/extensions/news/Main/Administration/Realurl/Index.html. At the moment I'm not interested in creating a special kind of rewritten URL, I just want to get RealURL rewrite the news URLs. Once that's running, I think I'll get the rest figured out.
<?php
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']=array (
'_DEFAULT' =>
array (
'init' =>
array (
'enableCHashCache' => true,
'appendMissingSlash' => 'ifNotFile,redirect',
'adminJumpToBackend' => true,
'enableUrlDecodeCache' => true,
'enableUrlEncodeCache' => true,
'emptyUrlReturnValue' => '/',
),
'pagePath' =>
array (
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'rootpage_id' => '1',
),
'fileName' =>
array (
'defaultToHTMLsuffixOnPrev' => 0,
'acceptHTMLsuffix' => 1,
'index' =>
array (
'print' =>
array (
'keyValues' =>
array (
'type' => 98,
),
),
),
),
'postVarSets' =>
array (
'_DEFAULT' =>
array (
// EXT:news start
'news' => array(
array(
'GETvar' => 'tx_news_pi1[action]',
),
array(
'GETvar' => 'tx_news_pi1[controller]',
),
array(
'GETvar' => 'tx_news_pi1[news]',
'lookUpTable' => array(
'table' => 'tx_news_domain_model_news',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
),
'languageGetVar' => 'L',
'languageExceptionUids' => '',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'autoUpdate' => 1,
'expireDays' => 180,
),
),
),
// EXT:news end
),
),
),
);
It turned out that my realurl_conf.php was correct, but the TypoScript configuration part was missing. As soon as I put those lines in the template setup of my root page, Typo3 started to rewrite the URLs:
config.absRefPrefix = /
config.tx_realurl_enable = 1
config.uniqueLinkVars = 1
# dont forget to set the allowed range - otherwise anything else could be inserted
config.linkVars = L(0-3)
Source:
http://wiki.typo3.org/Realurl/manual#TypoScript_configuration
http://docs.typo3.org/typo3cms/extensions/realurl/Realurl/Configuration/HandlingRelativeLinksWithSpeakingUrls/Index.html
I have an URL which looks like this:
http://domain.com/leistungen/industrial-design/?tx_fsproject_fsprojectfp%5Bproject%5D=2&tx_fsproject_fsprojectfp%5Baction%5D=show&tx_fsproject_fsprojectfp%5Bcontroller%5D=Project&cHash=7c405bcde49853af9a7e78bdf465002c
Using RealURL with the following configuration (and some hook functions as explained here):
'postVarSets' => array(
'_DEFAULT' => array(
// projects
'industrial-design' => array(
array(
'GETvar' => 'tx_fsproject_fsprojectfp[controller]',
),
array(
'GETvar' => 'tx_fsproject_fsprojectfp[action]',
),
array(
'GETvar' => 'tx_fsproject_fsprojectfp[project]',
'lookUpTable' => array(
'table' => 'tx_fsproject_domain_model_project',
'id_field' => 'uid',
'alias_field' => 'title',
'addWhereClause' => ' AND deleted !=1 AND hidden !=1',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
)
)
),
),
),
),
I get an URL looking like this:
http://domain.com/leistungen/industrial-design/industrial-design/projekt/project-b/
This is not bad. However, why does the industrial-design/ part show up twice?
The first industrial-design is the page that is being displayed. The second one is the keyword inserted by RealURL to identify the set of variables. To avoid that you can:
Change the structure of pages so that you don't have industrial-design page at all.
Rename the postVarSets that you set up in the RealURL configuration.
Use fixedPostVars instead as that doesn't use a keyword to identify the set of variables but a page UID.