PHPackages                             happenv-com/laravel-true-modular-phpstan - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. happenv-com/laravel-true-modular-phpstan

ActivePhpstan-extension[Testing &amp; Quality](/categories/testing)

happenv-com/laravel-true-modular-phpstan
========================================

PHPStan extensions for laravel-true-modular: dynamic Eloquent relation resolution and module boundary enforcement.

0.x-dev(today)00MITPHPPHP ^8.3CI passing

Since Jun 27Pushed todayCompare

[ Source](https://github.com/happenv-com/laravel-true-modular-phpstan)[ Packagist](https://packagist.org/packages/happenv-com/laravel-true-modular-phpstan)[ RSS](/packages/happenv-com-laravel-true-modular-phpstan/feed)WikiDiscussions 0.x Synced today

READMEChangelogDependencies (6)Versions (1)Used By (0)

PHPStan for Laravel True Modular
================================

[](#phpstan-for-laravel-true-modular)

  ![PHPStan for Laravel True Modular](https://camo.githubusercontent.com/c09004a6731f3b877bd9b0f964609498c35359081a24084d26877b7636a5dedd/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f5048505374616e253230666f722532304c61726176656c253230547275652532304d6f64756c61722e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b726571756972652b2d2d646576267061636b6167654e616d653d68617070656e762d636f6d2532466c61726176656c2d747275652d6d6f64756c61722d7068707374616e267061747465726e3d617263686974656374267374796c653d7374796c655f31266465736372697074696f6e3d456e666f7263652b6d6f64756c652b626f756e6461726965732b616e642b747970652b72756e74696d652b72656c6174696f6e732532432b737461746963616c6c79266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313030707826696d616765733d68747470732533412532462532466c61726176656c2e636f6d253246696d672532466c6f676f6d61726b2e6d696e2e737667)[![Latest Version on Packagist](https://camo.githubusercontent.com/396d1044add4b4eff8551823b0949d5691f41356d7f4872bc8a36a46dcd1f358/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f68617070656e762d636f6d2f6c61726176656c2d747275652d6d6f64756c61722d7068707374616e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/happenv-com/laravel-true-modular-phpstan)[![Total Downloads](https://camo.githubusercontent.com/866fe8446c55433204b1009372818440c44da1279dfd49859ebb286b8af83ccc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f68617070656e762d636f6d2f6c61726176656c2d747275652d6d6f64756c61722d7068707374616e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/happenv-com/laravel-true-modular-phpstan)[![Tests](https://camo.githubusercontent.com/6f9002caf07ca48bbac961e8cc1c673c0c35ef8c1578f2e3bc88c271b86f44e4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f68617070656e762d636f6d2f6c61726176656c2d747275652d6d6f64756c61722d7068707374616e2f74657374732e796d6c3f6272616e63683d302e78267374796c653d666c61742d737175617265266c6162656c3d7465737473)](https://github.com/happenv-com/laravel-true-modular-phpstan/actions/workflows/tests.yml)[![PHPStan](https://camo.githubusercontent.com/86f41d942d950a5f7c8b8087a72965922166c8a3da18eece3037557a20dc6fcd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f68617070656e762d636f6d2f6c61726176656c2d747275652d6d6f64756c61722d7068707374616e2f7068707374616e2e796d6c3f6272616e63683d302e78267374796c653d666c61742d737175617265266c6162656c3d7068707374616e)](https://github.com/happenv-com/laravel-true-modular-phpstan/actions/workflows/phpstan.yml)[![Zizmor](https://camo.githubusercontent.com/37254ad1de429c93123b71b349e62f3637fdcfbc9d013efa51d100d3523acddb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f68617070656e762d636f6d2f6c61726176656c2d747275652d6d6f64756c61722d7068707374616e2f7a697a6d6f722e796d6c3f6272616e63683d302e78267374796c653d666c61742d737175617265266c6162656c3d7a697a6d6f72)](https://github.com/happenv-com/laravel-true-modular-phpstan/actions/workflows/zizmor.yml)[![Code Style](https://camo.githubusercontent.com/ba7063930ebd069436f49cc69da9470aa3482aac46c9c5a846fd5508ac801496/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f68617070656e762d636f6d2f6c61726176656c2d747275652d6d6f64756c61722d7068707374616e2f6669782d636f64652d7374796c652e796d6c3f6272616e63683d302e78267374796c653d666c61742d737175617265266c6162656c3d636f64652532307374796c65)](https://github.com/happenv-com/laravel-true-modular-phpstan/actions/workflows/fix-code-style.yml)

PHPStan extensions for [laravel-true-modular](https://github.com/happenv-com/laravel-true-modular)modular monoliths. Ships two independent, **zero-config** extensions:

ExtensionWhat it does**Dynamic Relation Resolver**Teaches PHPStan about Eloquent relations registered at runtime via `Model::resolveRelationUsing()` (e.g. relations one module adds to another module's model). Such relations are normally invisible to static analysis — this extension makes `$model->relation` and `$model->relation()` fully typed.**Module Boundary Enforcer**Fails analysis when a module references a class from another module that is **not** declared in its `composer.json` `require`. Also detects circular dependencies between modules.Requires PHP 8.3+, PHPStan 2.x and `laravel-true-modular` (Laravel 12/13). It reuses the framework's own module discovery, so it understands your modules out of the box — no PHPStan parameters to set.

Installation
------------

[](#installation)

```
composer require --dev happenv-com/laravel-true-modular-phpstan
```

The package is a `phpstan-extension`. If you use [`phpstan/extension-installer`](https://github.com/phpstan/phpstan-extension-installer)(recommended), both extensions are registered automatically — nothing else to do:

```
composer require --dev phpstan/extension-installer
```

Make sure the plugin is allowed in your root `composer.json`:

```
{
    "config": {
        "allow-plugins": {
            "phpstan/extension-installer": true
        }
    }
}
```

### Manual registration (without extension-installer)

[](#manual-registration-without-extension-installer)

Include the bundled config in your `phpstan.neon`:

```
includes:
    - vendor/happenv-com/laravel-true-modular-phpstan/extension.neon
```

Or cherry-pick a single extension:

```
includes:
    - vendor/happenv-com/laravel-true-modular-phpstan/rules/dynamic-relations.neon
    - vendor/happenv-com/laravel-true-modular-phpstan/rules/module-boundary.neon
```

> **Larastan recommended.** The Dynamic Relation Resolver reflects your Eloquent models, so install [`larastan/larastan`](https://github.com/larastan/larastan)for accurate results. With `extension-installer` it is wired up automatically.

Zero configuration
------------------

[](#zero-configuration)

Neither extension needs any `parameters` in `phpstan.neon`. The Module Boundary Enforcer discovers modules through `laravel-true-modular`'s own `ModuleRegistry`, which means it automatically honours:

- the configured module composer type (`Application::moduleComposerType()`, default `true-module`), and
- the configured modules directory (`Application::modulesDirectory()`, default `app-modules`).

A "module" is any package under that directory whose `composer.json` declares the module type. Allowed cross-module dependencies are read straight from each module's `composer.json` `require` section — exactly the same source of truth the framework uses to order service providers at runtime. There is no vendor prefix or path to configure.

> If no modules are found (e.g. the directory does not exist), both rules silently do nothing, so installing the package never breaks an unrelated build.

What it reports
---------------

[](#what-it-reports)

### Dynamic Relation Resolver

[](#dynamic-relation-resolver)

Once installed it automatically types any relation registered through Laravel's relation resolver, for example:

```
// In some module's service provider initialize()/boot():
User::resolveRelationUsing('orders', fn (User $user) => $user->hasMany(Order::class));
```

```
$user->orders;   // PHPStan now sees: Illuminate\Database\Eloquent\Collection
$user->orders(); // PHPStan now sees: Illuminate\Database\Eloquent\Relations\HasMany
```

To-one relations (`hasOne`, `belongsTo`, `morphOne`, `hasOneThrough`) are typed as `Related|null`; to-many relations as `Collection`.

### Module Boundary Enforcer

[](#module-boundary-enforcer)

For every module the enforcer reads its `composer.json` and treats its `require`entries that resolve to **other known modules** as the allowed cross-module dependencies. A module may always reference its own classes and any class from a package that is not a module (vendor libraries, the host application, …).

Violations look like:

```
Module boundary violation: "acme/sales" is not allowed to use "Acme\Crm\Models\Customer"
(from module "acme/crm"). Add "acme/crm" to the require section of acme/sales/composer.json
to allow this dependency.

```

Both `use` statements and inline references (`new`, static calls, `instanceof`, `extends`/`implements`, `catch`, class constants) are checked.

Circular dependencies are reported once at the end of analysis:

```
Circular dependency detected between modules: acme/sales → acme/crm → acme/sales. ...

```

#### Error identifiers

[](#error-identifiers)

You can ignore findings by identifier in `phpstan.neon`:

IdentifierMeaning`trueModular.moduleBoundary`Disallowed cross-module reference`trueModular.circularDependency`Cycle between modules```
parameters:
    ignoreErrors:
        - identifier: trueModular.moduleBoundary
          path: app-modules/legacy/*
```

Example `phpstan.neon`
----------------------

[](#example-phpstanneon)

```
includes:
    # auto-included by extension-installer; shown here for the manual case
    - vendor/happenv-com/laravel-true-modular-phpstan/extension.neon

parameters:
    level: 6
    paths:
        - app-modules
```

That's the whole configuration — point PHPStan at your modules and run it.

Development
-----------

[](#development)

```
composer install
vendor/bin/pest        # test suite (Pest 4)
vendor/bin/pint        # code style
```

The test suite covers both extensions:

- **Dynamic relations** — boots an in-memory Eloquent connection, registers relations via `Model::resolveRelationUsing()`, and asserts the resolver exposes them with the correct method/property types.
- **Module boundary** — uses PHPStan's `RuleTestCase` against fixture modules under `tests/Fixtures` to assert allowed/disallowed cross-module references and circular dependency detection.

License
-------

[](#license)

[MIT](LICENSE.md)

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/855788?v=4)[Bartłomiej Gajda](/maintainers/webard)[@webard](https://github.com/webard)

---

Top Contributors

[![webard](https://avatars.githubusercontent.com/u/855788?v=4)](https://github.com/webard "webard (7 commits)")

---

Tags

PHPStanlaravelstatic analysisphpstan-extensionmodular-monolith

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/happenv-com-laravel-true-modular-phpstan/health.svg)

```
[![Health](https://phpackages.com/badges/happenv-com-laravel-true-modular-phpstan/health.svg)](https://phpackages.com/packages/happenv-com-laravel-true-modular-phpstan)
```

###  Alternatives

[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.6k](/packages/larastan-larastan)[calebdw/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

15104.9k4](/packages/calebdw-larastan)[phpstan/phpstan-symfony

Symfony Framework extensions and rules for PHPStan

79173.3M2.0k](/packages/phpstan-phpstan-symfony)[shipmonk/dead-code-detector

Dead code detector to find unused PHP code via PHPStan extension. Can automatically remove dead PHP code. Supports libraries like Symfony, Doctrine, PHPUnit etc. Detects dead cycles. Can detect dead code that is tested.

4813.1M82](/packages/shipmonk-dead-code-detector)[staabm/phpstan-dba

2942.5M2](/packages/staabm-phpstan-dba)[staabm/phpstan-todo-by

2042.0M76](/packages/staabm-phpstan-todo-by)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
