Right, that’s what it is supposed to do. It replaces any properties passed to the chunk (or any embedded in the chunk through other tags) that are cacheable first, and then removes the placeholders set from the properties. For the next release, it will also restore any placeholders overwritten in the scope of the chunk. Once the output of that chunk with all cacheable content is produced and cached, it will in the future skip the placeholder setting and simply return the output produced the time it was cached.
I must be misunderstanding this because what I see seems to contradict this. My chunk is in a cached page and should be cached by default (causing my original problem). But it *does* set the placeholder from the properties sent in the getChunk() call even though I don’t use _cachable=false or the ! token in the placeholder tags.
Because they are local to the scope of the chunk and should be replaced immediately. Delaying any placeholders set from these local properties with the ! token will prevent the local placeholders from being processed and you will instead get values outside of the chunk scope replaced (or they will be removed if unprocessed when processing is finished). The restoration feature that is coming in very soon will address the conflict issue with placeholders set outside the chunk scope.
I like that, but now I have this question: Why would I ever want to use the properties array in getChunk() if I can get any combination of cacheing I want using just setPlaceholder() and [[!$placeholder]], especially since using the properties array might conflict with a placeholder marked with the ! tag (perhaps set by a user of the snippet modifying the tpl).?
xPDO::getObject(), getCollection(), getObjectGraph() and getCollectionGraph() are the core xPDO functions that work with xPDOObjects generically. getChunk is a legacy modX API function that I extended with a new parameter to work just as parseChunk did. getChunk has nothing to do with xPDOObjects and is specific to the modX class functionality which extends xPDO and interacts with one particular xPDOObject, modChunk (which extends modElement). There is absolutely no relationship between these functions; one is for loading instances of xPDOObjects, while one is a shortcut method for getting the processed output of a chunk.
BTW, I wanted to ask about the philosophy of using the properties array to *set* incoming properties in getChunk(). My understanding of the general use of arrays like that in the getObject family is that we use an array like that as a set of search criteria for finding the object (and the argument is called $criteria in getObject()). I understand that getChunk() is not just a wrapper for getObject(), but based on what I knew of MODx objects, I would have guessed that that array in getChunk() would just add extra search criteria. I would never have guessed that its function was to set properties of the returned object and it would be really tough to understand what the scope of those changes would be (even after having it explained). And it’s not that common, IMO, to *set* specific object properties in a *get* method.
I don’t have much in the way of an alternative to suggest, but thought I’d at least raise the issue. The only other way I could think of is to do away with that argument altogether (or just not tell people about it) and just use setPlaceolder() and the ! token in the placeholder tags, even if it’s a little less efficient. It might prevent having to have a discussion like this one with a boatload of confused developers.
Once the output of that chunk with all cacheable content is produced and cached, it will in the future skip the placeholder setting and simply return the output produced the time it was cached.Just to see if I’m finally getting this --
Hmm, not really; I see it the opposite; any data that needs to be replaced in the local scope of processing the chunk should be passed as properties. No setPlaceholder() calls are necessary, and anything processed within the scope of the chunk is replaced with those local properties without affecting the global placeholders with the same name; just like parseChunk() always has. So once you call getChunk(’Chunk’, $properties) and the output comes back, you have whatever placeholders were set before you called it available again. Caching is irrelevant to this, since if the chunk is cached, everything it output when cached is not going to be processed again, just returned.
Am I getting close?
I still can’t think of a situation where you’d need to set placeholder properties in the getChunk() call rather than just putting setPlaceHolder() one line above the getChunk() call. Maybe I’m misunderstanding the scope of setPlaceholder(). Doesn’t the most recent setPlaceholder() always determine what goes in the output? I’m still wondering if setting the properties in getChunk() is worth the potential confusion it could cause.
For a chachable chunk, once you’ve made the changes you mention:
The chunk in the cache will always have [[!+placeholder]] tags in it but all other cachable tags will have been replaced with content.
Before rendering, those [[!+placeholder]] tags will be replaced with the most recent setPlaceholder() call’s content unless there are properties set in getChunk().
In that case those properties will appear instead of the ones from setPlaceholder() but what’s in the cache will be unchanged and if that chunk appears elsewhere, even on the same page, it will get the setPlaceholder() values for the placeholders tagged as uncached.
The chunk in the cache will have any tags that could not be processed, including all tags with non-cacheable tokens ( ! ) and any cacheable tags that were not replaced (i.e. no content could be retrieved for those tags).
For a chachable chunk, once you’ve made the changes you mention:
The chunk in the cache will always have [[!+placeholder]] tags in it but all other cachable tags will have been replaced with content.
Most recent is a difficult concept here, since it completely depends on source-order parsing of tags in a tree-like structure. The important point I think you are missing is that [[!+placeholder]] tags will never be replaced by local properties passed to an Element because by the time they are processed, that scope is gone and the placeholders that were set from those local properties are unset.
Before rendering, those [[!+placeholder]] tags will be replaced with the most recent setPlaceholder() call’s content unless there are properties set in getChunk().
In that case those properties will appear instead of the ones from setPlaceholder() but what’s in the cache will be unchanged and if that chunk appears elsewhere, even on the same page, it will get the setPlaceholder() values for the placeholders tagged as uncached.
Using the ! technique will not work with local properties, for a reason, as I have explained; otherwise, I would agree with this.
It’s a whole lot easier, IMHO, for both developers and developer educators if we just say: Use setPlaceholder() to set placeholders and mark any placeholders that shouldn’t be cached with a ! token. We’re done explaining it, and they get it instantly because it fits perfectly with what they already know about caching in MODx. I could be wrong, but I’m thinking that at least 99.9% of the time, that’s going to have exactly the same effect as setting properties in the getChunk() call. In the tiny fraction of other cases, you can still set the properties in getChunk(). On the plus side, and I think it’s a big plus, we don’t have to explain complex details about the scope of placeholder manipulation to the many people who won’t find the information in the docs.
The only counterexample I can think of would be nested snippets using the same placeholder names, but if placeholders always have a local name prefix, I don’t forsee many collisions ever happening and even if the names are the same, it would seldom cause a problem since placeholders are almost always set pretty close to where they’re used and set every time they’re used.
The important point I think you are missing is that [[!+placeholder]] tags will never be replaced by local properties passed to an Element because by the time they are processed, that scope is gone and the placeholders that were set from those local properties are unset.
Which is why using ! in placeholders should be reserved for special situations where placeholders set in the templates are conflicting with those in chunks from an installed add-on.
The important point I think you are missing is that [[!+placeholder]] tags will never be replaced by local properties passed to an Element because by the time they are processed, that scope is gone and the placeholders that were set from those local properties are unset.In my mind, that makes setting the properties in the getChunk() call not only more difficult, but more risky, since any user of the snippet can later make them fail to apply just by adding the ! token to a placeholder in the tpl chunk. A ! placeholder that is *only* set with properties would have no value at all in that case.
What if I decide to cache the snippet? Then those placeholders would never get set and since you prevented caching of the values set by those API calls into the cacheable content, they would now be empty. Another reason why ! in placeholders should be reserved for special situations where you know there will always be a placeholder being set (e.g. using [[!++site_url]] if you serve multiple domains from a single site), regardless of cacheability.
Before rendering, those [[!+placeholder]] tags will be replaced with the most recent setPlaceholder() call’s content. "Most recent" can be hard to predict, but a setPlaceholder() call made just before a call to getChunk() can be counted on to apply for placeholders marked with a ! tag.
It changes them, but just in the scope of processing that chunk. Once the parsing process leaves the scope of that chunk (which includes everything processed within the chunk), the placeholders set via properties are unset, and any values overwritten from the previous scope restored.
For [[+placeholder] tags (cached), sending local properties in a getChunk() call will override the values set in any setPlaceholder() call, but without changing any placeholder values set with setPlaceholder() and without altering the cached chunk.
Quote from: BobRay at Oct 22, 2008, 04:45 PMWhat if I decide to cache the snippet? Then those placeholders would never get set and since you prevented caching of the values set by those API calls into the cacheable content, they would now be empty. Another reason why ! in placeholders should be reserved for special situations where you know there will always be a placeholder being set (e.g. using [[!++site_url]] if you serve multiple domains from a single site), regardless of cacheability.
Before rendering, those [[!+placeholder]] tags will be replaced with the most recent setPlaceholder() call’s content. "Most recent" can be hard to predict, but a setPlaceholder() call made just before a call to getChunk() can be counted on to apply for placeholders marked with a ! tag.
Quote from: OpenGeek
For [[+placeholder] tags (cached), sending local properties in a getChunk() call will override the values set in any setPlaceholder() call, but without changing any placeholder values set with setPlaceholder() and without altering the cached chunk.
It changes them, but just in the scope of processing that chunk. Once the parsing process leaves the scope of that chunk (which includes everything processed within the chunk), the placeholders set via properties are unset, and any values overwritten from the previous scope restored.