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

[4.x]: Length Conditional acts differently from Craft 3 #11129

Closed
jmcgaha opened this issue May 6, 2022 · 4 comments
Closed

[4.x]: Length Conditional acts differently from Craft 3 #11129

jmcgaha opened this issue May 6, 2022 · 4 comments

Comments

@jmcgaha
Copy link

jmcgaha commented May 6, 2022

What happened?

Description

I upgraded a site from Craft 3 -> Craft 4. On my local environment I work with DevMode set to true.
I have a header image that is optional to be included on the page. The twig for this image is below.

{% if entry.headerImage is defined and entry.headerImage|length %}
    <img src="{{ entry.headerImage.one().url({ width: 940 }) }}" class="m-auto mb-10">
{% endif %}

On Craft 3, the conditional evaluates to false and nothing is output.
On Craft 4, I get an error for Impossible to invoke a method ("url") on a null variable.

If I run {{ entry.headerImage|length }} on Craft 4 I get 3396 which i think is a character count of what appears to be json about this query. If I just output {{ entry.headerImage }} I get the json below.

O:28:"craft\elements\db\AssetQuery":93:{s:8:"volumeId";N;s:8:"folderId";N;s:10:"uploaderId";N;s:8:"filename";N;s:4:"kind";N;s:6:"hasAlt";N;s:5:"width";N;s:6:"height";N;s:4:"size";N;s:12:"dateModified";N;s:17:"includeSubfolders";b:0;s:10:"folderPath";N;s:14:"withTransforms";N;s:11:"elementType";s:20:"craft\elements\Asset";s:5:"query";N;s:8:"subQuery";N;s:12:"contentTable";s:12:"{{%content}}";s:12:"customFields";N;s:9:"inReverse";b:0;s:7:"asArray";b:0;s:18:"ignorePlaceholders";b:0;s:6:"drafts";b:0;s:17:"provisionalDrafts";b:0;s:7:"draftId";N;s:7:"draftOf";N;s:12:"draftCreator";N;s:15:"savedDraftsOnly";b:0;s:9:"revisions";b:0;s:10:"revisionId";N;s:10:"revisionOf";N;s:15:"revisionCreator";N;s:2:"id";N;s:3:"uid";N;s:14:"siteSettingsId";N;s:10:"fixedOrder";b:0;s:6:"status";a:1:{i:0;s:7:"enabled";}s:8:"archived";b:0;s:7:"trashed";b:0;s:11:"dateCreated";N;s:11:"dateUpdated";N;s:6:"siteId";i:1;s:6:"unique";b:0;s:11:"preferSites";N;s:6:"leaves";b:0;s:9:"relatedTo";N;s:5:"title";N;s:4:"slug";N;s:3:"uri";N;s:6:"search";N;s:3:"ref";N;s:4:"with";N;s:7:"orderBy";a:1:{s:19:"relations.sortOrder";i:4;}s:13:"withStructure";N;s:11:"structureId";N;s:5:"level";N;s:14:"hasDescendants";N;s:10:"ancestorOf";N;s:12:"ancestorDist";N;s:12:"descendantOf";N;s:14:"descendantDist";N;s:9:"siblingOf";N;s:13:"prevSiblingOf";N;s:13:"nextSiblingOf";N;s:16:"positionedBefore";N;s:15:"positionedAfter";N;s:17:"*defaultOrderBy";a:1:{s:20:"elements.dateCreated";i:3;}s:53:"craft\elements\db\ElementQuery_placeholderCondition";N;s:51:"craft\elements\db\ElementQuery_placeholderSiteIds";N;s:39:"craft\elements\db\ElementQuery_result";N;s:47:"craft\elements\db\ElementQuery_resultCriteria";N;s:45:"craft\elements\db\ElementQuery_searchScores";N;s:42:"craft\elements\db\ElementQuery_cacheTags";N;s:51:"craft\elements\db\ElementQuery_joinedElementTable";b:0;s:6:"select";a:1:{s:2:"**";s:2:"**";}s:12:"selectOption";N;s:8:"distinct";N;s:4:"from";N;s:7:"groupBy";N;s:4:"join";a:1:{i:0;a:3:{i:0;s:10:"INNER JOIN";i:1;a:1:{s:9:"relations";s:14:"{{%relations}}";}i:2;a:4:{i:0;s:3:"and";i:1;s:40:"[[relations.targetId]] = [[elements.id]]";i:2;a:2:{s:18:"relations.sourceId";i:747;s:17:"relations.fieldId";s:2:"11";}i:3;a:3:{i:0;s:2:"or";i:1;a:1:{s:22:"relations.sourceSiteId";N;}i:2;a:1:{s:22:"relations.sourceSiteId";i:1;}}}}}s:6:"having";N;s:5:"union";N;s:11:"withQueries";N;s:6:"params";a:0:{}s:18:"queryCacheDuration";N;s:20:"queryCacheDependency";N;s:27:"yii\base\Component_events";a:0:{}s:35:"yii\base\Component_eventWildcards";a:0:{}s:30:"yii\base\Component_behaviors";a:1:{s:12:"customFields";O:35:"craft\behaviors\CustomFieldBehavior":29:{s:10:"hasMethods";b:1;s:16:"canSetProperties";b:1;s:5:"image";N;s:4:"body";N;s:15:"projectCategory";N;s:14:"articleContent";N;s:4:"text";N;s:7:"heading";N;s:5:"video";N;s:11:"headerImage";N;s:7:"sidebar";N;s:7:"address";N;s:4:"city";N;s:5:"state";N;s:5:"phone";N;s:13:"buyerCategory";N;s:7:"zipCode";N;s:14:"listingSection";N;s:5:"limit";N;s:13:"fairStartDate";N;s:11:"fairEndDate";N;s:8:"question";N;s:6:"answer";N;s:11:"sidebarLink";N;s:6:"button";N;s:4:"file";N;s:55:"craft\behaviors\CustomFieldBehavior_customFieldValues";a:0:{}s:5:"owner";r:1;s:34:"yii\base\Behavior_attachedEvents";a:0:{}}}s:5:"where";N;s:5:"limit";i:1;s:6:"offset";N;s:7:"indexBy";N;s:16:"emulateExecution";b:0;}

Is there an alternative conditional that I should use besides |length that works no matter what devMode is set to or perhaps is there some setting to turn this sort of query output off?

If something is different intentionally from Craft 3->4, having that in the upgrade docs would be great (or perhaps I just missed something).

Steps to reproduce

  1. Set devMode to true
  2. Evaluate a conditional for an empty asset field

Expected behavior

Evaluation of conditional for entry.assetName|length should be false.

Actual behavior

Evaluation of conditional for entry.assetName|length is true.

Craft CMS version

4.0.1

PHP version

8.0.18

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

No response

@jmcgaha
Copy link
Author

jmcgaha commented May 6, 2022

Going further I just found another query that while it's not loading a page error, it still evaluates to true and causes layout issues. This also happens whether or not devMode is true or false.

For this one, I have a matrix called sidebar. If there are any blocks in that matrix it will output a few extra tailwind classes that will allow for a sidebar to appear.
So now even though I don't have any sidebar blocks it is still adding those classes and making the layout wrong.

For this entry, entry.sidebar has no blocks but those grid classes are still being output on the page (no matter what devMode is set to).
<section class="max-w-195 {{ entry.sidebar|length ? 'sm:grid sm:gap-15 sm:grid-cols-10' }} m-auto px-5">

@jmcgaha jmcgaha changed the title [4.x]: Length Conditional with devMode on acts differently from Craft 3 [4.x]: Length Conditional acts differently from Craft 3 May 6, 2022
@jmcgaha
Copy link
Author

jmcgaha commented May 6, 2022

I reread the section on Collections.
It does seem that changing from |length to .count() when querying for the length/existance of objects like blocks/assets/entries/categories is what I needed... I just didn't quite grasp that from the docs because it actually says you can use |length or .count(). So maybe just some clarification is needed?

@brandonkelly
Copy link
Member

entry.headerImage will only be a collection if headerImage had been eager-loaded – in which case, |length would have worked as expected.

Since |length isn’t working I’ll assume it wasn’t eager-loaded though. In which case, you were passing |length directly to the asset query, which has been deprecated since 3.0, and removed in 4.0.

The way you had it set up would also end up resulting in two separate asset queries getting executed – one for |length, and another when you call .one() on the next line.

If you know you’re going to need the actual asset, just fetch it with .one(), and check if it came back with something:

{% set asset = entry.headerImage.one() %}
{% if asset %}
    <img src="{{ asset.url({ width: 940 }) }}" class="m-auto mb-10">
{% endif %}

@jmcgaha
Copy link
Author

jmcgaha commented May 9, 2022

Thanks for the explanation. I think because I never got a deprecation error for doing that I didn't know that it was. I'll make sure my code is updated going forward.

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

No branches or pull requests

2 participants