Problem/Motivation

Php 7.4 notice from function _field_write_instance at line 633 of field.crud.inc

Steps to reproduce

Under php 7.4 and when saving a content type's Manage Display page, I am getting
"Notice: Trying to access array offset on value of type null in _field_write_instance() (line 633 of .../modules/field/field.crud.inc)."

Proposed resolution

Changing line 633 to the following:
$display['module'] = isset($formatter_type['module']) ? $formatter_type['module'] : '';

The same approach has been implemented with $formatter['module'] at least at two other places:
https://www.drupal.org/project/drupal/issues/3085151
https://www.drupal.org/project/field_formatter_settings/issues/3166628

CommentFileSizeAuthor
#5 field-write-instance-notice-3314719-3.patch690 bytesarx-e

Issue fork drupal-3314719

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

arx-e created an issue. See original summary.

arx-e’s picture

Issue tags: +PHP 7.4
avpaderno’s picture

Title: Php 7.4 notice from function _field_write_instance in field.crud.inc » Notice: Trying to access array offset on value of type null in _field_write_instance()
arx-e’s picture

Issue summary: View changes
arx-e’s picture

StatusFileSize
new690 bytes
arx-e’s picture

Issue summary: View changes
poker10’s picture

Status: Active » Needs review
poker10’s picture

Thanks for the report and working on this. Do you know why the $formatter_type is NULL here? I read the comment added in #3085151: field_ui_display_overview_form() expects to always get an array from field_info_formatter_types() :

// For hidden fields, $formatter will be NULL, but we expect an array later.
// To maintain BC, but avoid PHP 7.4 Notices, ensure $formatter is an array
// with a 'module' element.

But this should not be the case here, as the code is checking if the field is not hidden.

  if ($display['type'] != 'hidden') {
    $formatter_type = field_info_formatter_types($display['type']);
    $display['module'] = $formatter_type['module'];
    $display['settings'] += field_info_formatter_settings($display['type']);
  }

Is there other usecase which was missed while fixing the #3085151?

Also the second question is, do we also need to fix the remaining usage of the $formatter_type['module'] in the field.info.class.inc?

https://git.drupalcode.org/project/drupal/-/blob/7.x/modules/field/field.info.class.inc#L628

arx-e’s picture

Well, I tried to look at what is causing this $formatter_type to be NULL (and I found out it was occurring only on one of the content types) but after deleting 4-5 unused and hidden fields the notice went away. The hidden fields I deleted were all term references using the same vocabulary and I tried to do it step by step but while the notices kept the same after the first deletions, at some point they stopped coming up.
I will need to get a backup of that version and reload it locally in order to try to find out.
For now I have no notices working with the unpatched version.

joseph.olstad’s picture

I'd say this is a safe change to make just my 2 cents. The migrate module fails testing anything higher than PHP 7.3.x.

https://www.drupal.org/pift-ci-job/2568554

migrate/tests/plugins/destinations/comment.test

This automated test has 10 failures Line 633 of modules/field/field.crud.inc:

Inside the automated test $migration->processImport(); is triggered also 10 times.

So it appears to be once per processImport() in the migrate test fail.

There's nothing obvious in the migrate processImport() or related migration that jumps out at me.

I think core should be able to handle if there's no module name defined.

This affects PHP 7.4, PHP 8.0, 8.1, 8.2 , the last PHP to not have an issue here was PHP 7.3.

check the automated tests for the migrate module.

This is the proverbial needle in the haystack. Not sure why PHP 7.3 has no issue here but 7.4+ does.

I just looked at the release notes for PHP 7.4, I don't see anything obvious, I searched for get_object_vars in the migrate module, also searched for get_declared_classes, both related to changes, nothing in the migrate module for this.

https://www.php.net/manual/en/migration74.php

the processImport failure in migrate ONLY fails when dealing with the comment.test , likely revolving around the comment module. The node imports using the same migration data do not have a failure.

joseph.olstad’s picture

ya this has something to do with hidden/disabled elements , somehow the comment test (relying on the core comment module) must have somewhere a hidden field maybe?
Anyhow, I'm just guessing at this point.

joseph.olstad’s picture

Found another contrib modue and another patch to entityreference that triggers this.

Same pattern, Succeeds on PHP 5.3, 5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3
fails on 7.4, 8.0, 8.1, 8.2 , same line in field.crud.inc

https://www.drupal.org/pift-ci-job/2572005

Entity Reference.EntityReferenceHandlersTestCase
	✗	
_field_write_instance

exception: [Warning] Line 617 of modules/field/field.crud.inc:
Trying to access array offset on value of type null

exception: [Warning] Line 617 of modules/field/field.crud.inc:
Trying to access array offset on value of type null

#1364802-42: Prevent reference self

joseph.olstad’s picture

avpaderno’s picture

Notice that Trying to access array offset on value of type null means, for example, accessing $formatter_type['module'] when $formatter_type is NULL.
I am not sure that setting $display['module'] to an empty string is much helpful, in that case. It could be helpful if it were be possible to set $display['module'] to a default module name, for example, for which invoking a hook would be later possible.

frazac’s picture

#5 does not work for me.

Still receiving the error on both remote production and dev server.

Warning: Trying to access array offset on value of type null in ctools_context_handler_get_render_handler() (line 68 of /home/.../sites/all/modules/ctools/includes/context-task-handler.inc).

Drupal 7.101
PHP 8.1.28

poker10’s picture

@frazac Not sure your warning is caused by the Drupal core, as it is in the ctools module. You can check a similar issue here: #1244434: Notice: Undefined index: handler type in ctools_context_handler_get_render_handler() (line 67, maybe it could help.

avpaderno’s picture

I think the patch is just hiding a bigger issue.
Why is $formatter_type NULL? If it is NULL, does continuing as nothing happened make sense?

avpaderno’s picture

As a side note, the line containing $display['module'] = $formatter_type['module']; is line 648, now.

avpaderno’s picture

Let's try to understand what exactly happens that makes $formatter_type set to NULL (or not initialized to a correct value).

The line causing that warning is contained in the following code.

$display += array(
  'label' => 'above',
  'type' => isset($field_type['default_formatter']) ? $field_type['default_formatter'] : 'hidden',
  'settings' => array(),
);
if ($display['type'] != 'hidden') {
  $formatter_type = field_info_formatter_types($display['type']);
  $display['module'] = $formatter_type['module'];
  $display['settings'] += field_info_formatter_settings($display['type']);
}

$formatter_type can be NULL because field_info_formatter_types() did not find information about the $field_type['default_formatter'] formatter or the cache used by _field_info_collate_types() got corrupted. (In the case $field_type['default_formatter'] is an empty string, field_info_formatter_types() would return an array with information about all the formatters and probably cause other issues.)
In both the cases, there is a bigger issue. At least, the code should log an error, since (apparently) not knowing the module that implements the formatter does not have any issue with saving the field data in the field configuration database.

avpaderno’s picture

I changed the code to the following one.

    if ($display['type'] != 'hidden') {
      $formatter_type = field_info_formatter_types($display['type']);
      if ($formatter_type) {
        $display['module'] = $formatter_type['module'];
        $display['settings'] += field_info_formatter_settings($display['type']);
      }
    }

The reason is that:

  • If the formatter has not been found, we do not know which module implements it. Leaving $formatter_type['module'] not set is probably the more correct way to say that.
  • If the formatter has not been found, field_info_formatter_settings() returns an empty array. Executing $display['settings'] += field_info_formatter_settings($display['type']); is perfectly useless, since $display['settings'] has been already initialized to an empty array.

Status: Needs review » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.