Bug #20541

Problem with $GLOBALS['TSFE']->recordRegister

Added by Stefan Froemken about 9 years ago. Updated over 4 years ago.

Status:
Closed
Priority:
Should have
Assignee:
-
Category:
Communication
Target version:
-
Start date:
2009-06-02
Due date:
% Done:

0%

TYPO3 Version:
4.2
PHP Version:
5.2
Tags:
Complexity:
Is Regression:
Sprint Focus:

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)

class.user_getSQLquery.zip (1.9 KB) Administrator Admin, 2009-08-04 09:58

bug_11238.diff View (952 Bytes) Administrator Admin, 2010-10-05 13:57

11238.diff View (1.81 KB) Administrator Admin, 2011-01-13 21:56

core-recordregister-debug.patch View (1.53 KB) Philipp Kitzberger, 2014-02-25 15:08


Related issues

Related to TYPO3 Core - Bug #28745: Problem with $GLOBALS['TSFE']->recordRegister Resolved 2011-08-04
Related to TYPO3 Core - Bug #53768: Displaying the same 'Insert Records'-element more than once does not work Resolved 2013-11-19
Duplicated by TYPO3 Core - Bug #14748: "Insert record" content not always displayed Closed 2005-05-23

History

#1 Updated by Stefan Froemken about 9 years ago

TYPO3 4.2.6 and
TYPO3 4.3 ALPHA 3

#2 Updated by Daniel Hahler about 9 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).

#3 Updated by Stefan Froemken about 9 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

#4 Updated by Armin Guenther almost 9 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 {
...
}

#5 Updated by Stefan Froemken almost 9 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.

#6 Updated by Armin Guenther almost 9 years ago

I agree: The debuging option added by Stefan is very helpfull indeed.

Best, Armin
(not Martin ;-)

#7 Updated by Petra Arentzen almost 9 years ago

I can confirm this behavior for version 4.2.8 too.

Greetings

Petra

#8 Updated by Petra Arentzen almost 9 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

#9 Updated by Thorsten Kahler over 8 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.

#10 Updated by Sascha Nowak almost 8 years ago

Uploaded a patch(bug_11238.diff) that fixes the issue

#11 Updated by Rik Willems over 7 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.

#12 Updated by Jo Hasenau over 7 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

#13 Updated by Rik Willems over 7 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.

#14 Updated by Jo Hasenau over 7 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

#15 Updated by Philipp Gampe over 7 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

#16 Updated by Rik Willems over 7 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

#17 Updated by Rik Willems over 7 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.

#18 Updated by Jigal van Hemert over 7 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?

#19 Updated by Rik Willems over 7 years ago

@Jigal
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.

#20 Updated by Ernesto Baschny over 7 years ago

Not reproduceable anymore. Please open a new issue if it appears again. Thanks!

#21 Updated by Philipp Kitzberger about 6 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 ;-/

#22 Updated by Yana Okulata almost 6 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]]

#23 Updated by André Fiedler over 5 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!

#24 Updated by Dan Untenzu over 5 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:
  1. Lower the counter on exit as described in #28745 (looks reasonable to me)
  2. Add a »ignoreRecordRegister« option to CONTENT objects, as proposed in patchfile 11238.diff by Rik Willems (looks like a workaround to me)
  3. 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

#25 Updated by Lisa Deng almost 5 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.

#26 Updated by Chris Wernsmann over 4 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
        }
    }
}

#27 Updated by Philipp Kitzberger over 4 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 ;-)

Also available in: Atom PDF