-
Notifications
You must be signed in to change notification settings - Fork 641
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
Matrices and Entries queries are over-written when filtered #2160
Comments
Yeah this is a bit of an awkward one… In Craft 2, when you chain-set element query params (or any model’s attributes), each method call would clone the model, set the new attribute value on the clone, and return the clone. $model = new MyModel();
$model->foo('bar');
echo $model->foo; You would expect that the above would output To fix that awkwardness, and for consistency with how chain-setting methods works for Yii's base Query classes (and how chain-setting usually works in general), Craft 3 chain-setter methods now set the new attribute value on the current instance of the model, and return that same current instance. It does result in a change in behavior for templating though, as demonstrated above. Not totally sure what we should do here (if anything). |
It's worth noting that this was easier to get around when I switched to the This worked pretty well: {% set products = craft.entries({ section: 'products' }) %}
{% set allProducts = products.all %}
{% set productSelected = products.slug(productSlug).one %}
|
The issue with the |
As far as a fixup on Craft2, quite possibly this situation doesn't come up too often, because people have already worked around it. It does seem no errors would be introduced by making the change, because chaining expectations hadn't before worked, while future modifications to extant Craft 2 installations would be safer? I might be missing something, it's always safe to add...! |
For me this deteriorates brevity in templating in a pretty serious way. In my case I'm trying to filter a list of films based on a category. I want to pull one category from the full list of entries, and filter my films based on relatedness to that category. But I also need to list all categories in a dropdown, which breaks by dropping to one as soon as the filtering occurs above. {% set films = craft.entries.section('films') %}
{% set collections = craft.categories.group('collections') %}
{% set collectionFilter = craft.app.request.getQueryParam('collection') %}
{% if collectionFilter %}
{% set films = films.relatedTo(collections.slug(collectionFilter).one) // Filters the collections variable instance persistently %}
{% endif %}
<select name="collection">
<option value="">{{ 'Collections'|t }}</option>
{% for collection in collections.all // Collections is now only one category %}
<option value="{{ collection.slug }}" {{ collection.slug == collectionFilter? 'selected' }}>{{ collection.title }}</option>
{% endfor %}
</select>
// Loop through films down here The only way to achieve this in 3 now would be to create a new instance of the list each time replacing line {% set films = films.relatedTo(craft.categories.group('collections').slug(collectionFilter).one) %} Which, granted, doesn't seem like a huge deal in one case, but now imagine 4 or five different filters, searches etc. The code gets really redundant and repetitive very quickly. I've used variations of this pattern countless times in my templates over the last few years on Craft 2 installs, and couldn't say how difficult it would be to update all my sites to work around this. It's not just a matter of a few find and replaces, whole swathes of structure would have to be entirely rewritten. It would definitely be enough to strongly dissuade me from upgrading to 3 on any of them, if only due to the fact that acquiring additional budget from clients would be a hard sell. Maybe I'm the only one that uses a similar style to this, but I would doubt it. I'd love to hear how this would effect others moving from Craft 2 to 3. |
We just released Craft 3 RC8, which adds a new {% set query = entry.matrixField %}
# `query` matches 10 blocks
{% set textBlock = clone(matrixBlocks).type('text').one() %}
# `query` still matches 10 blocks
# (The `type` param was only applied to a clone of the query) |
@brandonkelly I find myself having to use Just having a bit of trouble understanding the purpose of the change from Craft 2 to 3. I was really struggling to figure out what my issue stemmed from and doesn't seem very intuitive, especially to more front-end focused devs like me. |
@jsunsawyer there’s not really any benefit to using |
@brandonkelly I had to use I guess my real question is, why does |
@jsunsawyer Ah in this case, that’s a bug. We’ll get that fixed. Sorry for the confusion! |
resolves a bug brought up in #2160
This just took me 1,5 hours to debug. I'm rendering a template from code and accessing some entry properties at a later stage as well. The template performs a filtered query on a relation, which causes the same relation to still be filtered when I try to use it again later. My solution is to supply a cloned instance of the entry to |
@marten-wirelab We’ve actually changed this behavior in Craft 4 – now field values are automatically cloned each time you fetch them from |
Description
Matrices and entries queries are over-written when filtered.
Example 1:
Use case:
I want to get the first text block to generate the meta description for the page, but still use the full set of blocks for the actual content of the page.
Example 2:
Use case:
I need all of the Products for a drop-down filter, but I also need just the current Product that is selected, which I'd rather get out of the set I already have than query again.
Steps to reproduce
Follow the methods above.
Additional info
The text was updated successfully, but these errors were encountered: