Closed amacrobert-meq closed 3 months ago
This was already discussed in https://github.com/sonata-project/SonataAdminBundle/pull/6721 and https://github.com/sonata-project/SonataAdminBundle/pull/7066
// Use the model manager to get an entity other than Blog
$author = $modelManager->findOneBy(Author::class, ['id' => 1]);
is technically not the proper way to get another entity because you cannot be sure the entity is managed by the same entityManager behind the modelManager implementation.
I would recommend to use $yourEntityManager->findOneBy()
instead.
Also, a method-level template creates other issues as https://phpstan.org/r/f359d9d9-b98f-475e-9ec8-205070d14d0a.
Also, changing this, if it was decided as wanted, would be too little gain for too much work and there is not enought maintainer/contributor. So I'll close as not planned. Thanks for your understanding.
Environment
Sonata packages
show
``` $ composer show --latest 'sonata-project/*' Direct dependencies required in composer.json: sonata-project/admin-bundle 4.29.2 4.29.3 The missing Symfony Admin Generator sonata-project/doctrine-orm-admin-bundle 4.9.1 4.15.0 Integrate Doctrine ORM into the SonataAdminBundle sonata-project/entity-audit-bundle 1.11.0 1.16.1 Audit for Doctrine Entities Transitive dependencies not required in composer.json: sonata-project/block-bundle 5.1.0 5.1.0 Symfony SonataBlockBundle sonata-project/doctrine-extensions 1.18.1 2.3.0 Doctrine2 behavioral extensions sonata-project/exporter 3.3.0 3.3.0 Lightweight Exporter library sonata-project/form-extensions 1.20.0 2.3.0 Symfony form extensions sonata-project/twig-extensions 2.4.0 2.4.0 Sonata twig extensions ```
Symfony packages
show
``` $ composer show --latest 'symfony/*' Direct dependencies required in composer.json: symfony/browser-kit v5.4.31 v7.0.0 Simulates the behavior of a web browser, allowing you to make requ... symfony/console v5.4.34 v7.0.2 Eases the creation of beautiful and testable command line interfaces symfony/css-selector v5.4.26 v7.0.0 Converts CSS selectors to XPath expressions symfony/debug-bundle v4.4.37 v7.0.0 Provides a tight integration of the Symfony VarDumper component an... symfony/dotenv v5.4.34 v7.0.2 Registers environment variables from a .env file symfony/flex v1.21.4 v2.4.3 Composer plugin for Symfony symfony/framework-bundle v5.4.34 v7.0.2 Provides a tight integration between Symfony components and the Sy... symfony/mailer v5.4.34 v7.0.2 Helps sending emails symfony/maker-bundle v1.50.0 v1.52.0 Symfony Maker helps you create empty commands, controllers, form c... symfony/monolog-bundle v3.10.0 v3.10.0 Symfony MonologBundle symfony/phpunit-bridge v7.0.2 v7.0.2 Provides utilities for PHPUnit, especially user deprecation notice... symfony/process v5.4.34 v7.0.2 Executes commands in sub-processes symfony/runtime v5.4.26 v7.0.0 Enables decoupling PHP applications from global state symfony/security-bundle v5.4.34 v7.0.2 Provides a tight integration of the Security component into the Sy... symfony/serializer v5.4.34 v7.0.2 Handles serializing and deserializing data structures, including o... symfony/stopwatch v5.4.21 v7.0.0 Provides a way to profile code symfony/validator v5.4.34 v7.0.2 Provides tools to validate values symfony/var-dumper v5.4.29 v7.0.2 Provides mechanisms for walking through any arbitrary PHP variable symfony/web-profiler-bundle v5.4.34 v7.0.2 Provides a development tool that gives detailed information about ... symfony/yaml v5.4.31 v7.0.0 Loads and dumps YAML files Transitive dependencies not required in composer.json: symfony/asset v5.4.31 v7.0.0 Manages URL generation and versioning of web assets such as CSS st... symfony/cache v5.4.34 v7.0.2 Provides extended PSR-6, PSR-16 (and tags) implementations symfony/cache-contracts v2.5.2 v3.4.0 Generic abstractions related to caching symfony/config v5.4.31 v7.0.0 Helps you find, load, combine, autofill and validate configuration... symfony/dependency-injection v5.4.34 v7.0.2 Allows you to standardize and centralize the way objects are const... symfony/deprecation-contracts v3.4.0 v3.4.0 A generic function and convention to trigger deprecation notices symfony/doctrine-bridge v5.4.34 v7.0.2 Provides integration for Doctrine with various Symfony components symfony/dom-crawler v5.4.32 v7.0.0 Eases DOM navigation for HTML and XML documents symfony/error-handler v5.4.29 v7.0.0 Provides tools to manage errors and ease debugging PHP code symfony/event-dispatcher v5.4.34 v7.0.2 Provides tools that allow your application components to communica... symfony/event-dispatcher-contracts v3.4.0 v3.4.0 Generic abstractions related to dispatching event symfony/expression-language v5.4.21 v7.0.2 Provides an engine that can compile and evaluate expressions symfony/filesystem v5.4.25 v7.0.0 Provides basic utilities for the filesystem symfony/finder v5.4.27 v7.0.0 Finds files and directories via an intuitive fluent interface symfony/form v5.4.33 v7.0.1 Allows to easily create, process and reuse HTML forms symfony/http-client v5.4.34 v7.0.2 Provides powerful methods to fetch HTTP resources synchronously or... symfony/http-client-contracts v2.5.2 v3.4.0 Generic abstractions related to HTTP clients symfony/http-foundation v5.4.34 v7.0.0 Defines an object-oriented layer for the HTTP specification symfony/http-kernel v5.4.34 v7.0.2 Provides a structured process for converting a Request into a Resp... symfony/mime v5.4.26 v7.0.0 Allows manipulating MIME messages symfony/monolog-bridge v5.4.31 v7.0.0 Provides integration for Monolog with various Symfony components symfony/options-resolver v5.4.21 v7.0.0 Provides an improved replacement for the array_replace PHP function symfony/password-hasher v5.4.31 v7.0.0 Provides password hashing utilities symfony/polyfill-ctype v1.28.0 v1.28.0 Symfony polyfill for ctype functions symfony/polyfill-intl-grapheme v1.28.0 v1.28.0 Symfony polyfill for intl's grapheme_* functions symfony/polyfill-intl-icu v1.28.0 v1.28.0 Symfony polyfill for intl's ICU-related data and classes symfony/polyfill-intl-idn v1.28.0 v1.28.0 Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions symfony/polyfill-intl-normalizer v1.28.0 v1.28.0 Symfony polyfill for intl's Normalizer class and related functions symfony/polyfill-mbstring v1.28.0 v1.28.0 Symfony polyfill for the Mbstring extension symfony/polyfill-php72 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 7.2+ features to lower PHP v... symfony/polyfill-php73 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 7.3+ features to lower PHP v... symfony/polyfill-php80 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 8.0+ features to lower PHP v... symfony/polyfill-php81 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 8.1+ features to lower PHP v... symfony/property-access v5.4.26 v7.0.0 Provides functions to read and write from/to an object or array us... symfony/property-info v5.4.24 v7.0.0 Extracts information about PHP class' properties using metadata of... symfony/psr-http-message-bridge v2.3.1 v7.0.2 PSR HTTP message bridge symfony/routing v5.4.34 v7.0.2 Maps an HTTP request to a set of configuration variables symfony/security-acl v3.3.3 v3.3.3 Symfony Security Component - ACL (Access Control List) symfony/security-core v5.4.30 v7.0.1 Symfony Security Component - Core Library symfony/security-csrf v5.4.27 v7.0.1 Symfony Security Component - CSRF Library symfony/security-guard v5.4.27 v5.4.27 Symfony Security Component - Guard symfony/security-http v5.4.31 v7.0.1 Symfony Security Component - HTTP Integration symfony/service-contracts v2.5.2 v3.4.1 Generic abstractions related to writing services symfony/string v5.4.34 v7.0.2 Provides an object-oriented API to strings and deals with bytes, U... symfony/translation v5.4.31 v7.0.2 Provides tools to internationalize your application symfony/translation-contracts v2.5.2 v3.4.1 Generic abstractions related to translation symfony/twig-bridge v5.4.34 v7.0.2 Provides integration for Twig with various Symfony components symfony/twig-bundle v5.4.31 v7.0.0 Provides a tight integration of Twig into the Symfony full-stack f... symfony/var-exporter v6.4.2 v7.0.2 Allows exporting any serializable PHP data structure to plain PHP ... ```
PHP version
Subject
Summary
IDEs and static analyzers think that
$author
in this code is a Blog, not an Author:Detailed explanation
Sonata\AdminBundle\Model\ModelManagerInterface
declares a class-level generic typeT
:This type is an entity class used to restrict various parameters and return values of the class's methods. It is set when an admin's type is specified like so:
...which specifies
Sonata\AdminBundle\DependencyInjection\Admin\TaggedAdminInterface
's generic typeT
, which is used in its definition of the return value ofgetModelManager()
:That class-level type
T
for ModelManagerInterface is used for a number of methods, despite those methods being usable for any entity classes.For example, in an admin that
@extends AbstractAdmin<Blog>
, calling$this->getModelManager()->findOneBy(Author::class, ['id' => 1])
is expected to return aBlog
, but of course it returns anAuthor
.Minimal repository with the bug
https://github.com/amacrobert-meq/sonata-generic-type-example
Steps to reproduce
@extends AbstractAdmin<X>
whereX
is the entity the admin is for)$someOtherEntity = $this->getModelManager()->findOneBy(Y::class, []);
whereY
is an entity other than the admin's entityvendor/bin/phpstan
Expected results
PHPStan resolves with no errors.
Actual results
PHPStan errors with the following:
Suggested solution
The generic type
T
on ModelManagerInterface should not be class-level, but method-level.For example, this change would let IDEs and static analyzers know that the return value of
findBy(A::class, [])
is an array ofA
, without restricting the entity that is passed tofindBy()
.executeQuery()
because it is not passed a $class, but that's fine (and correct) because we do not know the query result type anyway.LockInterface
, which are informed by the implementation ofModelManagerInterface
.<T>
from anywhereModelManager<T>
is used inTaggedAdminInterface
.T
fromModelManagerInterface
's implementations insonata-project/doctrine-orm-admin-bundle
andsonata-project/doctrine-mongodb-admin-bundle