diff --git a/src/Type/Php/ArrayColumnHelper.php b/src/Type/Php/ArrayColumnHelper.php index 179d85bc04..0d9b5ea67d 100644 --- a/src/Type/Php/ArrayColumnHelper.php +++ b/src/Type/Php/ArrayColumnHelper.php @@ -147,7 +147,15 @@ private function getOffsetOrProperty(Type $type, Type $offsetOrProperty, Scope $ continue; } - $returnTypes[] = $type->getInstanceProperty($propertyName, $scope)->getReadableType(); + $property = $type->getInstanceProperty($propertyName, $scope); + if (!$property->isPublic()) { + if (!$type->hasMethod('__isset')->no() && !$type->hasMethod('__get')->no()) { + $returnTypes[] = new MixedType(); + } + continue; + } + + $returnTypes[] = $property->getReadableType(); } } diff --git a/tests/PHPStan/Analyser/nsrt/array-column.php b/tests/PHPStan/Analyser/nsrt/array-column.php index 4f830b96d9..bb79d0e790 100644 --- a/tests/PHPStan/Analyser/nsrt/array-column.php +++ b/tests/PHPStan/Analyser/nsrt/array-column.php @@ -244,11 +244,69 @@ public function testObjects2(array $array): void final class Foo { + public int $publicProperty; + protected int $protectedProperty; + private int $privateProperty; + + /** @param array $a */ + public function doFoo(array $a): void + { + assertType('array{}', array_column($a, 'nodeName')); + assertType('array{}', array_column($a, 'nodeName', 'tagName')); + assertType('list', array_column($a, 'publicProperty')); + assertType('array{}', array_column($a, 'protectedProperty')); + assertType('array{}', array_column($a, 'privateProperty')); + } + +} + + +class FooNotFinal +{ + + public int $publicProperty; + protected int $protectedProperty; + private int $privateProperty; + + /** @param array $a */ + public function doFoo(array $a): void + { + assertType('list', array_column($a, 'nodeName')); + assertType('array', array_column($a, 'nodeName', 'tagName')); + assertType('list', array_column($a, 'publicProperty')); + assertType('list', array_column($a, 'protectedProperty')); + assertType('list', array_column($a, 'privateProperty')); + } + +} + + +final class Magic +{ + + public int $publicProperty; + protected int $protectedProperty; + private int $privateProperty; + + public function __get($prop) + { + return $this->$prop; + } + + public function __isset($prop) : bool + { + return isset($this->$prop); + } + /** @param array $a */ public function doFoo(array $a): void { assertType('list', array_column($a, 'nodeName')); assertType('array', array_column($a, 'nodeName', 'tagName')); + assertType('list', array_column($a, 'publicProperty')); + assertType('list', array_column($a, 'protectedProperty')); + assertType('list', array_column($a, 'privateProperty')); } } +