<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eric Van Johnson</title>
    <description>The latest articles on DEV Community by Eric Van Johnson (@ericvanjohnson).</description>
    <link>https://dev.to/ericvanjohnson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F198023%2Fbf5c958a-ee8b-46a7-bada-86c2aa53b101.jpeg</url>
      <title>DEV Community: Eric Van Johnson</title>
      <link>https://dev.to/ericvanjohnson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ericvanjohnson"/>
    <language>en</language>
    <item>
      <title>PHP Architect January 2026: Wanted: PHP Developers</title>
      <dc:creator>Eric Van Johnson</dc:creator>
      <pubDate>Sat, 07 Feb 2026 16:20:00 +0000</pubDate>
      <link>https://dev.to/phparch/php-architect-january-2026-wanted-php-developers-26n7</link>
      <guid>https://dev.to/phparch/php-architect-january-2026-wanted-php-developers-26n7</guid>
      <description>&lt;p&gt;Each new year brings with it hopes and dreams of what will be…maybe a new workout routine, starting a new hobby, reading more often, or writing cleaner code – all worthy endeavors. The January edition of PHP Architect promises to help you achieve your goals; okay, we can’t actually help with all of them, but we can definitely help with the last couple. (Shameless plug incoming) We are currently gearing up for PHP Tek26, preparing all the amazing content to help you achieve at least a few of those New Year’s goals. If you haven’t already, check out the list of speakers at phptek.io to learn more and join us.&lt;br&gt;
&lt;a href="https://phpa.me/jan-2026" rel="noopener noreferrer"&gt;https://phpa.me/jan-2026&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>learning</category>
      <category>php</category>
      <category>programming</category>
    </item>
    <item>
      <title>Here’s Why FrankenPHP Worker Mode Saves Your Sanity</title>
      <dc:creator>Eric Van Johnson</dc:creator>
      <pubDate>Fri, 30 Jan 2026 23:34:00 +0000</pubDate>
      <link>https://dev.to/phparch/heres-why-frankenphp-worker-mode-saves-your-sanity-576d</link>
      <guid>https://dev.to/phparch/heres-why-frankenphp-worker-mode-saves-your-sanity-576d</guid>
      <description>&lt;p&gt;&lt;strong&gt;Here’s Why FrankenPHP Worker Mode Saves Your Sanity&lt;/strong&gt;&lt;br&gt;
A lot of developers spend little to no time thinking about how our code gets from being code to something that can be interacted with by the consumers of our code. There are several large components that we can affect to improve the performance of this interaction. One of them that doesn’t get much discussion is how altering the HTTP server can make a huge difference in performance.&lt;br&gt;
Traditionally, in the PHP space, we usually default to Apache or nginx, but recently, the FrankenPHP project has been released, which makes it much easier to deploy our code and potentially much faster.&lt;br&gt;
In this article, we’ll explore why the traditional PHP request lifecycle creates performance bottlenecks, how FrankenPHP’s worker mode eliminates that overhead, and how to migrate an existing Laravel application to FrankenPHP.&lt;br&gt;
&lt;a href="https://www.phparch.com/2026/01/heres-why-frankenphp-worker-mode-saves-your-sanity/" rel="noopener noreferrer"&gt;https://www.phparch.com/2026/01/heres-why-frankenphp-worker-mode-saves-your-sanity/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The PHP Podcast 2026.01.29</title>
      <dc:creator>Eric Van Johnson</dc:creator>
      <pubDate>Fri, 30 Jan 2026 18:11:13 +0000</pubDate>
      <link>https://dev.to/phparch/the-php-podcast-20260129-4m20</link>
      <guid>https://dev.to/phparch/the-php-podcast-20260129-4m20</guid>
      <description>&lt;p&gt;&lt;strong&gt;The PHP Podcast 2026.01.29&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This week on the PHP Podcast, Eric and John talk about Git Worktrees, The future of MySQL, PHP RFC’s, and more…&lt;br&gt;
Links from the show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub – michaeldyrynda/arbor&lt;/li&gt;
&lt;li&gt;GitHub – harris21/laravel-herd-worktree: A Claude Code skill that automates setting up git worktrees for Laravel projects served by Laravel Herd.&lt;/li&gt;
&lt;li&gt;What is the future for MySQL? | InfoWorld&lt;/li&gt;
&lt;li&gt;PHP: rfc:trim_form_feed&lt;/li&gt;
&lt;li&gt;PHP: rfc:isreadable-iswriteable
The PHP Podcast streams live, typically every Thursday at 3 PM PT. Come join us and subscribe to our YouTube channel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.phparch.com/podcast/the-php-podcast-2026-01-29/" rel="noopener noreferrer"&gt;https://www.phparch.com/podcast/the-php-podcast-2026-01-29/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>podcast</category>
    </item>
    <item>
      <title>PHPStan: Your Development Best Friend Who Actually Knows PHP Better Than You Do</title>
      <dc:creator>Eric Van Johnson</dc:creator>
      <pubDate>Mon, 15 Sep 2025 23:54:15 +0000</pubDate>
      <link>https://dev.to/phparch/phpstan-your-development-best-friend-who-actually-knows-php-better-than-you-do-98o</link>
      <guid>https://dev.to/phparch/phpstan-your-development-best-friend-who-actually-knows-php-better-than-you-do-98o</guid>
      <description>&lt;p&gt;&lt;em&gt;Original Post can be found at &lt;a href="https://www.phparch.com/2025/09/phpstan-your-development-best-friend-who-actually-knows-php-better-than-you-do/" rel="noopener noreferrer"&gt;phparch.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's 2 AM, you're three coffees deep, and you just pushed what you're convinced is the cleanest code you've ever written. Your tests are green, your commit message is poetry, and you're feeling like the PHP wizard you always knew you could be. Then PHPStan speaks up. "Hey," it says gently, "I noticed you're returning &lt;code&gt;null&lt;/code&gt; from a function that promises to return a &lt;code&gt;User&lt;/code&gt; object. Also, that &lt;code&gt;$product-&amp;amp;gt;price&lt;/code&gt; you're accessing? It might not exist if the product came from the legacy API."&lt;/p&gt;

&lt;p&gt;This is the moment most developers realize PHPStan isn't just a tool - it's the development friend they never knew they needed.&lt;/p&gt;

&lt;p&gt;I've been writing PHP since PHP 1 days. I've seen frameworks rise and fall, watched the language evolve from a simple templating system into a sophisticated platform. Through it all, I've learned one fundamental truth: &lt;strong&gt;the bugs you don't catch in development will find you in production, usually at the worst possible moment&lt;/strong&gt;. PHPStan has become that reliable friend who catches you before you fall. Not the annoying colleague who nitpicks your variable names, but the thoughtful companion who understands your code's intent and gently guides you toward better solutions.&lt;/p&gt;

&lt;h1&gt;Meeting Your New Best Friend&lt;/h1&gt;

&lt;h2&gt;The Origin Story Worth Knowing&lt;/h2&gt;

&lt;p&gt;Static analysis isn't new. Tools like lint have been protecting developers from themselves since the 1970s. But PHP's dynamic nature made traditional static analysis nearly impossible. Variables could change types mid-function, methods could be called on objects that might not exist, and the interpreter would happily run code that would explode spectacularly in edge cases. Ondřej Mirtes changed everything when he released PHPStan in 2016. He didn't just build another code quality tool - he created a system that could understand PHP's quirks while still catching the mistakes we make when we're human. The genius wasn't in the complexity, but in the approach. PHPStan doesn't try to execute your code; it reads it like an extremely careful developer would, tracking every variable, understanding every type, and spotting the inconsistencies that slip past our tired eyes.&lt;/p&gt;

&lt;p&gt;Learn more about PHPStan and get started at &lt;a href="https://phpstan.org" rel="noopener noreferrer"&gt;phpstan.org&lt;/a&gt;, the official home for documentation, guides, and community resources.&lt;/p&gt;

&lt;h2&gt;First Impressions: The Brutal Honesty Phase&lt;/h2&gt;

&lt;p&gt;Let me share a war story from a few years ago. I inherited an old system - 150,000 lines of PHP that had grown organically over eight years. The original developers were long gone, documentation was sparse, and every change felt like defusing a bomb. On a whim, I ran PHPStan level 0 (the most forgiving setting) against the codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;over 2000 errors.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My heart sank. Then I looked closer. PHPStan wasn't being petty - it was showing me real problems:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F001.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F001.png" alt="" width="599" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every error was a production bug waiting to happen. PHPStan had become my archaeological tool, uncovering years of accumulated technical debt with surgical precision. Think of PHPStan's error count like a health checkup. A high number isn't a judgment - it's information. Each error is PHPStan saying "I'm confused about what you intended here, and if I'm confused, the computer running your code might be too."&lt;/p&gt;

&lt;h2&gt;Configuration That Actually Makes Sense&lt;/h2&gt;

&lt;p&gt;PHPStan's configuration philosophy mirrors good friendship: it meets you where you are, then helps you grow. The beauty lies in the baseline file - PHPStan's way of saying "I know you're not perfect, and that's okay."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F002.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F002.png" alt="" width="540" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This isn't surrender - it's strategy. Start with level 0, generate a baseline for existing issues, then commit to keeping new code clean. It's like having a friend who doesn't judge your messy apartment but insists you wash the dishes you use going forward.&lt;/p&gt;

&lt;h1&gt;Teaching Your Friend Your Language&lt;/h1&gt;

&lt;p&gt;Here's where PHPStan transforms from useful tool to indispensable companion: custom rules. Every application has domain-specific logic that no generic tool can understand. Your business rules, your architectural decisions, your hard-learned lessons about what breaks in production. Let me show you how to teach PHPStan to speak your application's language.&lt;/p&gt;

&lt;h2&gt;PHPStan Tags &amp;amp; Annotations&lt;/h2&gt;

&lt;p&gt;PHPStan understands a rich vocabulary of special annotations that let you communicate with it in sophisticated ways. Think of these as the inside jokes and shared language that develop in any good friendship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core PHPStan Annotations:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F003.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F003.png" alt="" width="750" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced Type Flow Control:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F004.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F004.png" alt="" width="618" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object State Management:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F005.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F005.png" alt="" width="656" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameter Mutation Tracking:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F006.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F006.png" alt="" width="732" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern Error Ignoring (PHPStan 1.11+):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The old way was to ignore entire lines, which could hide multiple problems:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F007.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F007.png" alt="" width="521" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new way is surgical, targeting specific error types:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F008.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F008.png" alt="" width="715" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can ignore multiple specific errors:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F009.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F009.png" alt="" width="622" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new error identifiers make ignoring errors much safer. You're not just suppressing symptoms - you're acknowledging specific, known issues while maintaining protection against new problems.&lt;/p&gt;

&lt;h2&gt;PHP 8+ Attributes: Your Friend Learns Modern PHP&lt;/h2&gt;

&lt;p&gt;PHPStan 2.1+ fully supports PHP 8.4 attributes, including the new &lt;code&gt;#[Deprecated]&lt;/code&gt; attribute. These provide metadata that PHPStan can understand and act upon:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F010.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F010.png" alt="" width="580" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging Your Friend's Understanding:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When PHPStan's behavior seems mysterious, use the debugging helper:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F11.png" alt="" width="765" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This outputs something like &lt;code&gt;Dumped type: string|null&lt;/code&gt; during analysis, helping you understand why PHPStan is complaining about potential null pointer exceptions.&lt;/p&gt;

&lt;h2&gt;Advanced Callable Handling&lt;/h2&gt;

&lt;p&gt;PHPStan 1.11+ introduced sophisticated callback analysis. You can now tell PHPStan when callbacks are executed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EventDispatcher&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="cd"&gt;/**
* @param callable(): void $callback
* @param-immediately-invoked-callable $callback
*/&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nv"&gt;$callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// PHPStan knows this executes immediately&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cd"&gt;/**
* @param callable(): void $callback
* @param-later-invoked-callable $callback
*/&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;queueCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$callback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$callback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Executed later&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F12.png" alt="" width="647" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This helps PHPStan understand exception flow and side effects in your callback-heavy code.&lt;/p&gt;

&lt;h2&gt;Type Aliases: Creating Your Own Type Vocabulary&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F013.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F013.png" alt="" width="622" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Domain Rules: Building Your Shared Vocabulary&lt;/h2&gt;

&lt;p&gt;In that e-commerce system I mentioned, we had a critical business rule: &lt;strong&gt;Order totals can never be negative&lt;/strong&gt;. Seems obvious, right? Yet we'd discovered three separate bugs where calculation errors resulted in negative totals, causing accounting nightmares and confused customers.&lt;/p&gt;

&lt;p&gt;Here's how I taught PHPStan to catch this pattern:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F014.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F014.png" alt="" width="706" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how we're not just checking syntax - we're encoding business logic into static analysis. This rule understands our domain model and catches violations before they reach production.&lt;/p&gt;

&lt;h2&gt;API Contract Enforcement&lt;/h2&gt;

&lt;p&gt;APIs are promises. When you document that an endpoint returns a &lt;code&gt;User&lt;/code&gt; object with specific fields, you're making a commitment to every consumer of that API. Breaking that promise breaks integrations, crashes mobile apps, and generates angry support tickets.&lt;/p&gt;

&lt;p&gt;I learned this lesson the hard way when a "minor" API change brought down our entire checkout flow. The frontend team had relied on a field that I'd removed, and because it was only used in edge cases, our tests didn't catch it.&lt;/p&gt;

&lt;p&gt;Now PHPStan watches my API contracts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F015.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F015.png" alt="" width="766" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This rule ensures that every API response includes the fields documented in our schema. It's like having a friend who remembers all your promises and gently reminds you when you're about to break one.&lt;/p&gt;

&lt;h2&gt;Security: The Friend Who Watches Your Back&lt;/h2&gt;

&lt;p&gt;Security vulnerabilities often hide in the mundane - database queries constructed from user input, authentication checks that assume success, permission validations that trust the caller.&lt;/p&gt;

&lt;p&gt;I once spent three days hunting down an SQL injection vulnerability. The irony? We'd been incredibly careful with our main query builder, but there was one legacy function that still concatenated strings. PHPStan could have caught it in seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F016.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F016.png" alt="" width="774" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of security rules as having a friend who's been mugged before - they're hyperaware of dangerous neighborhoods and will steer you away from trouble before you realize you're in it.&lt;/p&gt;

&lt;h1&gt;PHPStan Learns Your Habits&lt;/h1&gt;

&lt;p&gt;The longer you work with PHPStan, the more it understands your patterns. Through extensions, baselines, and custom configuration, it adapts to your team's coding style and catches the mistakes you're most likely to make.&lt;/p&gt;

&lt;h2&gt;The Baseline: Acknowledging Reality&lt;/h2&gt;

&lt;p&gt;Every legacy codebase has technical debt. The baseline file is PHPStan's way of saying "I understand where you are, let's focus on not making things worse."&lt;/p&gt;

&lt;p&gt;When I first introduced PHPStan to a team of twelve developers, the psychological impact was immediate. Instead of being overwhelmed by thousands of existing issues, they could focus on keeping their new code clean. The baseline became a contract: we won't judge yesterday's code, but tomorrow's should be better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F017.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F017.png" alt="" width="632" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Extensions: Teaching PHPStan Your Framework&lt;/h2&gt;

&lt;p&gt;Modern PHP development relies heavily on frameworks, and each framework has its own magic. Dependency injection containers that resolve types at runtime, ORM entities that gain methods through annotations, template systems that pass variables between contexts.&lt;/p&gt;

&lt;p&gt;PHPStan's extension ecosystem teaches it to understand these patterns. Browse the &lt;a href="https://phpstan.org/user-guide/extension-library" rel="noopener noreferrer"&gt;official PHPStan extension library&lt;/a&gt; for your framework, or install popular ones like:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F018.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F018.png" alt="" width="540" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With these extensions, PHPStan understands that &lt;code&gt;$entityManager-&amp;amp;gt;getRepository(User::class)&lt;/code&gt; returns a &lt;code&gt;UserRepository&lt;/code&gt;, that &lt;code&gt;$request-&amp;amp;gt;get('id')&lt;/code&gt; might return &lt;code&gt;null&lt;/code&gt;, and that Laravel's &lt;code&gt;User::find()&lt;/code&gt; could fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Laravel developers&lt;/strong&gt;: &lt;a href="https://github.com/larastan/larastan" rel="noopener noreferrer"&gt;Larastan&lt;/a&gt; is specifically designed for Laravel projects and includes deep integration with Eloquent, Collections, Facades, and other Laravel-specific patterns.&lt;/p&gt;

&lt;p&gt;This is where PHPStan becomes truly powerful. It's not just checking your code - it's understanding your entire application stack and catching the integration issues that traditional testing might miss.&lt;/p&gt;

&lt;h2&gt;The Intervention: When PHPStan Saves You From Yourself&lt;/h2&gt;

&lt;p&gt;Let me tell you about the time PHPStan prevented a disaster that could have cost my customers company six figures. (For more war stories about how PHPStan catches critical bugs, check out this &lt;a href="https://www.phparch.com/2023/08/fixing-bugs-with-phpstan/" rel="noopener noreferrer"&gt;detailed guide on fixing bugs with PHPStan&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We were building a financial reconciliation system. Money was involved - serious money - and the calculations had to be perfect. Our test suite was comprehensive, our code reviews were thorough, and everyone was confident in the implementation.&lt;/p&gt;

&lt;p&gt;PHPStan level 9 caught something we'd all missed:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F019.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F019.png" alt="" width="616" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bug was subtle. Our API wrapper returned &lt;code&gt;null&lt;/code&gt; during maintenance windows, but only for certain transaction types. Our tests used mocks that never returned &lt;code&gt;null&lt;/code&gt;. Code review focused on the calculation logic, not the null-safety.&lt;/p&gt;

&lt;p&gt;PHPStan's error was simple: "Parameter #2 $bankData of function reconcileTransaction() expects BankData, BankData|null given."&lt;/p&gt;

&lt;p&gt;That one line prevented corrupted financial records, confused accountants, and probably my job.&lt;/p&gt;

&lt;h2&gt;Integration with CI/CD: Your Friend Working 24/7&lt;/h2&gt;

&lt;p&gt;The most powerful aspect of PHPStan isn't the analysis itself - it's the prevention. When integrated with your CI/CD pipeline, PHPStan becomes a safety net that catches problems before they reach production.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F020.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F020.png" alt="" width="616" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every pull request gets analyzed. Every commit is checked. Your friend never sleeps, never gets tired, and never lets problematic code slip through.&lt;/p&gt;

&lt;h2&gt;Metrics and Improvement Tracking&lt;/h2&gt;

&lt;p&gt;PHPStan provides measurable improvement over time. Track your error count, monitor your level progression, and celebrate the victories:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F021.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F021.png" alt="" width="800" height="332"&gt;&lt;/a&gt;&lt;br&gt;
I've seen teams turn error count reduction into a game. Fixing PHPStan errors becomes a satisfying puzzle rather than tedious busywork. Each level increase feels like a genuine achievement because it represents measurably safer code.&lt;/p&gt;

&lt;h1&gt;Relationship Goals: PHPStan Level 10&lt;/h1&gt;

&lt;p&gt;After working with PHPStan for years, you eventually reach the relationship goals phase: level 10 with custom rules that understand your application's deepest patterns.&lt;/p&gt;

&lt;h2&gt;Advanced Configuration for Maximum Strictness&lt;/h2&gt;

&lt;p&gt;Level 10 is where PHPStan becomes almost psychic. It treats all &lt;code&gt;mixed&lt;/code&gt; types strictly (not just explicit ones), catches edge cases you didn't know existed, prevents bugs you never would have considered, and enforces patterns that make your code genuinely robust.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F022.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F022.png" alt="" width="590" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At level 10, PHPStan catches:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;All mixed type usage (implicit and explicit)&lt;/li&gt;
    &lt;li&gt;Generic type mismatches&lt;/li&gt;
    &lt;li&gt;Unused parameters and variables&lt;/li&gt;
    &lt;li&gt;Dead code that can never execute&lt;/li&gt;
    &lt;li&gt;Overly complex conditional logic&lt;/li&gt;
    &lt;li&gt;Missing return type declarations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want even more strictness? The &lt;a href="https://github.com/phpstan/phpstan-strict-rules" rel="noopener noreferrer"&gt;phpstan-strict-rules extension&lt;/a&gt; adds additional rules for defensive programming, including stricter array handling and more aggressive type checking.&lt;/p&gt;

&lt;h2&gt;Custom Extension Development&lt;/h2&gt;

&lt;p&gt;For truly advanced users, PHPStan allows you to extend its core functionality. You can add support for new libraries, create domain-specific analysis rules, and even modify how PHPStan understands PHP itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F023.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F023.png" alt="" width="599" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where you can encode architectural decisions into static analysis. Want to enforce that all database queries go through your repository layer? Write a rule. Need to ensure that all API responses include correlation IDs? Create an extension.&lt;/p&gt;

&lt;p&gt;For comprehensive guidance on developing custom rules and extensions, see the &lt;a href="https://phpstan.org/developing-extensions/rules" rel="noopener noreferrer"&gt;official PHPStan extension development documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Contributing Back to the Community&lt;/h2&gt;

&lt;p&gt;The PHPStan ecosystem thrives because developers contribute back. Whether it's reporting bugs, submitting extensions, or improving documentation, every contribution makes the tool better for everyone.&lt;/p&gt;

&lt;p&gt;Get involved with the PHPStan community on &lt;a href="https://github.com/phpstan/phpstan" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; - report issues, contribute code, or join the discussions. For teams wanting premium features like web UI, continuous analysis, and advanced integrations, &lt;a href="https://phpstan.org/phpstan-pro" rel="noopener noreferrer"&gt;PHPStan Pro&lt;/a&gt; provides professional tooling on top of the open-source foundation.*&lt;/p&gt;

&lt;h1&gt;War Stories from the Trenches&lt;/h1&gt;

&lt;h2&gt;The Case of the Disappearing Customer&lt;/h2&gt;

&lt;p&gt;In 2020, we had a subtle bug that only manifested during Black Friday traffic. Customer objects were occasionally becoming &lt;code&gt;null&lt;/code&gt; during checkout, but only under high load. Our error logs showed the symptoms, but tracking down the cause took days of investigation.&lt;/p&gt;

&lt;p&gt;PHPStan would have caught it immediately:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F024.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F024.png" alt="" width="776" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cache was evicting entries under memory pressure, but our code assumed they'd always be there. One PHPStan rule could have prevented thousands of failed transactions.&lt;/p&gt;

&lt;h2&gt;The API That Lied About Its Types&lt;/h2&gt;

&lt;p&gt;A third-party API claimed to return consistent JSON structures. Their documentation showed examples, their types looked correct, and our integration worked perfectly in development.&lt;/p&gt;

&lt;p&gt;Production was different. Sometimes the API returned strings where we expected numbers. Sometimes arrays where we expected objects. Sometimes the fields we relied on simply didn't exist.&lt;/p&gt;

&lt;p&gt;PHPStan couldn't have predicted the API's inconsistency, but it could have forced us to handle the possibility:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F025.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F025.png" alt="" width="616" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;The Refactoring That Went Too Well&lt;/h2&gt;

&lt;p&gt;During a major refactoring, I changed a method signature and updated all the obvious call sites. The tests passed, code review looked good, and the deployment went smoothly.&lt;/p&gt;

&lt;p&gt;Two weeks later, we discovered a callback function that still used the old signature. It was only triggered by a specific admin action that happened once a month. PHPStan level 6 would have caught the mismatch immediately.&lt;/p&gt;

&lt;h2&gt;The Philosophy of Friendly Static Analysis&lt;/h2&gt;

&lt;p&gt;PHPStan succeeds where other tools fail because it embraces a fundamental truth: &lt;strong&gt;developers are human&lt;/strong&gt;. We make mistakes when we're tired, confused when context-switching between projects, and overconfident when everything seems to be working.&lt;/p&gt;

&lt;p&gt;A good development tool doesn't just catch errors - it teaches you to write better code. PHPStan's error messages are educational:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Method App\Service\OrderService::processPayment() should return App\Entity\Payment but returns App\Entity\Payment|null.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't just an error report; it's a lesson in type safety. It explains what you intended, what actually happens, and guides you toward a solution.&lt;/p&gt;

&lt;h2&gt;Teaching Moments vs. Gotcha Moments&lt;/h2&gt;

&lt;p&gt;Compare PHPStan's approach to older static analysis tools that would report cryptic error codes with no context. PHPStan explains the problem, suggests solutions, and helps you understand the underlying principles.&lt;/p&gt;

&lt;p&gt;When PHPStan tells you that a variable "might not be defined," it's teaching you about variable scope. When it warns about null pointer exceptions, it's showing you defensive programming. Each error is a teaching moment, not a gotcha.&lt;/p&gt;

&lt;h2&gt;The Compound Effect of Small Improvements&lt;/h2&gt;

&lt;p&gt;The real power of PHPStan isn't in preventing any single catastrophic bug - it's in the compound effect of thousands of small improvements. Each error you fix makes your code slightly more robust. Each level you increase makes your application marginally safer.&lt;/p&gt;

&lt;p&gt;Over time, these marginal gains add up to dramatically more stable software. Applications that run for months without errors. Deployments that succeed on the first try. Customer-facing features that work consistently across edge cases.&lt;/p&gt;

&lt;h1&gt;Practical Implementation Guide&lt;/h1&gt;

&lt;h2&gt;Starting Your PHPStan Journey&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: The Baseline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F026.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F026.png" alt="" width="607" height="243"&gt;&lt;/a&gt;Don't try to fix existing errors immediately. Focus on preventing new ones. For complete setup instructions and configuration options, check the &lt;a href="https://phpstan.org/user-guide/getting-started" rel="noopener noreferrer"&gt;PHPStan Getting Started guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Team Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add PHPStan to your CI/CD pipeline. Make it a requirement for merging pull requests. The goal isn't perfection - it's consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Custom Rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Identify patterns specific to your application. What mistakes does your team make repeatedly? What business rules could be encoded?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Level Progression&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start increasing the strictness level. Move from 0 to 1, then to 2. Each level catches different categories of errors. The ultimate goal is level 10 - maximum type safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Approaching Level 10&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By this point, you should be comfortable with mid-level strictness (levels 5-7). Level 10 is the end goal - treating all &lt;code&gt;mixed&lt;/code&gt; types strictly for maximum type safety.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Extensions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add framework-specific extensions. Let PHPStan understand your ORM, your dependency injection, your templating system.&lt;/p&gt;

&lt;h2&gt;Advanced Configuration Patterns&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F027.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.phparch.com%2Fwp-content%2Fuploads%2F2025%2F08%2F027.png" alt="" width="565" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Team Adoption Strategies&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Gradual Approach&lt;/strong&gt;: Start with level 0, generate baselines, and slowly increase strictness as the team gets comfortable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Clean Slate Approach&lt;/strong&gt;: Apply PHPStan level 10 to all new code while leaving legacy code alone. New features are held to higher standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Big Bang Approach&lt;/strong&gt;: Fix all PHPStan errors in a dedicated sprint. This works for smaller codebases but can be overwhelming for large applications.&lt;/p&gt;

&lt;p&gt;I've seen all three approaches succeed, but the key is team buy-in. PHPStan works best when everyone understands its value and commits to keeping their code clean.&lt;/p&gt;

&lt;h1&gt;Your Next Steps&lt;/h1&gt;

&lt;p&gt;PHPStan isn't just a tool - it's a development philosophy that embraces the reality of human fallibility while providing the safety net we all need. It's the friend who catches you when you stumble, teaches you when you're confused, and grows with you as you improve.  Remember: PHPStan isn't about achieving perfection immediately. It's about making continuous improvements, learning from mistakes, and building more reliable software over time.&lt;/p&gt;

&lt;p&gt;The friend you never knew you needed is waiting. All you have to do is say hello.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>php</category>
      <category>phpstan</category>
    </item>
  </channel>
</rss>
