{"id":15017575,"url":"https://github.com/vkcom/modulite-phpstan","last_synced_at":"2025-06-12T12:39:39.340Z","repository":{"id":63565155,"uuid":"568457505","full_name":"VKCOM/modulite-phpstan","owner":"VKCOM","description":"Bring modules into PHP and PHPStan","archived":false,"fork":false,"pushed_at":"2024-08-30T18:56:14.000Z","size":345,"stargazers_count":13,"open_issues_count":8,"forks_count":3,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-01-29T18:45:44.538Z","etag":null,"topics":["modules","modulite","php","phpstan"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VKCOM.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-20T15:41:46.000Z","updated_at":"2024-06-26T11:47:03.000Z","dependencies_parsed_at":"2024-02-07T02:15:12.236Z","dependency_job_id":null,"html_url":"https://github.com/VKCOM/modulite-phpstan","commit_stats":{"total_commits":4,"total_committers":2,"mean_commits":2.0,"dds":0.25,"last_synced_commit":"4d50e14c589514f442bbf8182f88ba6d575a673c"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VKCOM%2Fmodulite-phpstan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VKCOM%2Fmodulite-phpstan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VKCOM%2Fmodulite-phpstan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VKCOM%2Fmodulite-phpstan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VKCOM","download_url":"https://codeload.github.com/VKCOM/modulite-phpstan/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237152846,"owners_count":19263793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["modules","modulite","php","phpstan"],"created_at":"2024-09-24T19:50:42.194Z","updated_at":"2025-02-04T16:31:21.543Z","avatar_url":"https://github.com/VKCOM.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Modulite plugin for PHPStan\n\nModulite is a conception that **brings modules into the PHP language**.\nPHP does not have native modules (internal classes, private namespaces, explicit exports), \nand Modulite tries to eliminate this drawback.\n\nActually, all \"modularity\" is represented as `.modulite.yaml` files, which declare exports and requires. \nThere is a PHPStorm plugin that deeply integrates into an IDE, visualizes yaml config and provides actions to modify it.\n\nThis PHPStan plugin reads `.modulite.yaml` files and fires errors if your code breaks modularity. \nThat allows you to check a whole project in Git hooks, in CI, etc.\n\n**Tip**. If you are unfamiliar with Modulite, consider a [PHPStorm plugin](https://github.com/VKCOM/modulite)\nand a [landing page (in Russian)](https://vkcom.github.io/modulite/).\n\n\n## Installation and configuration\n\nTo install, just use Composer:\n```bash\ncomposer require --dev vkcom/modulite-phpstan\n```\n\nAfter installing, include the plugin in your `phpstan.neon` and pass 2 parameters:\n```\nparameters:\n    modulite:\n        projectRoot: path    # project root is where composer.json/composer.lock/vendor exist\n        srcRoot: path        # typically, projectRoot/src ; .modulite.yaml files will be searched recursively\n\nincludes:\n    - vendor/vkcom/modulite-phpstan/extension.neon\n```\n\n\n## Example project\n\nClone [modulite-example-project](https://github.com/VKCOM/modulite-example-project), run `composer install`, \nrun `vendor/bin/phpstan analyze`, and see some errors. \n\nThe example intentionally contains some errors :) Also, it describes several steps of making its code perfect.\n\n\u003cimg alt=\"screen-err-phpstan\" src=\"docs/img/screen-err-phpstan.png\" width=\"700\"\u003e\n\nYou can use Modulite while developing Composer packages, too. Moreover, you can control which symbols\nare exported from your package. That ability is covered in [documentation](https://github.com/VKCOM/modulite).\n\n\n## How the plugin works\n\nAs expected, *modulite-phpstan* analyzes function calls, class usages, PHPDocs, etc., \nand ensures that your code fits `export`, `require`, and other Modulite rules.\n\nWe advise you to use PHPStorm while development, because PHPStorm's plugin smoothly integrates into an IDE,\nproducing `.modulite.yaml` files, which are analyzed by *modulite-phpstan*.\n\nTypically, a project structure is the following:\n```text\nmy_project/     # projectRoot\n    src/        # srcRoot\n    tests/\n    vendor/\n    composer.json\n```\n\nWhen PHPStan starts analyzing your code, this plugin \n* locates all `.modulite.yaml` inside `{srcRoot}` \n* locates all `.modulite.yaml` and `composer.json` files inside `{projectRoot}/vendor`\n\nThe plugin has to scan `vendor`, because Composer packages are also checked to be required, etc.\nMoreover, a package can also be developed using Modulite and contain private symbols, \nso when embedded into your project, the plugin would check against their usages also.\n\nModulite files are parsed, resolved and validated once PHPStan runs. \nIn case they contain no errors, all modularity checks will be performed. \nOtherwise, yaml errors are dumped and no checks are performed.\n\n\n## Composer packages outside vendor dir\n\nIn rare situations, you may be developing Composer packages locally, in the same repo. \nBeing installed to `vendor`, they are just symlinked:\n```text\nmy_project/     # projectRoot\n    src/        # srcRoot\n    packages/   # additionalPackagesRoot\n        utils-common/\n            src/\n            composer.json\n    tests/\n    vendor/\n        doctrine/\n        phpstan/\n        utils/\n            common/   (symlink to packages/utils-common)\n    composer.json     (contains \"repositories\" type \"path\" into packages/*)\n```\n\nIn such cases, PHPStan's internal reflection discovers some classes in `packages/`, which are expected to be in `vendor/`\nfrom the Modulite's point of view. Without additional hints, Modulite will produce errors, thinking `vendor/` uses\nfiles out of scope. \n\nTo overcome this problem, pass `additionalPackagesRoot` parameter besides `srcRoot`. \nThen *modulite-phpstan* will also scan that directory and create necessary path mappings.\n\n\n## A sad note about PHPStan cache\n\nIf a PHP file is unchanged, PHPStan doesn't run analysis within it. It caches files state and errors, and just dumps them out, it analyzes only diff and changed dependencies.\n\nAs appears from the above,\n* when PHP code is unchanged, but `.modulite.yaml` files are changed via PHPStorm plugin, no checks will be run\n* when bits of PHP code are changed and `.modulite.yaml` files are changed also, PHPStan will run checks only for changed files, and dump previous (cached) errors for unchanged files, though unchanged files may contain no errors after yaml modification\n\nFor now, a 100% working advice is to clear cache from time to time:\n```bash\nvendor/bin/phpstan clear-result-cache\n```\n\nThat will make PHPStan analyze a whole project, and the plugin will work as expected.\n\nProbably, this may be fixed using some deep knowledge of PHPStan cache internals, how to embed into it and how to tell PHPStan about PHP\u003c-\u003eyaml interconnection. If you are experienced in writing plugins, give a suggestion in [this issue](https://github.com/VKCOM/modulite-phpstan/issues/1).\n\n\n## Limitations\n\n* If you have unexpected behavior, try clearing PHPStan cache (a section above).\n* `vendor/` dir is scanned recursively every run, which may take noticeable time; this can be improved, vote for [this issue](https://github.com/VKCOM/modulite-phpstan/issues/2).\n* `projectRoot` and `srcRoot` parameters are required, but probably, they may be calculated automatically; if you are experienced in writing plugins, add a comment for [this issue](https://github.com/VKCOM/modulite-phpstan/issues/3).\n* Only static method calls are analyzed, `$obj-\u003emethod()` are not, that's why instance methods can't be added to `force-internal`. It's intentional, because static calls are resolved unambiguously, whereas instance calls rely on type inferring, which would certainly differ between IDE and PHPStan; static calls and class usages are more than enough, actually. \n\n\n## Contributing notes\n\nKeep in mind, that all logic of Modulite behavior must be equal in 3 places:\n* Modulite in [PHPStorm](https://github.com/VKCOM/modulite); checks are represented as IDEA inspections, symbols resolving also rely on PHPStorm internals.\n* Modulite in PHPStan (this repo).\n* Modulite in [KPHP](https://github.com/VKCOM/kphp); KPHP is a PHP compiler invented in VK; moreover, initial implementation of modules was made for KPHP+PHPStorm combination, and later the same logic was exposed as a PHPStan plugin to be used in regular PHP projects; lots of code related to yaml validation and rules checking are ported from the C++ implementation and must be kept in sync with KPHP, to remain sustainable.\n\nIf you find a bug, it's either a specific bug related to PHPStan peculiarities, or it may be a bug that also exists in other implementations and should be fixed simultaneously. If you have a feature request, it must be implemented in three repos at the same time, covered with the same tests, also. So, feel free to file issues, we'll find a way to manage them.\n\nIf you are experienced in PHPStan internals, and you have some advices to make this plugin more canonical, we'd be glad to see your comments and PRs.\n\n\n## Ask questions and provide feedback\n\nThis plugin was developed by the KPHP Team at VK.com.\n\nTo communicate with our community, use GitHub issues or a [Telegram chat](https://t.me/kphp_chat).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvkcom%2Fmodulite-phpstan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvkcom%2Fmodulite-phpstan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvkcom%2Fmodulite-phpstan/lists"}