craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.2k stars 617 forks source link

[4.x]: Calling unknown method: craft\models\FieldLayout::getFields() on users/save-user from the CP #14123

Closed romainpoirier closed 5 months ago

romainpoirier commented 6 months ago

What happened?

Description

When creating a new user in the CP via /admin/users/new, I am encountering the following error:

Twig Runtime Error – [Twig\Error\RuntimeError](http://twig.sensiolabs.org/api/2.x/Twig/Error/RuntimeError.html)
Calling unknown method: craft\models\FieldLayout::getFields() in "__string_template__9e1e754f05d83ae28ec00638f3807f6d" at line 10

However, I am in the CP and do not have any events that call getFields.

I have executed project-config/apply, project-config/rebuild, utils/fix-field-layout-uids/index, and utils/repair/project-config just in case, but without success.

Craft CMS version

4.5.11.1

PHP version

8.1.0

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

-

i-just commented 5 months ago

Hi, thanks for getting in touch!

Can you please try clearing caches, either via clear-caches/all or Control Panel > Utilities > Caches? If that doesn’t help, can you please post the full stack trace from the logs?

romainpoirier commented 5 months ago

Thank you. I cleared the caches using both methods.

Here's the full stack trace :

Twig\Error\RuntimeError: Calling unknown method: craft\models\FieldLayout::getFields() in "__string_template__9e1e754f05d83ae28ec00638f3807f6d" at line 10 in /vendor/craftcms/cms/src/helpers/Template.php:135
Stack trace:
#0 /storage/runtime/compiled_templates/c9/c9fd308ff88a1852a77734ecfab166b9.php(47): craft\helpers\Template::attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(craft\models\FieldLayout), 'getFields', Array, 'method')
#1 /vendor/twig/twig/src/Template.php(394): __TwigTemplate_b15e5b00804ec03c67f6ff365c5ffc12->doDisplay(Array, Array)
#2 /vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#3 /vendor/twig/twig/src/Template.php(379): Twig\Template->display(Array)
#4 /vendor/twig/twig/src/TemplateWrapper.php(40): Twig\Template->render(Array, Array)
#5 /vendor/craftcms/cms/src/web/View.php(576): Twig\TemplateWrapper->render(Array)
#6 /vendor/craftcms/webhooks/src/Plugin.php(157): craft\web\View->renderString('{% set entry = ...', Array)
#7 [internal function]: craft\webhooks\Plugin->craft\webhooks\{closure}(Object(craft\events\ModelEvent))
#8 /vendor/yiisoft/yii2/base/Event.php(312): call_user_func(Object(Closure), Object(craft\events\ModelEvent))
#9 /vendor/yiisoft/yii2/base/Component.php(642): yii\base\Event::trigger('craft\\elements\\...', 'afterSave', Object(craft\events\ModelEvent))
#10 /vendor/craftcms/cms/src/base/Element.php(5169): yii\base\Component->trigger('afterSave', Object(craft\events\ModelEvent))
#11 /vendor/craftcms/cms/src/elements/User.php(1833): craft\base\Element->afterSave(true)
#12 /vendor/craftcms/cms/src/services/Elements.php(3382): craft\elements\User->afterSave(true)
#13 /vendor/craftcms/cms/src/services/Elements.php(1097): craft\services\Elements->_saveElementInternal(Object(craft\elements\User), false, false, true, Array, false, false)
#14 /vendor/craftcms/cms/src/controllers/UsersController.php(1453): craft\services\Elements->saveElement(Object(craft\elements\User), false)
#15 [internal function]: craft\controllers\UsersController->actionSaveUser()
#16 /vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#17 /vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams(Array)
#18 /vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction('save-user', Array)
#19 /vendor/craftcms/cms/src/web/Application.php(305): yii\base\Module->runAction('users/save-user', Array)
#20 /vendor/craftcms/cms/src/web/Application.php(606): craft\web\Application->runAction('users/save-user', Array)
#21 /vendor/craftcms/cms/src/web/Application.php(284): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#22 /vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest(Object(craft\web\Request))
#23 /htdocs/index.php(26): yii\base\Application->run()
#24 {main}

It looks like it comes from the craftcms/webhooks plugin. FYI I'm using the version 3.0.5.

After checking this Payload Template :

{% set entry = event.sender %}
{% set fields = {
  photo: entry.photo.url ?? null,
  userPrimaryCategory_attendees: {
    id: entry.userPrimaryCategory_attendees.one().id ?? null,
    slug: entry.userPrimaryCategory_attendees.one().slug ?? null,
    title: entry.userPrimaryCategory_attendees.one().title ?? null
  }
} %}
{% for fieldLayoutField in entry.getFieldLayout().getFields() %}
  {% set field = craft.app.fields.getFieldById(fieldLayoutField.id) %}
  {% set fields = fields | merge({
    (field.handle): entry[field.handle].getContent() ??? entry[field.handle].value ??? entry[field.handle].one() ??? entry[field.handle] ?? null
  }) %}
{% endfor %}
{{
  {
    time: now | atom,
    user: currentUser ?? null,
    name: event.name,
    sender: entry,
    fields: fields
  } | json_encode | raw
}}

FYI this project was recently updated from Craft CMS 3 to 4.

It looks like entry.getFieldLayout().getFields() is causing this: what's the new appropriate way?

i-just commented 5 months ago

Thanks for all the info! craft\models\FieldLayout::getFields() has been renamed to getCustomFields().

There’s also getVisibleCustomFields(), which returns the visible custom fields included in the layout, taking conditions into account.

I hope this helps!