Skip to content

Issue on associative array #15

Closed

Description

@mitelg

I am not sure, why this happens. it seems, that the array shape defined as return type is not matching what is really returned. but the hint is not really pointing to the right place, I guess 🤔

see https://github.com/shopware/shopware/blob/trunk/src/Core/Framework/DataAbstractionLayer/AttributeEntityCompiler.php#L219

PHP Fatal error: Uncaught TypePHP\Exception\TypeError: Shopware\Core\Framework\DataAbstractionLayer\AttributeEntityCompiler::parseField(): Return value must be of type (array{type: string, name: string, class: class-string<Shopware\Core\Framework\DataAbstractionLayer\Field\Field>, flags: array<string, array{class: string, args?: (array<string, (string | bool | float | null)> | list)}>, translated: bool, args: list<(string | int | false)>} | null), associative array (key 'type') returned in /home/runner/work/shopware/shopware/src/Core/Framework/DataAbstractionLayer/AttributeEntityCompiler.php:237

Activity

  1. added a commit that references this issue on Aug 11, 2026
  2. rcalicdan commented on Aug 11, 2026

    @rcalicdan
    Member

    Hi @mitelg

    TypePHP actually caught a genuine type contract discrepancy in Shopware Core's AttributeEntityCompiler.php!

    The Discrepancy in Shopware

    In AttributeEntityCompiler.php, the @phpstan-type FieldArray annotation promises that args is a list<string|int|false>:

    /**
     * @phpstan-type FieldArray array{
     *     ...
     *     args: list<string|int|false>
     * }
     */

    However, at runtime, when parseField() compiles an ENUM field, getFieldArgs() returns $this->getFirstEnumCase($property), which evaluates to a \BackedEnum object:

    $field->type === FieldType::ENUM => [$column, $property->getName(), $this->getFirstEnumCase($property)]

    Because \BackedEnum is an object (not string, int, or false), TypePHP correctly flagged the return value as a contract violation at runtime!

    To fix the type contract in Shopware Core, FieldArray should be updated to include \BackedEnum:

    /**
     * @phpstan-type FieldArray array{
     *     ...
     *     args: list<string|int|false|\BackedEnum>
     * }
     */

    Error Path Improvement in TypePHP

    You were also completely right that the error hint wasn't pointing to the exact nested key!

    When a Union type (like FieldArray | null) failed, TypePHP previously swallowed inner structural errors and returned a generic top-level error (must be of type (array{...} | null)).

    I have enhanced the UnionValidator so that when a nested shape or list fails inside a Union/Nullable type, TypePHP surfaces the exact failing key path instead of the generic union message:

    TypeError: Shopware\Core\Framework\DataAbstractionLayer\AttributeEntityCompiler::parseField(): Return value['args'][2] must be of type (string | int | false), object (Shopware\...\StatusEnum) returned
    

    This error path enhancement, along with the fix for issue #14, and has been release in v0.2.2 minor fix and pr #17 . Thank you for reporting this!..

    please update your composer dep on the library, and if you have any more problem dont hesitate to submit more issue and this way we can help each other..

  3. mitelg commented on Aug 12, 2026

    @mitelg
    Author

    ah nice! very cool to catch the first issue 😁 will update today!

  4. rcalicdan commented on Aug 12, 2026

    @rcalicdan
    Member

    @mitelg Btw looking at this pr ci check: https://github.com/shopware/shopware/actions/runs/31465546940/job/93697692190?pr=19140
    as well as in other acceptance check, Typephp caught a genuine doctype lie, if you want this to be resolve, it should be either be resolve at its root cause and update the annotation or use @typephp-ignore in methods to prevent typephp from enforcing the doctype, cheers..

    Exception

    ​php TypePHP\Exception\TypeError {#38858 #message: "Variable $bundles[FrameworkBundle] must be a class-string of Shopware\Core\Framework\Bundle, 'Symfony\Bundle\FrameworkBundle\FrameworkBundle' given" #code: 0 #file: "./src/Core/Framework/DependencyInjection/CompilerPass/AssetBundleRegistrationCompilerPass.php" #line: 19 } ​

    Stack Trace

    1. AssetBundleRegistrationCompilerPass.php:19
       Shopware\Core\Framework\DependencyInjection\CompilerPass\AssetBundleRegistrationCompilerPass->process(ContainerBuilder $container): void
       // @phpstan-ignore varTag.type (ReflectionClass requires a class-string, but the bundles are already validated strings)
       $bundles = $container->getParameter('kernel.bundles');
    1. vendor/symfony/dependency-injection/Compiler/Compiler.php:73
    2. vendor/symfony/dependency-injection/ContainerBuilder.php:825
    3. vendor/symfony/http-kernel/Kernel.php:516
    4. vendor/symfony/http-kernel/Kernel.php:762
    5. vendor/symfony/http-kernel/Kernel.php:122
    6. src/Core/Kernel.php:156
    7. bin/shopware:60
    8. vendor/autoload_runtime.php:27
    9. bin/shopware:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions