diff --git a/.gitignore b/.gitignore
index 532d5de2c675ad6aa36154b4c540000a0b665a3c..1f1829da0fa7d599026b250a712dbf0d2995ea20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
 composer
 node_modules
 nbproject
+phpstan.neon
 .caches/*
 .reports/*
 
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5392ceee8282ae9d003bfe5d323bde9a637dbebf..113e6ef3ea2e4be27a9d342eee36ae2577b74f6f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,6 +8,7 @@ variables:
   MYSQL_HOST: mariadb
   DEMO_DATA: "true"
   MAIL_TRANSPORT: debug
+  PHPSTAN_LEVEL: 0
   # Optimize caching
   FF_USE_FASTZIP: "true"
   CACHE_COMPRESSION_LEVEL: "fast"
@@ -16,6 +17,7 @@ variables:
 
 stages:
   - checks
+  - analyse
   - tests
   - packaging
   - release
@@ -53,6 +55,9 @@ stages:
     paths:
       - composer/
       - .caches/phplint-cache
+      - .caches/resultCache.php
+      - .caches/cache/*
+      - .caches/resultCaches/*
   js: &npm-cache
     key: "js-$CI_COMMIT_REF_SLUG"
     paths:
@@ -129,6 +134,23 @@ lint-css:
     reports:
       junit: .reports/stylelint-report.xml
 
+phpstan:
+  stage: analyse
+  needs: [lint-php]
+  allow_failure: true
+  interruptible: true
+  when: manual
+  cache: *composer-cache
+  before_script:
+    - make composer-dev
+    - mkdir .reports -p
+  script:
+    - php composer/bin/phpstan analyse --memory-limit=1G --no-progress --level=$PHPSTAN_LEVEL > .reports/report-phpstan.xml
+  artifacts:
+    when: always
+    reports:
+      junit: .reports/report-phpstan.xml
+
 test-unit:
   stage: tests
   needs: [lint-php]
diff --git a/composer.json b/composer.json
index 395c367cdf9023dac85bdfce2593f1cdc0f794d3..a99ae27c2d3c9867be532dce37ea7be3cd5c4ac2 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,8 @@
         "woohoolabs/yang": "2.3.2",
         "codeception/codeception": "~4.1.21",
         "codeception/module-asserts": "^1.3",
-        "overtrue/phplint": "^3.0"
+        "overtrue/phplint": "^3.0",
+        "phpstan/phpstan": "^1.7"
     },
     "require": {
         "php": "^7.2",
diff --git a/composer.lock b/composer.lock
index 34d1a2eb0d53716eba12deb32243e785cda662f6..70c1c16aef71c36b447b591f8859249066ac2595 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "28f7b44e60723efc25ae44ea906ee3a1",
+    "content-hash": "a509730f82537f1faf0264b4c9246370",
     "packages": [
         {
             "name": "algo26-matthias/idna-convert",
@@ -5190,6 +5190,65 @@
             },
             "time": "2021-03-17T13:42:18+00:00"
         },
+        {
+            "name": "phpstan/phpstan",
+            "version": "1.7.15",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpstan/phpstan.git",
+                "reference": "cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a",
+                "reference": "cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2|^8.0"
+            },
+            "conflict": {
+                "phpstan/phpstan-shim": "*"
+            },
+            "bin": [
+                "phpstan",
+                "phpstan.phar"
+            ],
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "PHPStan - PHP Static Analysis Tool",
+            "support": {
+                "issues": "https://github.com/phpstan/phpstan/issues",
+                "source": "https://github.com/phpstan/phpstan/tree/1.7.15"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/ondrejmirtes",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/phpstan",
+                    "type": "github"
+                },
+                {
+                    "url": "https://www.patreon.com/phpstan",
+                    "type": "patreon"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-06-20T08:29:01+00:00"
+        },
         {
             "name": "phpunit/php-code-coverage",
             "version": "7.0.14",
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000000000000000000000000000000000000..09688095e8f39eb4bca4cab344bc93359301253a
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,24 @@
+parameters:
+    level: 0
+    phpVersion: 70200 # PHP 7.2
+    paths:
+        # - app/routes
+        - lib
+        # - tests
+    scanDirectories:
+        - app/controllers
+        - lib
+        - vendor
+    excludePaths:
+        - lib/classes/ZipArchiveLegacyTrait.php
+        - lib/soap/StudipSoapClient_PHP5.class.php
+    tmpDir: .caches
+    earlyTerminatingMethodCalls:
+        RESTAPI\RouteMap:
+            - error
+            - halt
+    errorFormat:
+       junit
+    ignoreErrors:
+        - '#Access to an undefined property#'
+        - '#Undefined variable#'