Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpstan Disallowed Calls Laravel Package

spaze/phpstan-disallowed-calls

PHPStan extension to define and enforce a denylist of disallowed function and method calls in your codebase. Catch legacy, unsafe, or unwanted APIs during static analysis with configurable rules and helpful error messages.

View on GitHub
Deep Wiki
Context7
v4.12.0

New

  • classPattern param directive matches a parameter's declared class name against a wildcard pattern using fnmatch() (#412, docs example #417)
  • allowInInstanceOf/disallowInInstanceOf now support fnmatch() wildcard patterns (#399, docs example #417) and param conditions (#401)
  • Param conditions also work with allowExceptIn/allowExceptInMethods and their disallowIn* aliases (#414)
  • allowExceptParamsAnywhere and disallowParamsAnywhere aliases for allowExceptParams/disallowParams to match other *Anywhere directives (#410)

Bugfixes

  • typeString: descriptive exception on parse failure (#407)
  • Empty string in typeString now throws an exception, and '0' (a string consisting of 0) is now a valid typeString (#409)
  • First-class callable syntax (func(...)) with param conditions is now handled correctly (#418)
  • allowExceptInFunctions/allowExceptInMethods with multiple entries only checked the first one, not anymore (#405)

Internal changes

  • Added CLAUDE.md (#403, export-ignored in #413)
  • export-ignore phpstan-dead-code-detector.php from release archives (#413)
v4.11.0

Allow or disallow classes/namespaces in param or return type hint positions (#392)

Applies only to disallowedNamespaces and disallowedClasses, the following configuration keys let you permit (or restrict) a class or namespace based on whether it appears as a parameter type hint or a return type hint in a function or method signature, and ban (or allow) using it elsewhere, for example in the method body.

  • allowInParamTypes: true
  • allowExceptInParamTypes: true (or the disallowInParamTypes alias)
  • allowInReturnType: true
  • allowExceptInReturnType: true (or the disallowInReturnType alias)

See the docs for examples.

Note: to enable usage in use imports use allowInUse: true.

Internal changes

  • Normalize PHPUnit PHP version requirements to X.Y.Z to eliminate test-runner warnings (#393, thanks @Copilot)
  • Rework allowInMethodsWithAttributes in signatures to use a node visitor (#395)
v4.10.0

Can disallow (some) keywords with disallowedKeywords, only global supported for now (#390)

parameters:
    disallowedKeywords:
        -
            keyword: 'global'
            allowIn:
                - 'legacy/*'
v4.9.2

This release includes a proper fix for the "defined in" checks originally fixed in 4.9.1. (#388)

As a necessary side effect, unknown functions (functions where their reflection is not available) won't be reported as disallowed anymore, if configured, by this extension as is the case with for example methods already.

v4.9.1
  • Short-cut "defined in" checks for built-in functions and methods (#384) (Now they're not flagged anymore)

Internal changes

  • Mention properties in README (#380) (Hmm, naming the extension "disallowed calls" wasn't as clever as I though back then)
  • Fix --prefer-lowest installs PHPStan 2.x instead of 1.x (#382, thanks @Copilot) Tests are now again running on PHPStan 1.x as well
v4.9.0

Naming is hard, so that's why this Disallowed Calls extension now supports disallowing instance and static properties, and enum properties with disallowProperties (#378)

Other (mostly) internal changes

  • Add generics to Generator (#372)
  • Handle all the include types in the switch (#373)
  • Upgrade Dead Code Detector (#375, thanks @janedbal)
  • Make the disallowedSuperglobals docs more clear that it doesn't recommend $_REQUEST (#377)

Oh, a Friday 13th release! 👻

v4.8.0

You can now also pass an array to errorTip in the config:

errorTip:
  - Tip 1
  - Tip 2

PHPStan will print al the tips, but please note that tips will be prefixed with , like this:

💡• a tip
• another one

  • Allow passing an array to errorTip (#367 #369, thanks @Copilot and myself 🤖)
  • Allow PHPUnit 13 (#368)
v4.7.1

Constants

  • Don't include template types in constant's declaring class display name, needed for PHPStan 2.1.38+ (#363)
  • Update the docs for constant usage in params (#364)

Tests

  • Run e2e tests on PHP 8.5 (#356, #359)
  • Analyze bin (#358)

Dependency updates

  • Bump actions/checkout from 5 to 6 (#357)
  • Upgrade shipmonk/dead-code-detector (#362)
v4.7.0

What's Changed

Internal changes

  • Update Dead Code Detector (#350)
  • Remove nikic/php-parser as a direct dev dependency (#347)
  • Support nikic/php-parser 5.6.1 in tests (#348)
  • Bump actions/checkout from 4 to 5 (#345)
  • Narrow the thrown type in docblock to void when no exception is thrown (#352)
v4.6.0

More and better tests

  • Automate end-to-end tests (#336, #339; want to add your repo to end-to-end tests, see below? Let me know!)
  • Run PHPStan on tests as well (#331)
  • Start using the Dead Code Detector (#332, #338, #333)
  • Test rule registration (#335)

Cleanup

  • Ignore PHPStan's ClassReflection::isEnum error when analyzing the extension code on PHP 7.4 (#324)
  • Don't add phpstan-ignore-errors.php into the package (#328)
  • Remove the extra config file leftovers (#334)
  • Remove the hasConstant check (#343)

What's an end-to-end test?

A test to ensure the extension still works where it was working before. The test checks out a configured repository, installs the latest version of the extension, then runs PHPStan.

v4.5.0

Allow excluding disallowed classes based on attribute (#319, thanks @morrislaptop)

If you disallow multiple classes or namespaces using an fnmatch wildcard, for example like this:

    disallowedClasses:
        -
            class: 'Foo\Bar\*Something'

... then there may be one or more classes that you'd like to exclude from all the *Something classes for some reason. Previously, starting with 2.15.0, you could exclude them by name using the exclude option:

            exclude:
                - 'Foo\Bar\NotThisSomething'

This release brings a new directive called excludeWithAttribute which you can also use to exclude items from the original set, but based on whether they have the specified attribute:

    disallowedClasses:
        -
            class: 'Foo\Bar\*Something'
            excludeWithAttribute:
                - 'MyApp\ThisAttribute'

Then if you have two classes like this:

namespace Foo\Bar;

class ThisSomething
{
}

#[\MyApp\ThisAttribute]
class ThatSomething
{
}

then only ThisSomething class would be disallowed.

excludeWithAttribute is supported for classes and namespaces for now, and supports fnmatch patterns.

Internal changes

  • Make tests green when running with zend.assertions=1 (#321)
v4.4.1

This is a follow-up to the allowInMethodsWithAttributes feature added in 4.3.1.

When you disallow the Event class (with disallowedClasses) and would like to allow it again in a method that has the Attr attribute (see the example code below), the Event class should be allowed even in the method signature. Previously, it was flagged as a disallowed usage (#315)

class Handler
{
    #[Attr]
    public function foo(Event $event) // should be allowed too
    {
        $event = new Event(); // allowed
    }
}
v4.4.0

What's Changed

  • You can now allow some items in instanceofs (allowInInstanceOf, allowExceptInInstanceOf, allowInUse directives, docs) (#306)
  • Full allow* support for all items (previously constants, superglobals and control structures didn't support for example allowInMethods etc.) (#310)
  • The extension can now be tested with PHPUnit 12.x (#309)

If this extension helps you write better code you can sponsor a release or buy me a 🍻 or a 🍰, thanks!

v4.3.1

This bugfix release includes a better detection of disallowed attributes reallowed in a method with attributes (#304)


The original 4.3.0 release notes:

This release has been sponsored by @ticketswap & @ruudk, thank you 🍰

Re-allow in class with/by attributes (#296, #298)

So far, when you wanted to re-allow a disallowed function or a method, or specifically disallow them, you could use:

  • an allowIn path to specify a path or a filename where the function or method could be called without generating an error
  • or allowInMethods (or the allowInFunctions alias) to specify functions and methods in which the disallowed function would be allowed
  • you could also use the companion directives disallowIn or disallowInMethods (or the allowExceptIn[...] aliases) if you wanted to list paths or methods in which the call is explicitly disallowed

Starting with this release, you can use attributes to sort of mark functions and methods in which the disallowed call would be allowed (or explicitly disallowed):

  • use allowInClassWithAttributes to allow for example a method in a class that has a specified class attribute
  • use allowInMethodsWithAttributes (or the disallowInFunctionsWithAttributes alias) to allow the call in methods (or function) with the given method attribute (or a function attribute)
  • use allowInClassWithMethodAttributes to allow a call in a class where any method has the attribute, where "any method" includes any other method as well, static or not, public, private, or protected
  • you can also use the disallowIn[...] counterparts (with allowExceptIn[...] aliases) to specify only classes and methods in which the call should be disallowed

This allows you to create rules that do not depend on paths or method names, and can be useful if you're working with frameworks or libs that already use attributes. You can specify multiple items in the directives above and only one of them needs to match (it's not an AND list, more like OR list) and they all support fnmatch patterns.

Other minor changes

  • More callable param tests for a bugfix in the previous release (#295)
  • Call fnmatch less often only when needed (#297)
  • Tweak attribute example in the disallowedAttributes docs (#299, thanks @ruudk)

You too can sponsor a release or buy me a 🍻 or a 🍰, thanks!

v4.3.0

This release has been sponsored by @ticketswap & @ruudk, thank you 🍰

Re-allow in class with/by attributes (#296, #298)

So far, when you wanted to re-allow a disallowed function or a method, or specifically disallow them, you could use:

  • an allowIn path to specify a path or a filename where the function or method could be called without generating an error
  • or allowInMethods (or the allowInFunctions alias) to specify functions and methods in which the disallowed function would be allowed
  • you could also use the companion directives disallowIn or disallowInMethods (or the allowExceptIn[...] aliases) if you wanted to list paths or methods in which the call is explicitly disallowed

Starting with this release, you can use attributes to sort of mark functions and methods in which the disallowed call would be allowed (or explicitly disallowed):

  • use allowInClassWithAttributes to allow for example a method in a class that has a specified class attribute
  • use allowInMethodsWithAttributes (or the disallowInFunctionsWithAttributes alias) to allow the call in methods (or function) with the given method attribute (or a function attribute)
  • use allowInClassWithMethodAttributes to allow a call in a class where any method has the attribute, where "any method" includes any other method as well, static or not, public, private, or protected
  • you can also use the disallowIn[...] counterparts (with allowExceptIn[...] aliases) to specify only classes and methods in which the call should be disallowed

This allows you to create rules that do not depend on paths or method names, and can be useful if you're working with frameworks or libs that already use attributes. You can specify multiple items in the directives above and only one of them needs to match (it's not an AND list, more like OR list) and they all support fnmatch patterns.

Other minor changes

  • More callable param tests for a bugfix in the previous release (#295)
  • Call fnmatch less often only when needed (#297)
  • Tweak attribute example in the disallowedAttributes docs (#299, thanks @ruudk)

You too can sponsor a release or buy me a 🍻 or a 🍰, thanks!

v4.2.1

What's Changed

  • Check just one callable parameter variant (#293) this fixes a rather rare regression introduced in 4.1.1.
v4.2.0

What's new

  • Can disallow isset() in disallowedFunctionCalls (#289, thanks @ksaveras!)
  • Can disallow unset, too (#291)

Internal change

  • array_merge arrays with error messages only when not empty, this should speed things up a bit, maybe (#287)
v4.1.1

This version replaces 4.1.0 in which callables were not detected in constructors. The notes below are taken from 4.1.0.

This release adds new detections listed below, meaning it's possible that you'll see new error messages.

First class callable syntax (#279), for example:

$func = print_r(...);

Dynamic calls (#276, #278), for example:

$func('foo');
$object->$method();

Test anonymous class usages (#277), for example:

$foo = new class implements ...
$foo = new class extends ...

Anonymous class usages (when the anonymous class extends DisallowedClass for example) were detected before, however the detection is now tested.

Detect callable parameters (#281, #283, #285), for example:

array_map('function', []);
array_map([$object, 'method'], []);
array_map([Class::class, 'staticMethod']);
v4.1.0

This release has been replaced by 4.1.1 which also detects callables in constructors, unlike this version.

v4.0.1

The 4.0 release removed support for PHPStan 1.x, and this release brings it back. Both PHPStan 1.12 and PHPStan 2.0 are supported (#273).

You can learn more about PHPStan 2.0 in the release notes or in the blog post and don't forget to get yourself an elephpant and a t-shirt!

v4.0.0

This major release supports and requires PHPStan 2.0 (#267) (update: the 4.0.1 release adds back support for PHPStan 1.12)

As mentioned in the UPGRADING.md guide:

It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code.

You can learn more about PHPStan 2.0 in the release notes or in the blog post and don't forget to get yourself an elephpant and a t-shirt!

v3.5.1
  • Support PHP 8.4 (#270)

That's it. That's the release.

v3.5.0
  • Add create_function as a disallowed function call (#261, thanks @BackEndTea)
  • Process ClassConstFetch where $class is Name only for enums to correctly support PHPStan 1.12.6 (#266)

Internal changes:

  • Add phpstan/phpstan-deprecation-rules in expectation of PHPStan 2.0 (#263)
  • Fix test class name (#260, spotted by @szepeviktor, thanks)
v3.4.0
  • Add default error identifiers, used if not specified/overridden in your custom config (#258)

PHPStan 1.11 added error identifiers and while they were supported by this extension for quite some time (since #97), they were not added by default, only when you've specified them.

This release adds error identifiers everywhere, and they'll be used if you don't specify custom identifiers in your custom config. The full list of identifiers is in the ErrorIdentifiers class here https://github.com/spaze/phpstan-disallowed-calls/blob/main/src/RuleErrors/ErrorIdentifiers.php and they have a disallowed.something format.

v3.3.0
  • Can disallow control structures like else, elseif, goto (#257)

Checking params inside ( ... ) doesn't work at the moment, so you can disallow all declare() constructs but can't re-allow e.g. declare(strict-types = 1).

If you try to disallow else if with the space, an exception will be thrown, because else if is parsed as else followed by if, so disallowing else if with the space wouldn't have the desired effect and the result would be unexpected. Disallow elseif, or don't write else if in your code 😇

v3.2.0

Add phpinfo() to dangerous calls config (#255)

See

for reasons why (phpinfo() echoes cookie values like the session id, which may then be stolen with XSS for example, bypassing HttpOnly cookie flag), and use https://github.com/spaze/phpinfo instead of just calling phpinfo().

Internal changes

  • It's already a list, no need to call array_values() (#253, this is a new bleeding edge rule added in PHPStan 1.10.59)
  • Update dev dependencies (#254)
v3.1.2
  • Hardcode ENT_QUOTES as int 3 in disallowed-loose-calls.neon config (#250)
  • Run tests every day to assure compatibility (#251)
v3.1.1

What's Changed

  • Support dynamic class constant fetch available in PHP 8.3 (#242, #248)
  • Added disallowedEnums, they use DisallowedConstant internally (#243, docs)

Internal changes:

  • The PHP 8.0 polyfill is not needed anymore (#237)
  • More tests for attributes (#240) and on more PHP versions (#244)
  • More strict/correct config schema, disallowedConstants' constant field is always present (#245)
  • Reuse the existing reflection variable (#246)

Note

The 3.1.0 release was the same minus #248.

v3.0.0

New major version because some major new features in this release, and some potential backwards compatibility breaks, if you use the extension in one way or another, all described below.

New features

  • Can specify params with a doctype in typeString config option (#234) You can now specify dis/allowed parameter values as PHPDoc string like typeString: 'foo'|'bar' or typeString: 'array{}' etc. instead of just value: scalar
  • Support more attribute targets: properties, class constants, params (#225) Disallowed attributes will now be also reported when used on/with those.

Changed

  • No "because reasons", because reasons (#221) (Possible backwards compatibility break, if you ignore error messages in your config) Previously, if there was no message key in the disallowed configuration, "because reasons" was added automatically. I thought it was funny back when this was an internal extension only, but maybe it's not anymore. So there's no "because reasons" anymore, and the error message will always end with a full stop ., unless it already ends with one, or unless it ends with ? or !.
  • Define extension parameters as a structure (#222, #231 and a follow-up in #229 thanks to @francescolaffi) (Possible BC break, if you have a typo in your config, you may suddenly be alerted about it) Bye typos, at least some of them.
  • Can add more rules for the same call to have different messages for various params (#232) (Possible BC break if you for some reason relied on the order of the rules for the same function or method)
  • The allowExceptParamsInAllowed description in docs was flipped around (#235)

Internal test changes

  • Use the DI container in tests (#223, #228)
  • Merge test libs dir into src (#227)
  • Rename attribute tests and drop ClassWithAttributesAllow (#230)
v2.16.1

What's Changed

  • Support PHP 8.3 (#217)
  • Bump actions/checkout from 3 to 4 (#218)

Did you know you can use @dependabot to update your actions, not just your code? I've updated my article which mentions Dependabot https://www.michalspacek.com/dont-let-security-bugs-catch-you-off-guard#github-dependabot

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dualmedia/log-bundle
codyas/spreadsheet-bundle
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/opensearch-client
directorytree/opensearch-adapter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php