You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm having trouble with chaining multiple ->with_xxx() calls for TActiveRecord finders that are not executed immediately.
The basic setup is:
TActiveRecords: FirstRecord and SecondRecord
FirstRecord has foreign objects FieldOne and FieldTwo
SecondRecord has foreign objects FieldThree and FieldFour
I'm trying to prepare a finder (with chained with_xxx() calls) for FirstRecord, but execute the appropriate find*() method later in application's lifecycle. The call fails if there's another chain of ->with_xxx() between the creation of the first finder and find*() call. For example:
$preparedFinder = FirstRecord::finder()->withFieldOne()->withFieldTwo();
$otherFinder = SecondRecord::finder()->withFieldThree()->withFieldFour();
$preparedFinder->findAll(); // throws "FirstRecord.FieldFourID is not defined" TInvalidOperationException
As a matter of fact, replacing the last line with:
$otherFinder->findAll();
(so not deferring the second finder, just the first), throws the same exception, only trying to access FieldTwo in SecondRecord.
If there's no chaining (i.e. there's no ->with_xxx() call on TActiveRecordRelation instance, just on TActiveRecord instance), deferring the find*() call works as expected.
This is caused by a static stack used in the TActiveRecordRelation::__call method - which causes the result of withFieldFour() call to be appended to the stack, which is later processed by the findAll() call on TActiveRecordRelation object returned by withFieldTwo() (or vice versa).
Getting rid of multiple with_xxx() chaining does not trigger the same behavior, as the static stack in TActiveRecordRelation is not used. I can also see that design present all the way since 2007, so I'm guessing I'm just trying to use the framework in a way it wasn't supposed to be used. I couldn't find any code examples in documentation that would show either deferring finder() use or multiple with_xxx() chains - is that something that's achievable at all, somehow?
For now I think I can be able to patch my copy of the framework, for example by splitting the static stack per SourceRecord class name, but I'm not sure how unintrusive that workaround would be (it would certainly not work on multiple finders for the same record class, but from what I can see in TActiveRecord::finder implementation, that's impossible anyway).
Best regards,
Michal K.
The text was updated successfully, but these errors were encountered:
Nice analysis of the problem, thank you. Imho this is a technological limit of how TActiveRecordRelations has been implemented.
Yii's ActiveRecord implementation has been worked as a replacement of Prado's ActiveRecord, and for some time a backport also existed in Testing: d4b1971
It worked fine, but has been dropped since we had no active maintainer for it. I hope it could help you in find a solution to the problem.
Hi,
I'm having trouble with chaining multiple
->with_xxx()
calls forTActiveRecord
finders that are not executed immediately.The basic setup is:
TActiveRecord
s:FirstRecord
andSecondRecord
FirstRecord
has foreign objectsFieldOne
andFieldTwo
SecondRecord
has foreign objectsFieldThree
andFieldFour
I'm trying to prepare a finder (with chained
with_xxx()
calls) forFirstRecord
, but execute the appropriatefind*()
method later in application's lifecycle. The call fails if there's another chain of->with_xxx()
between the creation of the first finder andfind*()
call. For example:As a matter of fact, replacing the last line with:
(so not deferring the second finder, just the first), throws the same exception, only trying to access
FieldTwo
inSecondRecord
.If there's no chaining (i.e. there's no
->with_xxx()
call onTActiveRecordRelation
instance, just onTActiveRecord
instance), deferring thefind*()
call works as expected.This is caused by a static stack used in the
TActiveRecordRelation::__call
method - which causes the result ofwithFieldFour()
call to be appended to the stack, which is later processed by thefindAll()
call onTActiveRecordRelation
object returned bywithFieldTwo()
(or vice versa).Getting rid of multiple
with_xxx()
chaining does not trigger the same behavior, as the static stack inTActiveRecordRelation
is not used. I can also see that design present all the way since 2007, so I'm guessing I'm just trying to use the framework in a way it wasn't supposed to be used. I couldn't find any code examples in documentation that would show either deferringfinder()
use or multiplewith_xxx()
chains - is that something that's achievable at all, somehow?For now I think I can be able to patch my copy of the framework, for example by splitting the static stack per
SourceRecord
class name, but I'm not sure how unintrusive that workaround would be (it would certainly not work on multiple finders for the same record class, but from what I can see inTActiveRecord::finder
implementation, that's impossible anyway).Best regards,
Michal K.
The text was updated successfully, but these errors were encountered: