Bug #20541
closedProblem with $GLOBALS['TSFE']->recordRegister
0%
Description
I searched a very long time in class.tslib_content.php. Wow...it's a very big file :-)
OK...I have following TS:
lib.productPerformance = CONTENT
lib.productPerformance {
table = tx_ebsprod_product
select {
pidInList = 72
andWhere.data = register:productUid
andWhere.intval = 1
andWhere.wrap = uid=|
selectFields = parameters
}
renderObj = RECORDS
renderObj {
tables = tx_ebsprod_parameter
source.field = parameters
conf.tx_ebsprod_parameter = COA
conf.tx_ebsprod_parameter.10 = TEXT
conf.tx_ebsprod_parameter.10.field = parametername
conf.tx_ebsprod_parameter.10.wrap = <div class="flex-prodinfo-name">|</div>
conf.tx_ebsprod_parameter.10.ifEmpty = <div class="flex-prodinfo-name"> </div>
conf.tx_ebsprod_parameter.20 = TEXT
conf.tx_ebsprod_parameter.20.field = parametervalue
conf.tx_ebsprod_parameter.20.wrap = <div class="flex-prodinfo-value">|</div>
conf.tx_ebsprod_parameter.30 = TEXT
conf.tx_ebsprod_parameter.30.value = <div class="clearer"> </div>
}
}
lib.productInformation = CONTENT
lib.productInformation {
table = tx_ebsprod_product
select {
pidInList = 72
andWhere.data = register:productUid
andWhere.intval = 1
andWhere.wrap = uid=|
selectFields = materials
}
renderObj = TEXT
renderObj {
field = materials
required = 1
wrap = |
}
}
The first part (lib.productPerformance) works without any problems, but second part wouldn't be displayed. This is because $GLOBALS['TSFE']->recordRegister[$conf['table'].':'.$row['uid']] returns "1" on my second part.
So CONTENT wich will be rendered twice will not be displayed.
I found somebody who has the same problem...maybe he explains it a little bit better:
http://typo3.toaster-schwerin.de/typo3_dev/2005_06/msg00595.html
He also has a solution for this problem.
(issue imported from #M11238)
Files
Updated by Daniel Hahler over 15 years ago
I can confirm that the fix (decrementing $GLOBALS['TSFE']->recordRegister[$originalRec] at the end of CONTENT and RECORDS again) works (for Typo3 4.1.x), and that the bug causes very strange behavior, especially if you do not select the uid field (in selectFields).
Updated by Stefan Froemken over 15 years ago
For now I copied the CONTENT-Function and modify it for my needs. Further I added a possibility to debug my SQL-String. You can insert my Script as userFunc with same parameters as CONTENT-Object.
You can download it here. It's a german page:
http://typo3.sfroemken.de/blog/datum/2009/06/18/getsqlquery-veraendertes-content-objekt.html
Updated by Armin Guenther over 15 years ago
I confirm the bug and the fix by Stefan Froemken. I think this is a severe bug.
Tried to build a hierarchical structur out of a (joined) table by recursively query the same table with the CONTENT object (see TS below) - without success. Took me a whole day to figure out that it's a bug in the CONTENT object.
Stefans fix worked like a charm. Thanx!
===
lib.my_example = CONTENT
lib.my_example {
table = tx_thesis_schools
select.join = tx_thesis_programms ON tx_thesis_schools.uid = tx_thesis_programms.school
select.pidInList = 192
select.orderBy = place
select.groupBy = place
renderObj = COA
renderObj.10 = TEXT
renderObj.10.dataWrap = <div class="level_1">{field: place}</div>
renderObj.20 < lib.my_example
renderObj.20 {
select.andWhere.dataWrap = tx_thesis_schools.place = "{field: place}"
select.orderBy = name
select.groupBy = name
renderObj.10.dataWrap = <div class="level_2">{field: name}</div>
renderObj.20 < lib.my_example
renderObj.20 {
select.andWhere.dataWrap = tx_thesis_schools.name = "{field:name}"
select.orderBy = programm_label
select.groupBy >
renderObj.10.dataWrap = <div class=level_3">{field:programm_label}</div>
renderObj.20 >
}
}
}
With the class by Stefan Froemken it works like expected:
includeLibs.getSQLquery = fileadmin/<path>/class.user_getSQLquery.php
lib.my_example = USER
lib.my_example.userFunc = user_getSQLquery->getSQLquery
lib.my_example {
...
}
Updated by Stefan Froemken over 15 years ago
Thanks to Martin Guenther for little example script. I have added my script here to bugtracker, too.
Here I have an addition to Martins script with debugging enabled:
includeLibs.getSQLquery = fileadmin/<path>/class.user_getSQLquery.php
lib.my_example = USER
lib.my_example.userFunc = user_getSQLquery->getSQLquery
lib.my_example {
debug = 1
}
Now my script tolds you the complete SQL-String and how many records it received.
I think this debugging has to be included in original version, too. It is very helpful.
Updated by Armin Guenther over 15 years ago
I agree: The debuging option added by Stefan is very helpfull indeed.
Best, Armin
(not Martin ;-)
Updated by Petra Arentzen over 15 years ago
I can confirm this behavior for version 4.2.8 too.
Greetings
Petra
Updated by Petra Arentzen over 15 years ago
For me I did a little extension which calls original tslib_cObj::CONTENT, but saves counter before and restores it after. My intension was to go a "minimal invasive" way and to keep it work even after an upgrade to next T3-Version which hopefully has fixed this problem. Tested on 4.2.8, guessing it works also an 4.2.6 ...
Feel free to download my little quick fix not really tested user extension:
http://www.pegu.de/fileadmin/content/others/T3X_user_fixbug11238-0_0_0.t3x
Greetings Petra
Updated by Thorsten Kahler almost 15 years ago
I must agree that the "recursion prevention" mechanism represented by tslib_fe::recordRegister indeed is a bit too strict. I don't like Armins example because it only illustrates why this "recursion prevention" probably was introduced: to interrupt TS code that might lead to infinite loops.
I'd suggest to make maximum re-rendering level configurable, because that should help in any reasonable cases and is comparatively easy to implement: the recordRegister already contains a count of usages of a record.
Updated by Sascha Nowak over 14 years ago
Uploaded a patch(bug_11238.diff) that fixes the issue
Updated by Rik Willems about 14 years ago
I bumped into this same problem today. WIthout modifying the source there is no way to get around it, except for a dirty trick. Suppose there already is a CONTENT object that reads the same table and records. This would mean the records wouldn't show up a second time.... Here's what I did.
20 = CONTENT
20 {
wrap = <div class="wrap"> | </div>
table = tx_tagpack_tags
select {
pidInList = 217
join = tx_tagpack_tags_relations_mm ON (tx_tagpack_tags.uid = tx_tagpack_tags_relations_mm.uid_local)
andWhere = tx_tagpack_tags_relations_mm.uid_foreign = {field:uid}
andWhere.insertData = 1
selectFields = *, uid + 100000 as uid
}
renderObj = TEXT
renderObj {
field = name
wrap = <span class="tag"> | </span>
typolink.parameter = 2
typolink.additionalParams = {field:uid}-100000
typolink.additionalParams.wrap = &tx_tagpack_pi1[uid]=|
typolink.additionalParams.stdWrap.insertData = 1
typolink.additionalParams.prioriCalc = 1
}
}
This specific code selects tags from the tagpack extension that are attached to a tt_news record.
Updated by Jo Hasenau about 14 years ago
This is not a bug but a known feature of CONTENT.
It has got built in security to avoid rendering the same element of a table twice and this is done on purpose.
So if you want to introduce this to the core, you have to file a feature request, not a bugfix.
Means: It has to wait until 4.6
Updated by Rik Willems about 14 years ago
For my case I was stunned that stuff would not render. Perhaps a note in TSref would be nice for that? Where do I propose that?
This check will have its benefits but for my case it is annoying. I render a list of tags on the top of my screen. For each record that is lists I also show its attached records. All through CONTENT objects.
What about a property for CONTENT that disables this check? Then you really are aware of what you do.
Updated by Jo Hasenau about 14 years ago
Sounds like a plan.
So according to the new "Don't use negative statements with boolean switches" rule, we should introduce a switch
removeDuplicatedRecords => boolean / default ON
or maybe another parameter
maximumRecordDuplication => integer / default 1
still this has to wait until 4.6 though
Updated by Philipp Gampe about 14 years ago
@Rik changes in TSref go to http://forge.typo3.org/projects/show/typo3v4-doc_core_tsref - just file a feature request/ bug report
Updated by Rik Willems about 14 years ago
@Philipp I added this, thx for the hint
@Jo How do you set typoscript default values? Or do you just do this in the code? I have problems getting a valid and safe check in. If it is not set in Typoscript, each check will result in 0
Updated by Rik Willems about 14 years ago
I added file 11238.diff as a patch for the given problem. It doesn't really adhere to the new rule Jo described but I believe this is the most clear.
The 'maximumRecordDuplication' solution doesn't appeal to me. You can never know what 'run' your TS piece will be.
The proposed solution is fully backwards compatible but allows you to 'actively' circumvent the current safety check.
Updated by Jigal van Hemert almost 14 years ago
Couldn't reproduce this problem in current trunk and Rik Willems couldn't reproduce it in 4.4.6. Can someone test it in 4.3?
Updated by Rik Willems almost 14 years ago
@Jigal van Hemert
I couldn't reproduce today on my live server. But I'm pretty sure I experienced this behaviour before on my testserver. Will have an extra look into this.
Updated by Ernesto Baschny almost 14 years ago
Not reproduceable anymore. Please open a new issue if it appears again. Thanks!
Updated by Anonymous over 12 years ago
i ran into this bug/feature while trying to generate some sort of a-z index for seminars records.
here's my typoscript (modified for demonstration purposes on the andWhere-part):
page.10 > page.10 = COA page.10 { wrap = <ul>|</ul> 10 = CONTENT 10 { table = tx_seminars_seminars select { pidInList = 2025 selectFields = *, SUBSTRING(SOUNDEX(title), 1, 1) as firstLetter groupBy = firstLetter orderBy = firstLetter ASC } renderObj > renderObj = COA renderObj { wrap = <li>|</li> 10 = TEXT 10.field = firstLetter 11 = TEXT 11.field = title 11.noTrimWrap = | (|)| 20 = CONTENT 20 { wrap = <ul>|</ul> table = tx_seminars_seminars select { pidInList = 2025 andWhere = SOUNDEX(title) LIKE "C%" #andWhere.field = firstLetter #andWhere.wrap = SOUNDEX(title) LIKE "|%" orderBy = title ASC } renderObj = TEXT renderObj { field = title wrap = <li>|</li> } } } } }
for a set of seminars records on page 2025 like this:
1 | Axxxxx 2 | Bxxxxx 3 | Cxxxxx 4 | Dxxxxx
this leads to a nested list like this:
<ul> <li> A (Axxxxx) <ul> <li>Cxxxxx</li> </ul> </li> <li> B (Bxxxxx) <ul> <li>Cxxxxxx</li> </ul> </li> <li> C (Cxxxxxx) <ul></ul> </li> <li> D (Dxxxxxx) <ul></ul> </li> </ul>
as soon as the outer CONTENTs row "Cxxxxxx" has being rendered it's not possible to render it again with the inner CONTENT ;-/
Updated by Yana Okulata over 12 years ago
Had the same problem here with 4.7.2 doing a RECORDS-Query via Typoscript - I used a solution that might be helpful and doesn't require making changes to the Typo3-Core. It's described in German - but gathering from your last names that shouldn't be much of a problem: [[http://labor.99grad.de/?p=522]]
Updated by André Fiedler about 12 years ago
I came across the same "issue" in Typo3 4.7.7 and it took me many hours to figure it out why my second select doesn't get rendered. :(
So please add the "ignoreRecordRegister" configuration parameter! (and a big fat notice in the docs!!!)
thx!
Updated by Dan Kleine (Untenzu) almost 12 years ago
I ran into this bug just recently (TYPO3 LTS 4.5.25, 4.6 4.7 6.0 have the same logic though). I fetch one content element via TypoScript on several places inside one page (eg. for the title, and image for the header, a description somewhere else, some fields in a teaser, in a form, whatever). Whenever I nest a CONTENT object inside of another the bug occurs.
I made a short snippet to reproduce the bug in general (Assumption: Have tt_content elements with uid 1 and 10 on the current page).page.999 = COA page.999 { 10 = CONTENT 10 { table = tt_content select { uidInList = 1 selectFields = uid, pid, crdate } renderObj = TEXT renderObj.field = uid stdWrap.wrap = First:| } ### nested CONTENT objects 20 = CONTENT 20 { table = tt_content select { uidInList = 1 selectFields = uid, pid, crdate } renderObj = COA renderObj { ### this call causes setting tt_content:1 as current element ### and increase $GLOBALS['TSFE']->recordRegister[] by one 10 = CONTENT 10 { table = tt_content select { uidInList = 10 selectFields = uid, pid, crdate } renderObj = TEXT renderObj.field = uid } } stdWrap.wrap = Second:| } ### comment out this line to test the bug 20 > 30 = CONTENT 30 { table = tt_content select { uidInList = 1 selectFields = uid, pid, crdate } renderObj = TEXT renderObj.field = uid stdWrap.wrap = Third:| } ### this will always work 40 = TEXT 40.data = DB:tt_content:1:uid 40.wrap = Fourth:| }
- Result without .20: »First:1Third:1Fourth:1« (every call is valid)
- Result with .20: »First:1Second:10Third:Fourth:1« (the third call is empty because tt_content:1 is registered due to the nested CONTENT objects)
PS: I got around the bug by removing the nested CONTENT object and using getText DB (see page.999.40) instead.
Possible solutions to this bug:- Lower the counter on exit as described in #28745 (looks reasonable to me)
- Add a »ignoreRecordRegister« option to CONTENT objects, as proposed in patchfile 11238.diff by Rik Willems (looks like a workaround to me)
- Declare that nesting CONTENT objects is not allowed for the very same element (feels ugly and odd)
I have no idea about side effects, so some smart core devs should suggest a solution imho
Updated by Lisa Deng over 11 years ago
I can produce a similar issue with this feature-bug.
In my case I try to nest content in dependency of a different colPos:
If colPos 1 is empty:
Show me only the bodytext of the first element in colPos 0.
Then list the other ContentElements in colPos 0 as usual.
Instead of not showing the nested content at all as described above in the other posts, the first contentelement is shown twice (first: only the bodytext as wanted, second: the whole contentelement as it is again).
The other contents of this colPos are not shown at all.
// colPos 0 content_main < styles.content.get content_main { table = tt_content select.languageField = sys_language_uid // if ColPos 1 is empty, get rid of the header and show only the bodytext of the 1st ContentElement in colPos 0 stdWrap.override { cObject = COA cObject { 10 = CONTENT 10 { table = tt_content select { where = colPos = 0 orderBy = sorting max = 1 } renderObj < tt_content renderObj { text { 10 > } textpic < .text } } 20 = CONTENT 20 { table = tt_content select { selectFields = CType, uid, header where = colPos = 0 orderBy = sorting languageField = sys_language_uid pidInList = this } renderObj = COA renderObj { 5 = TEXT 5.field = uid 10 = TEXT 10.field = CType 20 = TEXT 20.field = header } } // and then show the other contentElements in colPos 0 as usual 20 > 20 < styles.content.get // here the first ContentElement will be rendered again! // the other ContentElement are not shown } if { isFalse.cObject = CONTENT isFalse.cObject { table = tt_content select { pidInList = this where = colPos = 1 } } } } }
I am assuming that at this point the same "recursion prevention" mechanism is working. Only in a different way.
Updated by Chris Wernsmann about 11 years ago
Ive encountered this problem serveral times now.
If i try to fetch an object which i fetched already before I dont get any response..
Following setup as example:
temp.current = COA temp.current { 10 = CONTENT 10 { table = pages select { pidInList = 22 max = 1 } renderObj = COA renderObj { 10 = CONTENT 10 { table = tt_content select { pidInList.field = uid where = colPos = 9 max = 1 languageField = sys_language_uid } renderObj = COA renderObj { 5 = TEXT 5 { value = here typolink { parameter.field = pid title { cObject = RECORDS cObject { tables = pages source.field = pid conf.pages = TEXT conf.pages.field = title } } } } 20 = IMAGE 20 { required = 1 file{ import = uploads/pics/ import.field = image import.data = levelmedia: -1, slide import.listNum = 0 width = 300c height = 300c } titleText.field = titleText // altText altText.field = altText // titleText imageLinkWrap = 1 imageLinkWrap { enable = 1 typolink { parameter.data = field:pid } } } } } } } }
This is my current setup which I need to get a current project.
The important part is:
5 = TEXT 5 { value = here typolink { parameter.field = pid title { cObject = RECORDS cObject { tables = pages source.field = pid conf.pages = TEXT conf.pages.field = title } } } }
I've already debugged the result of source... The value is 92, which is the correct uid from the page from where I need the title field...
Also I know that the code should be okay, because I use this snippet on many pages.
I think the problem is, that I try to fetch a content which i already fetched before..
Right here:
temp.current = COA temp.current { 10 = CONTENT 10 { table = pages select { pidInList = 22 max = 1 } } }
Now i found a very good WORKAROUND for this problem..
Maybe it helps some of you.
5 = TEXT 5 { value = hier typolink { parameter.field = pid title.cObject = TEXT title.cObject { data.dataWrap = DB:pages:{field:pid}:title } } }
Updated by Anonymous almost 11 years ago
Issue has been fixed for TYPO3 6.x (see http://forge.typo3.org/issues/53768).
Attached to this issue here is a little patch (written against TYPO3 4.5) that adds a tiny debugging alert to the FE, whenever the record/content cannot be rendered due to the recordRegister. Might by helpful to someone ;-)