craftcms / cms

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

[4.x]: Calling unknown method: craft\models\FieldLayout::getFields() #11465

Closed ezawadzki closed 2 years ago

ezawadzki commented 2 years ago

What happened?

Description

I Implemented my own exporter in craft 3.7. In Craft 4.0.4, this is not working anymore.

Steps to reproduce

<?php

namespace customexporter;

use Craft;
use craft\assets\id;
use craft\base\EagerLoadingFieldInterface;
use craft\base\ElementExporter;
use craft\elements\db\ElementQuery;
use craft\elements\db\ElementQueryInterface;

class Exporter extends ElementExporter
{
    /**
     * @inheritdoc
     */
    public static function displayName(): string
    {
        return 'Bright exporter';
    }

    /**
     * @inheritdoc
     */
    public function export(ElementQueryInterface $query): array
    {
        // Eager-load as much as we can
        $eagerLoadableFields = [];
        foreach (Craft::$app->getFields()->getAllFields() as $field) {
            if ($field instanceof EagerLoadingFieldInterface) {
                $eagerLoadableFields[] = $field->handle;
            }
        }

        $data = [];

        /** @var ElementQuery $query */
        $query->with($eagerLoadableFields);

        foreach ($query->each() as $element) {
            // Get the basic array representation excluding custom fields
            $attributes = array_flip($element->attributes());
            if (($fieldLayout = $element->getFieldLayout()) !== null) {
                foreach ($fieldLayout->getFields() as $field) {
                    unset($attributes[$field->handle]);
                }
            }

....

Expected behavior

It sould export a json file though admin interface.

Actual behavior

Got this error on last loop on $fieldLayout->getFields():

2022-06-20 14:11:58 [web.ERROR] [yii\base\UnknownMethodException] yii\base\UnknownMethodException: Calling unknown method: craft\models\FieldLayout::getFields() in /var/www/project/cms/vendor/yiisoft/yii2/base/Component.php:300
Stack trace:
#0 /var/www/project/cms/modules/customexporter/src/Exporter.php(45): yii\base\Component->__call('getFields', Array)
#1 /var/www/project/cms/vendor/craftcms/cms/src/controllers/ElementIndexesController.php(320): customexporter\Exporter->export(Object(craft\elements\db\EntryQuery))
#2 [internal function]: craft\controllers\ElementIndexesController->actionExport()
#3 /var/www/project/cms/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#4 /var/www/project/cms/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams(Array)
#5 /var/www/project/cms/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction('export', Array)
#6 /var/www/project/cms/vendor/craftcms/cms/src/web/Application.php(301): yii\base\Module->runAction('element-indexes...', Array)
#7 /var/www/project/cms/vendor/craftcms/cms/src/web/Application.php(625): craft\web\Application->runAction('element-indexes...', Array)
#8 /var/www/project/cms/vendor/craftcms/cms/src/web/Application.php(280): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#9 /var/www/project/cms/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest(Object(craft\web\Request))
#10 /var/www/project/cms/web/index.php(22): yii\base\Application->run()
#11 {main} {"memory":10129296,"exception":"[object] (yii\\base\\UnknownMethodException(code: 0): Calling unknown method: craft\\models\\FieldLayout::getFields() at /var/www/project/cms/vendor/yiisoft/yii2/base/Component.php:300)"} 
2022-06-20 14:11:58 [web.INFO] [application] Request context:
$_GET = [
    'p' => 'admin/actions/element-indexes/export'
    'site' => 'stBase'
]

Thanks for your help

Craft CMS version

4.0.4

PHP version

8.0.13

Operating system and version

Linux 657e222112ab 5.10.0-0.bpo.9-amd64 #1 SMP Debian 5.10.70-1~bpo10+1 (2021-10-10) x86_64 Linux

Database type and version

Postgres 13.4

Image driver and version

Docker Image : nystudio107/php-prod-base:8.0-alpine

Installed plugins and versions

No response

brandonkelly commented 2 years ago

craft\models\FieldLayout::getFields() was renamed to getCustomFields() in Craft 4.0.0 (mentioned in the release notes).

ezawadzki commented 2 years ago

Hi @brandonkelly thanks for quick answer. I replaced getFields by getCustomFields. I got this error :

2022-06-21 09:45:17 [web.ERROR] [Exception] Exception: Property [customFields] does not exist on this collection instance. in /var/www/project/cms/vendor/illuminate/collections/Traits/EnumeratesValues.php:982
Stack trace:
#0 /var/www/project/cms/modules/customexporter/src/Exporter.php(62): Illuminate\Support\Collection->__get('customFields')
#1 /var/www/project/cms/vendor/craftcms/cms/src/controllers/ElementIndexesController.php(320): customexporter\Exporter->export(Object(craft\elements\db\EntryQuery))
#2 [internal function]: craft\controllers\ElementIndexesController->actionExport()
#3 /var/www/project/cms/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#4 /var/www/project/cms/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams(Array)
#5 /var/www/project/cms/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction('export', Array)
#6 /var/www/project/cms/vendor/craftcms/cms/src/web/Application.php(301): yii\base\Module->runAction('element-indexes...', Array)
#7 /var/www/project/cms/vendor/craftcms/cms/src/web/Application.php(625): craft\web\Application->runAction('element-indexes...', Array)
#8 /var/www/project/cms/vendor/craftcms/cms/src/web/Application.php(280): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#9 /var/www/project/cms/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest(Object(craft\web\Request))
#10 /var/www/project/cms/web/index.php(22): yii\base\Application->run()
#11 {main} {"memory":10202896,"exception":"[object] (Exception(code: 0): Property [customFields] does not exist on this collection instance. at /var/www/project/cms/vendor/illuminate/collections/Traits/EnumeratesValues.php:982)"} 
2022-06-21 09:45:17 [web.INFO] [application] Request context:
$_GET = [
    'p' => 'admin/actions/element-indexes/export'
    'site' => 'stBase'
]
brandonkelly commented 2 years ago

What’s happening at modules/customexporter/src/Exporter.php line 62?

ezawadzki commented 2 years ago

The new issue is because in Craft 3.7, when I was looping on all fields values of my entry with:

$value = $element->getFieldValue($field->handle);

I called customFields property on craft\elements\db\MatrixBlockQuery, like this : $value->customFields

In Craft 4, craft\elements\db\MatrixBlockQuery becomes Illuminate\Support\Collection. That's why it craches.

brandonkelly commented 2 years ago

In Craft 4, craft\elements\db\MatrixBlockQuery becomes Illuminate\Support\Collection. That's why it craches.

Not really sure what you mean by that. When you call $element->getFieldValue($field->handle) (or $element->myFieldHandle) for a Matrix field, a craft\elements\db\MatrixBlockQuery object will be returned in both Craft 3 and 4. The only case where Craft 4 differs is if field was eager-loaded, in which case:

In either case, you would not be able to do $value->customFields directly from the resulting field value.