Skip to content

[PropertyAccess] Add nullsafe operator support #34483

@ogizanagi

Description

@ogizanagi

Description

Given an object graph foo.bar.baz, where bar is optional (can be null),
trying to call the property accessor with foo.bar.baz will throw a:

UnexpectedTypeException: PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path "foo.bar.baz" at property "baz".

In some use-cases, it'll be very handy to get null instead of this exception (e.g: in custom validation constraints using a property path set by the developper in annotations).

The flag introduced in #30545 allows to ignore exception on invalid property paths, but it works differently and has some drawbacks:

  • paths like foo.bak (non-existing property) will be considered as readable and return null. But foo.bar.baz would still throw the same exception.
  • it'll indeed hide potential mistakes in the property path. Which I'd like to avoid for this feature (bar must exist, but can be null).

Then I was about to suggest yet another flag for the PropertyAccessor ($throwOnNullValueInGraph?), but instead, I'm wondering if we shouldn't allow something mimicking the PHP nullsafe_calls RFC 👇

Example

Given an object graph foo.bar.baz, where bar is optional (can be null):

$propertyAccessor = PropertyAccess::createPropertyAccessor();

// Where class Foo has a `bar` property, and class Bar has a `baz` property, for which values are set by the constructors:
$full = new \stdClass();
$full->foo = new Foo(new Bar(new Baz()));

$propertyAccessor->getValue($full, 'foo.bar?.baz') // Would return the Baz instance

$noBar = new \stdClass();
$noBar->foo = new Foo(null);

$propertyAccessor->getValue($noBar, 'foo.bar?.baz') // Would return null

$noBak = new \stdClass();
$noBak->foo = new Foo(new Bar(new Baz()));

$propertyAccessor->getValue($noBak, 'foo.bak?.baz') // Would still throw a NoSuchPropertyException, as property `bak` does not exist in class `Foo`

This wouldn't change anything for writing, only for reading.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions