http://forge.typo3.org/http://forge.typo3.org/themes/typo3_forge/favicon/favicon.png?17058661692020-01-27T15:10:12ZTYPO3 ForgeTYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4144192020-01-27T15:10:12ZChris no-lastname-given
<ul><li><strong>Related to</strong> <i><a class="issue tracker-1 status-5 priority-3 priority-lowest closed" href="/issues/87651">Bug #87651</a>: Lazy loading (sometimes) not working in Fluid (only n:1 relations)</i> added</li></ul> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4145662020-01-30T08:47:09ZWolfgang Klingerwolfgang@wazum.com
<ul><li><strong>Priority</strong> changed from <i>Should have</i> to <i>Must have</i></li></ul><p>I can confirm this in composer mode too … 9.5.13, typo3fluid/fluid 2.6.8</p>
<p>If I use a view helper like <br /><pre>
<f:groupedFor groupBy="department" groupKey="department" each="{person.roles}" as="relations">
<f:for each="{relations -> v:iterator.sort(sortBy: 'role.priority', order: 'DESC')}" as="relation">
{relation.role.name}, {relation.department.name}<br>
</f:for>
</f:groupedFor>
</pre></p>
<p>{relation.role.name} is output (loaded because of the v:iterator.sort view helper), but {relation.department.name} is not</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4154952020-02-17T10:13:07ZGuillaume Germainguillaume@germain.bzh
<ul></ul><p>I also see the problem with TYPO3 9.5.13 and typo3fluid/fluid 2.6.9 in Composer mode.</p>
<p>This bug has an impact on performances.</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4154962020-02-17T10:28:25ZAlexander Vogtalexander.vogt@avenit.de
<ul></ul><p>We have the same issue (9.5.13, composer mode). Currently we are using a viewhelper as workaround. For example:</p>
<pre><code class="haml syntaxhl" data-language="haml"><span class="nt"><site:lazyLoad</span> <span class="na">model=</span><span class="s">"{relation.department}"</span> <span class="nt">/></span>
</code></pre>
<pre><code class="php syntaxhl" data-language="php"><span class="mf">...</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="n">renderStatic</span><span class="p">(</span><span class="kt">array</span> <span class="nv">$arguments</span><span class="p">,</span> <span class="nc">\Closure</span> <span class="nv">$renderChildrenClosure</span><span class="p">,</span> <span class="nc">RenderingContextInterface</span> <span class="nv">$renderingContext</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$arguments</span><span class="p">[</span><span class="s1">'model'</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nc">LazyLoadingProxy</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$arguments</span><span class="p">[</span><span class="s1">'model'</span><span class="p">]</span><span class="o">-></span><span class="nf">_loadRealInstance</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="mf">...</span>
</code></pre> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4155972020-02-18T13:39:32ZJohannes Rebhan
<ul></ul><p>We have the same problem. A silly workaround seems to be<br /><pre><code class="xml syntaxhl" data-language="xml"><span class="nt"><f:if</span> <span class="na">condition=</span><span class="s">"{element.lazy} == null"</span><span class="nt">></span>
... do something with {element.lazy.something}
<span class="nt"></f:if></span>
</code></pre><br />This seems to trigger the Proxy and initialize the subobject.</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4174632020-03-03T21:18:08ZB. Kauschb.kausch@bekay.de
<ul></ul><p>That is pretty nasty... can please somebody fix this?</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4174642020-03-03T21:25:21ZB. Kauschb.kausch@bekay.de
<ul></ul><p>Guillaume Germain wrote:</p>
<blockquote>
<p>I also see the problem with TYPO3 9.5.13 and typo3fluid/fluid 2.6.9 in Composer mode.</p>
<p>This bug has an impact on performances.</p>
</blockquote>
<p>Same problem here. Have found the bug: <a class="external" href="https://github.com/TYPO3/Fluid/issues/513">https://github.com/TYPO3/Fluid/issues/513</a></p>
<p>It only occurs in composer mode when the LazyLoadingProxy is a standard/root variable.</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4175682020-03-04T19:13:41ZB. Kauschb.kausch@bekay.de
<ul><li><strong>Subject</strong> changed from <i>Lazy loading (sometimes) not working in Fluid (only n:1 relations)</i> to <i>Getters of class LazyLoadingProxy can't be called by Fluid</i></li></ul><p>Maintainer of the Fluid library says, the problem should be fixed inside of the Typo3 core:</p>
<blockquote>
<p>As such, the problem is already placed on the implementer instead of the library. The library imposes the restriction that overloaded methods don't work - the implementer then has to provide a formalised way to avoid depending on overloaded methods to do the work. One such method in TYPO3 CMS context is to provide a virtual, secondary getter for methods/properties that would return incompatible overloaded method implementers. The virtual getter would then either forcibly read the data in a way that triggers the overloaded method, or call formalised methods that perform the necessary action (in this case, thaws the lazy storage).</p>
</blockquote>
<p>Reasoning behind this: <a class="external" href="https://github.com/TYPO3/Fluid/pull/486#issuecomment-545661652">https://github.com/TYPO3/Fluid/pull/486#issuecomment-545661652</a></p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4176932020-03-05T19:20:10ZGeorg Ringer
<ul><li><strong>Status</strong> changed from <i>New</i> to <i>Accepted</i></li></ul> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4177242020-03-05T23:38:37ZB. Kauschb.kausch@bekay.de
<ul></ul><p>Ideas for a solution: <a class="external" href="https://github.com/TYPO3/Fluid/issues/513#issuecomment-594823546">https://github.com/TYPO3/Fluid/issues/513#issuecomment-594823546</a></p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4179122020-03-07T10:14:31ZClaus Dueclaus@phpmind.net
<ul><li><strong>Category</strong> changed from <i>Fluid</i> to <i>Extbase</i></li></ul><p>Moving issue to Extbase category to be resolved there.</p>
<p>Suggested compatibility approach: use ArrayAccess on LazyLoadingProxy to trigger the loading and proxy to the thawed object when a property is attempted accessed on the proxy.</p>
<p>See for reference:</p>
<p><a class="external" href="https://github.com/TYPO3/Fluid/issues/513#issuecomment-594823546">https://github.com/TYPO3/Fluid/issues/513#issuecomment-594823546</a></p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4245402020-05-04T17:05:12ZRémy DANIEL
<ul></ul><p>Maybe I am to naive, but does adding thoses lines to LazyLoadingProxy will do the job?</p>
<pre><code class="php syntaxhl" data-language="php">
<span class="kd">class</span> <span class="nc">LazyLoadingProxy</span> <span class="kd">implements</span> <span class="nc">\Iterator</span><span class="p">,</span> <span class="nc">LoadingStrategyInterface</span><span class="p">,</span> <span class="nc">\ArrayAccess</span>
<span class="c1">// ...</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">offsetExists</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">__isset</span><span class="p">(</span><span class="nv">$offset</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">offsetGet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">__get</span><span class="p">(</span><span class="nv">$offset</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">offsetSet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">,</span> <span class="nv">$value</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">__set</span><span class="p">(</span><span class="nv">$offset</span><span class="p">,</span> <span class="nv">$value</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">offsetUnset</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">__unset</span><span class="p">(</span><span class="nv">$offset</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>I've added those line on master, and ran successfully Extbase's unit and functional tests.<br />I've also tested it on a real project, and my "fluid" issue was solved.</p>
<p>In the meantime, would it be okay-ish to use the $this->_loadRealInstance() inside the getters of @lazy properties?</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4247162020-05-06T13:17:28ZMarkus Gerdesmarkus@madaxel.de
<ul></ul><p>Hi Daniel,<br />for me your workaround does not work completely.</p>
<p>My LazyLoaded object inherits some properties from its parent class. Those could not be printed whereas the normal properties show up after your workaround.</p>
<p>DANIEL Rémy wrote:</p>
<blockquote>
<p>Maybe I am to naive, but does adding thoses lines to LazyLoadingProxy will do the job?</p>
<p>[...]</p>
<p>I've added those line on master, and ran successfully Extbase's unit and functional tests.<br />I've also tested it on a real project, and my "fluid" issue was solved.</p>
<p>In the meantime, would it be okay-ish to use the $this->_loadRealInstance() inside the getters of @lazy properties?</p>
</blockquote> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316052020-09-21T16:45:39ZStephan Großberndt
<ul><li><strong>Related to</strong> <i><a class="issue tracker-1 status-5 priority-4 priority-default closed" href="/issues/87899">Bug #87899</a>: Magic getters stop to be evaluated in Fluid starting from TYPO3 9</i> added</li></ul> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316372020-09-22T10:36:29ZGerrit Code Review
<ul><li><strong>Status</strong> changed from <i>Accepted</i> to <i>Under Review</i></li></ul><p>Patch set 1 for branch <strong>master</strong> of project <strong>Packages/TYPO3.CMS</strong> has been pushed to the review server.<br />It is available at <a class="external" href="https://review.typo3.org/c/Packages/TYPO3.CMS/+/65803">https://review.typo3.org/c/Packages/TYPO3.CMS/+/65803</a></p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316382020-09-22T10:40:39ZStephan Großberndt
<ul></ul><p>The proposed patch makes <code>AbstractDomainObject</code> implement <code>\ArrayAccess</code> and load the real extbase domain model hidden behind a <code>LazyLoadingProxy</code> on calling <code>offsetGet()</code>. This makes all magic getters of extbase domain models with <code>@lazy</code> annotation available for rendering in Fluid again if they haven't been resolved yet, which was broken since the removal of <code>CmsVariableProvider</code> in TYPO3 v9.0 in <a class="external" href="https://review.typo3.org/c/Packages/TYPO3.CMS/+/53227">https://review.typo3.org/c/Packages/TYPO3.CMS/+/53227</a></p>
<p>Fluid will only resolve the properties that are actually used in the template, and only once - once resolved, the property value is changed (because <code>LazyLoadingProxy</code> violates visibility and sets it on the parent instance through forced reflection).</p>
<p>This is obviously also broken in v9.5 but will not be fixed there anymore as the version only receives security relevant bugfixes.</p>
<p>This solution also fixes the case of lazy loaded objects inheriting properties from their parent class from <a class="external" href="https://forge.typo3.org/issues/90215#note-13">https://forge.typo3.org/issues/90215#note-13</a></p>
<p>In order to reproduce the issue you need:</p>
<pre><code class="php syntaxhl" data-language="php">
<span class="kd">class</span> <span class="nc">\MyVendor\MyExtension\Domain\Model\MyChild</span> <span class="kd">extends</span> <span class="nc">\MyVendor\MyExtension\Domain\Model\MyParent</span> <span class="p">{</span>
<span class="p">}</span>
<span class="kd">class</span> <span class="nc">\MyVendor\MyExtension\Domain\Model\MyParent</span> <span class="kd">extends</span> <span class="nc">\TYPO3\CMS\Extbase\DomainObject\AbstractEntity</span> <span class="p">{</span>
<span class="cd">/**
* @var \MyVendor\MyExtension\Domain\Model\MyReference
* @lazy
*/</span>
<span class="k">protected</span> <span class="nv">$myReference</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
<p>If you put a <code>MyChild</code> instance containing a valid <code>MyReference</code> into a view <code>$this->view->assign('myChild', $myChild);</code> and accessing <code>{myChild.myReference.uid}</code> in a Fluid template this will return an empty uid in Fluid without the patch. With the patch the UID is there.</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316442020-09-22T12:06:19ZGerrit Code Review
<ul></ul><p>Patch set 2 for branch <strong>master</strong> of project <strong>Packages/TYPO3.CMS</strong> has been pushed to the review server.<br />It is available at <a class="external" href="https://review.typo3.org/c/Packages/TYPO3.CMS/+/65803">https://review.typo3.org/c/Packages/TYPO3.CMS/+/65803</a></p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316452020-09-22T12:09:58ZGerrit Code Review
<ul></ul><p>Patch set 3 for branch <strong>master</strong> of project <strong>Packages/TYPO3.CMS</strong> has been pushed to the review server.<br />It is available at <a class="external" href="https://review.typo3.org/c/Packages/TYPO3.CMS/+/65803">https://review.typo3.org/c/Packages/TYPO3.CMS/+/65803</a></p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316632020-09-22T14:29:06ZStephan Großberndt
<ul><li><strong>Status</strong> changed from <i>Under Review</i> to <i>Accepted</i></li></ul><p>Patch was abandoned as implementing <code>\ArrayAccess</code> on <code>AbstractDomainObject</code> lead to problems with <code>ObjectAccess</code> and <code>JsonView</code> of Extbase.</p> TYPO3 Core - Bug #90215: Getters of class LazyLoadingProxy can't be called by Fluidhttp://forge.typo3.org/issues/90215?journal_id=4316912020-09-22T18:50:10ZStephan Großberndt
<ul></ul><p>Reviving the <code>CmsVariableProvider</code> class from <a class="external" href="https://review.typo3.org/c/Packages/TYPO3.CMS/+/53227/4/typo3/sysext/fluid/Classes/Core/Variables/CmsVariableProvider.php">https://review.typo3.org/c/Packages/TYPO3.CMS/+/53227/4/typo3/sysext/fluid/Classes/Core/Variables/CmsVariableProvider.php</a> solves the issue for me in TYPO3 v9 (method <code>resolveSubVariableReferences()</code> is not needed as it is the same in <code>StandardVariableProvider</code>).</p>
<p>But this is a poor workaround only for a TYPO3 v9, which is a version that only receives security updates nowadays, so this is only valuable knowledge for people stuck to v9 at the moment. If you want to upgrade to v10 anyway (which you should), this will not help, as there were changes in the reflection area of Extbase and according to Claus Due this will probably break it - I did not test it though.</p>
<p>The better way is to explicitly resolve the <code>LazyLoadingProxy</code> in your domain model:</p>
<p>Change your model from</p>
<pre><code class="php syntaxhl" data-language="php"><span class="kd">class</span> <span class="nc">\MyVendor\MyExtension\Domain\Model\MyModel</span> <span class="kd">extends</span> <span class="nc">\TYPO3\CMS\Extbase\DomainObject\AbstractEntity</span> <span class="p">{</span>
<span class="cd">/**
* @var \MyVendor\MyExtension\Domain\Model\MyReference
* @lazy
*/</span>
<span class="k">protected</span> <span class="nv">$myReference</span><span class="p">;</span>
<span class="cd">/**
* @return TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy|\MyVendor\MyExtension\Domain\Model\MyReference
*/</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getMyReference</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="n">myReference</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>to</p>
<pre><code class="php syntaxhl" data-language="php"><span class="kd">class</span> <span class="nc">\MyVendor\MyExtension\Domain\Model\MyModel</span> <span class="kd">extends</span> <span class="nc">\TYPO3\CMS\Extbase\DomainObject\AbstractEntity</span> <span class="p">{</span>
<span class="cd">/**
* @var \MyVendor\MyExtension\Domain\Model\MyReference
* @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
*/</span>
<span class="k">protected</span> <span class="nv">$myReference</span><span class="p">;</span>
<span class="cd">/**
* @return \MyVendor\MyExtension\Domain\Model\MyReference
*/</span>
<span class="k">public</span> <span class="k">function</span> <span class="n">getMyReference</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="n">myReference</span> <span class="k">instanceof</span> <span class="nc">LazyLoadingProxy</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">myReference</span><span class="o">-></span><span class="nf">_loadRealInstance</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-></span><span class="n">myReference</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>Now you are able to use strict types on the reference, do not have to care about <code>LazyLoadingProxy</code> anywhere else in your controllers or services and the getters work in Fluid too as if the getter is accessed always the real instance is returned.</p>
<p>This of course means you no longer work with a <code>LazyLoadingProxy</code> at all and do not profit from changes like <a href="https://review.typo3.org/c/Packages/TYPO3.CMS/+/58925" class="external">Allow fetching uid of a LazyLoadingProxy without loading the object first</a></p>
<p>By the way: This is only an issue with <code>LazyLoadingProxy</code>, NOT with <code>LazyObjectStorage</code>, there no such explicit loading is necessary.</p>