Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: Repeated template lookups were not cached (fixes #4626) #4628

Closed

Conversation

kinglozzer
Copy link
Member

Hopefully the test makes a bit more sense than my wall of text in #4626. Basically, <% with $Foo %>, <% loop $Foo %> and {$Foo.Bar} are not cached.

As far as I can see in git history, they never have been explicitly cached. However, they were somewhat accidentally cached in 3.1. This is what happened in 3.1:

  • <% if $Foo %> looks up Foo and then caches the result
  • <% with $Foo %> would not be cached, but as the result was already in the cache from the <% if %> it would be pulled out anyway
    Refactor ViewableData::obj caching #3985 changed this behaviour, meaning that now if $cache is set to false, it avoids the cache - even if Foo is already present in the cache.

I don’t like using regular expressions to add a fourth parameter to obj() calls, but I can’t see any way to avoid it. Its method signature is different to XML_val() and hasValue(), yet it looks like the template parser expects it to be identical.

cc @hafriedlander

@@ -3775,6 +3780,8 @@ function ClosedBlock_Handle_With(&$res) {
}

$on = str_replace('$$FINAL', 'obj', ($arg['ArgumentMode'] == 'default') ? $arg['lookup_php'] : $arg['php']);
// obj() has a fourth argument to enable caching, so add that to the end of the call
$on = preg_replace('/(\))$/', ', true)', $on);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like risky code. You're using a regexp to hack in an additional parameter to a method call?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see you've addressed this in your PR description. I guess we should get @hafriedlander to look at it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, not ideal :(. I’m sure it’s possible to achieve the same output some other way, I’m just not anywhere near familiar enough with the parser to do that sort of refactoring!

@tractorcow
Copy link
Contributor

I think we should fix this in 4.0. Also see #3924 for some of the work @dhensby has been doing with casting helpers.

Essentially we should REMOVE $forceReturnedObject, always return an object, and make both ViewableData::obj and ViewableData::*_val have the same method signature. Does that remove the need to hack in the extra param and special case for $method === 'obj'?

Alternatively, we could just revert the caching logic for 3.2. I would prefer not changing it again at this stage, though, since it's actually working predictably.

@tractorcow tractorcow added this to the 4.0 milestone Oct 6, 2015
@tractorcow
Copy link
Contributor

Tentatively setting milestone for this issue to 4.0 (even though it's a pr against the 3.2 branch).

@kinglozzer
Copy link
Member Author

Essentially we should REMOVE $forceReturnedObject, always return an object, and make both ViewableData::obj and ViewableData::*_val have the same method signature. Does that remove the need to hack in the extra param and special case for $method === 'obj'?

Yes, making both method signatures identical would solve the issue (and remove the need for either hack). We can definitely fix this (for master) a lot more cleanly if we do it that way.

I would prefer not changing it again at this stage, though, since it's actually working predictably.

The API in ViewableData is more predictable but the way it works in “template-land” is, if anything, less predictable than 3.1 as a result. I agree that we probably shouldn’t revert that commit, though.

My concern is that this is potentially a BC breaking issue when upgrading to 3.2 as this might cause unexpected repeated queries etc with no notice of what’s happening or why: it took me some time to track down why my example wasn’t working in 3.2 but was working in 3.1.

It’s not a critical issue - it’s possible to work around it, at least for my example - but it’s a pain and is potentially a (minor) performance issue depending on what data is being fetched, so I’d like to see this fixed for 3.2 in some way if at all possible.

@tractorcow
Copy link
Contributor

Hm, it might be a bit late for 3.2.0, since it's in rc2 at the moment. =(

@sminnee
Copy link
Member

sminnee commented Apr 19, 2016

Shall we rebase this against master and merge it in, @tractorcow @kinglozzer?

@kinglozzer
Copy link
Member Author

I think it’s best to wait for #3924 to be merged before looking at this again. Either way this won’t be merged into 3.2, so closing

@tractorcow
Copy link
Contributor

I'm in favour of removing $forceReturnedObject in master. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants