phpstan: False positives when using "method_exists" condition on interfaces

When variable is typed as interface and we use concrete implementation in code, sometimes there are valid calls to methods that doesn’t exist in interface. For example when using Symfony\Component\HttpFoundation\Session\SessionInterface and want to use getFlashBag method, this will trigger error in PHPStan (level 2):

/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
$session = $request->getSession();
if ($session && method_exists($session, 'getFlashBag')) {
    $session->getFlashBag()->add('success', 'False positive detected!');
}

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 3
  • Comments: 41 (26 by maintainers)

Commits related to this issue

Most upvoted comments

I have good news! I implemented support for method_exists: https://github.com/phpstan/phpstan/commit/69ef4b1f1f34fce1b2643cac126e962379663211 🎉

If you like PHPStan and use it to find bugs in your projects, I’d love if you supported it on Patreon. I have many ideas how to make PHPStan even smarter and faster but doing it over evenings and weekends is not sustainable longterm. I’m trying to make developing open-source a viable livelihood alternative. Even a $1 a month helps, but the more you contribute, the closer I am to my goal to work on it fulltime 😃

No one said it isn’t being considered, this issue is still open after all.

@Wirone Using method_exists is usually sign of bad design. Using instanceof is usually better, i.e.

$session = $request->getSession();
if ($session instanceof \Symfony\Component\HttpFoundation\Session\Session) {
    $session->getFlashBag()->add('success', 'False positive detected!');
}

If this behaviour would be configurable then i vote for yes.

Why would you want to configure this? If we add support for method_exists why would you want to disable this feature?

I’m having this same issue, with __toString we cannot rely on an interface, see https://github.com/getsentry/sentry-symfony/pull/145

Using method_exists is usually sign of bad design.

@JanTvrdik For project code, maybe. Not for library. Lot of Symfony bundles use method_exists to make BC tricks (if this method exist, then we are under Symfony 3.4, etc…)

I was first opposed to supporting and solving class_exists/method_exists/function_exists in PHPStan, but it’s a really common issue, so I’m gonna fix it. But in current state of PHPStan, it won’t be able to track it across scopes (check method_exists in one method, use it in a different method), but it will work for your example.