<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://tomasvotruba.com/rss</id>
    <link href="https://tomasvotruba.com" />
    <title>
        <![CDATA[ Read about upgrades, static analysis, GPT, Symfony and Laravel ]]>
    </title>
    <description/>
    <language/>

    <updated>Mon, 12 Jan 2026 00:00:00 +0000</updated>

            <entry>
            <title><![CDATA[ 5 Books I Enjoyed Reading in 2025 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/5-books-2025" />
            <id>https://tomasvotruba.com/blog/5-books-2025</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Keeping the tradition from [previous](/blog/5-books-i-enjoyed-reading-in-2024) [years](/blog/5-books-i-enyjoed-reading-in-2023), here is my short list of 5 books I really enjoyed reading in 2025.
 ]]>
            </summary>

            <updated>Mon, 12 Jan 2026 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The Patch for Laravel Container ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/the-patch-for-laravel-container" />
            <id>https://tomasvotruba.com/blog/the-patch-for-laravel-container</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ [I switched this website from Symfony to Laravel](/blog/why-I-migrated-this-website-from-symfony-to-laravel) 2,5 years ago, and I [love Laravel Container](/blog/what-i-prefer-about-laravel-dependency-injection-over-symfony) ever since.

Symfony and Laravel containers are very similar - read this [compare post](/blog/experiment-how-i-replaced-symfony-di-with-laravel-container-in-ecs) if you know one and want to understand the other.

Yet, I **always patch Laravel Container in `/vendor`** for all projects I use.

Single line change.

Why and where?
 ]]>
            </summary>

            <updated>Tue, 06 May 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How we Maintain Dozens of Symfony Workflows with Peace ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-we-maintain-dozens-of-symfony-workflows-with-peace" />
            <id>https://tomasvotruba.com/blog/how-we-maintain-dozens-of-symfony-workflows-with-peace</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ There are dozens of posts and talks about how Symfony Workflows work and what they are for. To give you the simplest example, if you have a post - it can be drafted, reviewed, or published. The workflow component makes sure the transitions between these states are valid. That's it.

Yet, there is not a single post about how terrible the configuration is.

On one hand, we have Symfony components, like Event Dispatcher and Console, with native PHP 8 strict attributes. On the other hand, we have **Workflows configuration with a fractal array of strings**. It's like a minefield for a developer who's tasked with adding a new line there.

How can we do it better?
 ]]>
            </summary>

            <updated>Thu, 17 Apr 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Upgrading Sensio Security Annotation: The Full Story ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/upgrading-sensio-security-annotation-the-full-story" />
            <id>https://tomasvotruba.com/blog/upgrading-sensio-security-annotation-the-full-story</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The `@Security` annotation, which originated in the Sensio extra bundle, goes a long way. The official upgrade docs have a few misleading pointers, that force you to use unnecessary verbose language.

Fortunately, few hidden levels make code much less verbose and more readable.

This post sums up upgrading the Sensio `@Security` annotation to Symfony `#[IsGranted()]` attribute in one place.
 ]]>
            </summary>

            <updated>Wed, 09 Apr 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Create Weird Fun PHPStan Rules like Nobody&#039;s Watching ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/create-weird-fun-phpstan-rules" />
            <id>https://tomasvotruba.com/blog/create-weird-fun-phpstan-rules</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ There are 2 ways to use PHPStan. You can use native levels, and official extensions and raise the level from 0 to 8. This is a good start, but it often requires enormous work and brings must-have value.

There is also a 2nd way: I wanted PHPStan **to be more fun and more tailored to the unique projects I work with**. That's why I made [symplify/phpstan-rules](https://github.com/symplify/phpstan-rules), a package that just crossed 6 200 000 downloads. It is one of the most used PHPStan extensions apart from official ones.

I put all the fun and practical rules there, and often they prove to be useful to others too.

But today I want you to move from end-user to **creator**.
 ]]>
            </summary>

            <updated>Wed, 12 Mar 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why AST beats GPTs - featuring php-parser, ChatGPT 4.5 and Grok 3 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/why-ast-beats-gpt" />
            <id>https://tomasvotruba.com/blog/why-ast-beats-gpt</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ As I'm manually writing this article, GPTs are on the hype train now. In this post, we'll use freshly released ChatGPT 4.5 and Grok 3 and see, if they know the AST of PHP well enough to be used on **a large PHP project**.

Understanding AST takes longer than writing an English sentence in a chat. But once you see the abstract syntax tree in a code you're reading, it cannot be unseen.

Today I'll try to convince you to start writing your own AST visitors and see how they make magic happen on your codebase.
 ]]>
            </summary>

            <updated>Fri, 07 Mar 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Custom PHPStan Rules to Improve Every Symfony project ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/custom-phpstan-rules-to-improve-every-symfony-project" />
            <id>https://tomasvotruba.com/blog/custom-phpstan-rules-to-improve-every-symfony-project</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Using PHPStan is not just about getting to level 8 with less than 100 ignored cases. Yes, there are also [official extensions](https://packagist.org/?query=phpstan%2Fphpstan-) that improve the type support of Symfony, Doctrine, and Laravel projects.

But more rules are needed to get our PHP project into a future-proof state.

**It takes less effort than getting to level 5 and we can use them since day one**. That's why I love them so much.
 ]]>
            </summary>

            <updated>Mon, 03 Mar 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Cost-effective Container Smoke Tests every Symfony Project must have ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/cost-effective-container-smoke-tests-every-symfony-project-must-have" />
            <id>https://tomasvotruba.com/blog/cost-effective-container-smoke-tests-every-symfony-project-must-have</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today, I'll share a trademark secret that allows us to move fast and make huge changes without fear.

When we're starting a new [Symfony 2.8-7.2 upgrade project](/blog/off-the-beaten-path-to-upgrade-symfony-28-to-72), we cover it with a couple of tests first. These tests are not units, but smoke tests - with a couple of lines they cover a huge portion of the Symfony framework layer we use.

With a couple of lines, we can cover complex container operations and avoid most dummy yet destructive bugs while working with services.
 ]]>
            </summary>

            <updated>Wed, 22 Jan 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Books I enjoyed Reading in 2024 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/5-books-i-enjoyed-reading-in-2024" />
            <id>https://tomasvotruba.com/blog/5-books-i-enjoyed-reading-in-2024</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Another year is gone, and it's [tradition](/blog/5-books-i-enyjoed-reading-in-2023) to pick 5 books I enjoyed reading in 2024.
 ]]>
            </summary>

            <updated>Sat, 18 Jan 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Alice, Nelmio, Hautelook, Faker - How to upgrade Doctrine Fixtures - Part 2 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/alice-nelmio-hautelook-faker-and-how-to-upgrade-doctrine-fixtures-part-2" />
            <id>https://tomasvotruba.com/blog/alice-nelmio-hautelook-faker-and-how-to-upgrade-doctrine-fixtures-part-2</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the first part, [we've kicked off the plan](/blog/alice-nelmio-hautelook-faker-and-how-to-upgrade-doctrine-fixtures-part-1) to upgrade all these packages to their latest version, like a blind map into unknown territory. Since then, we've put in a couple of months of hard work and climbed the terrain.

Today, we look at the practical steps we've taken and the new challenges we discovered [after the first hill](/blog/mountain-climbing).
 ]]>
            </summary>

            <updated>Tue, 14 Jan 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Symfony @required - Avoid the Temptation and Use it Right ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/symfony-required-avoid-the-temptation-and-use-it-right" />
            <id>https://tomasvotruba.com/blog/symfony-required-avoid-the-temptation-and-use-it-right</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Symfony 3 introduced a [`@required` annotation](https://symfony.com/doc/3.x/service_container/calls.html) (now also an attribute) that allows injecting more services via the setter method apart constructor. At the time, it was good.

The goal was to solve circular dependencies: when A needs B, B needs C, and C needs A.

But more often than not, I see PHP projects where it got completely out of hand.

How to use it right?
 ]]>
            </summary>

            <updated>Wed, 08 Jan 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Unused Definitions with Behat Static Analysis ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/unused-definitions-with-behat-static-analysis" />
            <id>https://tomasvotruba.com/blog/unused-definitions-with-behat-static-analysis</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Recently, I've been working on projects with Behat tests. There are hundreds of definitions that can be used in feature file scenarios.

I accidentally noticed that one of the definitions is not used at all and could be removed. This would result in less code to maintain, less code to read, and less code to upgrade.

But I thought, "That's weird." **Why did not Behat report this definition** in our CI? Oh, because there is no Behat static analysis report out of the box. Let's fix that.
 ]]>
            </summary>

            <updated>Mon, 06 Jan 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why Final Classes make Rector and PHPStan more powerful ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/why-final-classes-make-rector-and-phpstan-more-powerful" />
            <id>https://tomasvotruba.com/blog/why-final-classes-make-rector-and-phpstan-more-powerful</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Final classes bring much more value than `extends` it lacks. It teaches composition over inheritance, makes upgrades easier, and [even mocking](/blog/2019/03/28/how-to-mock-final-classes-in-phpunit) is fine.

If you're lazy like me, you can [automate the `final` keyword addition](/blog/finalize-classes-automated-and-safe) to your code - quickly, safely, and check it the CI!
 ]]>
            </summary>

            <updated>Fri, 03 Jan 2025 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Off the Beaten Path to Upgrade Symfony 2.8 to 7.2 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/off-the-beaten-path-to-upgrade-symfony-28-to-72" />
            <id>https://tomasvotruba.com/blog/off-the-beaten-path-to-upgrade-symfony-28-to-72</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ There are two types of upgrades. One follows only `UPGRADE.md` files on every release, replacing what has been removed with new alternatives. It works, and we could say that the codebase will be "up-to-date."

The other upgrade doesn't stop at the required minimum but **makes use of all modern features the framework provides**. It will be faster, easier to understand, and easier to upgrade to the next version. I [wrote a post](/blog/two-kinds-of-legacy-code-upgrade) that explains why the latter is better.

There are no sources about Symfony upgrades spanning multiple major versions—time to fix that.
 ]]>
            </summary>

            <updated>Tue, 17 Dec 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to flip Doctrine ODM repositories to Services ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-flip-doctrine-odm-repositories-to-services" />
            <id>https://tomasvotruba.com/blog/how-to-flip-doctrine-odm-repositories-to-services</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ While working with legacy projects, I often encountered this anti-pattern of misusing repositories. Instead of easy-to-inject service, projects are locked into a service locator.

This makes code hard to upgrade and locks your project heavily to the Doctrine ODM packages. And there are plenty of them. Each extra package bites off its share of upgrade costs.

Today, we look at how to refactor the ODM service locator to independent services and separate your project from ODM. We also get a few advantages in strict type coverage.
 ]]>
            </summary>

            <updated>Tue, 19 Nov 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Alice, Nelmio, Hautelook, Faker - How to upgrade Doctrine Fixtures - Part 1 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/alice-nelmio-hautelook-faker-and-how-to-upgrade-doctrine-fixtures-part-1" />
            <id>https://tomasvotruba.com/blog/alice-nelmio-hautelook-faker-and-how-to-upgrade-doctrine-fixtures-part-1</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Upgrading Doctrine Fixtures can be challenging work. It requires the coordination of four different package groups on Github. One cannot be upgraded without the other.
<br>
<br>
We first prepare for the jump, then take the leap with confidence. I'm writing this post as I handle the upgrade, so my thoughts are fresh, and the process is ongoing. It may evolve based on new information. Let's see where the rabbit hole goes.
 ]]>
            </summary>

            <updated>Thu, 14 Nov 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Ways to Extract Value from Overmocked Tests ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/5-ways-to-extract-value-from-overmocked-tests" />
            <id>https://tomasvotruba.com/blog/5-ways-to-extract-value-from-overmocked-tests</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The legacy projects we work with are often flooded with mocks. I already wrote [How to Remove Dead Mock Calls from PHPUnit Tests](/blog/how-to-remove-dead-mock-calls-from-phpunit-tests), which focuses on dealing with PHPUnit bloated syntax.

Today, we look at the next wave of improvements that make tests more valuable, more accessible to upgrade and read, and even avoid false types.
 ]]>
            </summary>

            <updated>Tue, 05 Nov 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Upgrade deprecated PHPUnit withConsecutive() ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-upgrade-deprecated-phpunit-with-consecutive" />
            <id>https://tomasvotruba.com/blog/how-to-upgrade-deprecated-phpunit-with-consecutive</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The `withConsecutive()` method [was deprecated in PHPUnit 9](https://github.com/sebastianbergmann/phpunit/issues/4255#issuecomment-636422439) and removed in PHPUnit 10. It sparked many [questions](https://stackoverflow.com/questions/75389000/replace-phpunit-method-withconsecutive-abandoned-in-phpunit-10), [on StackOverflow](https://stackoverflow.com/questions/77865216/phpunit-withconsecutive-is-gone-what-is-the-recommended-approach), in [various projets](https://www.drupal.org/project/drupal/issues/3306554) and [GitHub](https://github.com/search?q=repo%3Asebastianbergmann%2Fphpunit+withConsecutive&type=issues).

It was not a very popular BC break. There is no 1:1 replacement. It can be combined with `willReturn*()` methods, which can make it even more tricky to merge with.

PHPUnit upgrades take 95 % of the time to upgrade this single method and 5 % for everything else.
In recent months, we've done a couple of project upgrades with Rector and learned a lot.

Today, I want to share some knowledge with you and explain why it's a change for better code.
 ]]>
            </summary>

            <updated>Thu, 10 Oct 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ PHP is the Best Choice for Long&amp;#8209;Term Business ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/php-is-the-best-choice-for-long-term-business" />
            <id>https://tomasvotruba.com/blog/php-is-the-best-choice-for-long-term-business</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Recently, I listened to Lex Friedman's [podcast with Pieter Levels](https://open.spotify.com/episode/6KBpL2XfR9VdojbKNpE7cX). Pieter talked about his technology stack for building startups: vanilla PHP, jQuery, and SQLite.

Hype is exciting, but there is no better technology proof than long-term usage by sustainable business.

The podcast inspired me to write my views about why PHP is the best choice for long-term.
 ]]>
            </summary>

            <updated>Tue, 27 Aug 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Scope and Downgrade your PHP Tools for Everyone  to Use ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/scope-and-downgrade-your-php-tool-for-everyone-to-use" />
            <id>https://tomasvotruba.com/blog/scope-and-downgrade-your-php-tool-for-everyone-to-use</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Yesterday, I came across a cool PHP tool. I wanted to try it, but the installation instructions were a bit tricky. The tool required a specific PHP version and a specific version of each dependency. It required Symfony 5.4+, but our project has Symfony 3.3. I was unable to use it.

Many PHP tools suffer from the same issue, so I thought I'd share a way to do it better.
 ]]>
            </summary>

            <updated>Fri, 12 Jul 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Awesome PHP Packages from Japan ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/awesome-php-packages-from-japan" />
            <id>https://tomasvotruba.com/blog/awesome-php-packages-from-japan</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last month, I spent in Japan to travel and absorb the local culture. I've also pinged a few friends I knew from Rector and AST projects in the past. I was surprised by how productive the PHP community is around here, with tools I'd personally use and ideas that inspire me.
 ]]>
            </summary>

            <updated>Mon, 17 Jun 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 2 Tricks to get your Symfony configs lines to minimum ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2-tricks-to-get-your-symfony-configs-lines-to-minimum" />
            <id>https://tomasvotruba.com/blog/2-tricks-to-get-your-symfony-configs-lines-to-minimum</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I believe that every Symfony app can fit service config under 5 lines.

Configs are among the most underestimated parts of Symfony projects and deserve to be done right. Like a healthy tree trunk, which brings power to the branches and leaves, clear configs keep the design architecture clear and easy to grow.
 ]]>
            </summary>

            <updated>Mon, 10 Jun 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to reload code highlighter on Livewire 3 component update ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-reload-code-highlighter-on-livewire-3-component-update" />
            <id>https://tomasvotruba.com/blog/how-to-reload-code-highlighter-on-livewire-3-component-update</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I use Livewire 3 for interactive forms and fast clickable maps. Last week, I worked on a filter page for the Rector website, where you can use text input to search for core and community rules.

I typed "add param" to the input and got the results that best matched the rules I could use. But the code highlight was gone; what now?

Current proposed solutions in Laracast/Livewire forums are miss-leading or using old Livewire 2 syntax, so I wanted to share the solution here to make it easier to find.
 ]]>
            </summary>

            <updated>Mon, 03 Jun 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to add visibility to 338 Class Constants in 25 seconds ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-add-visbility-to-338-class-constants-in-25-seconds" />
            <id>https://tomasvotruba.com/blog/how-to-add-visbility-to-338-class-constants-in-25-seconds</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In PHP, we have classes with methods inside them. Would making all your methods `public` be a good idea? No, because some of them should be used only by the class they're in and not anywhere else.

What about class constants?
 ]]>
            </summary>

            <updated>Wed, 29 May 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Cool features of Swiss Knife ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/cool-features-of-swiss-knife" />
            <id>https://tomasvotruba.com/blog/cool-features-of-swiss-knife</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When using a Swiss knife, we think of a tool with many practical abilities.

They're useful for different situations we might experience in the wild. Opening a box of milk? Here is a knife. Cutting wood to start a fire? Here is a chainsaw. Are the letters on the paint bucket too tiny? Try this magnifying class.

Now, we apply the same approach to PHP tooling.
 ]]>
            </summary>

            <updated>Wed, 15 May 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Get Quick Error Count for each PHPStan level ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/get-quick-error-count-for-each-phpstan-level" />
            <id>https://tomasvotruba.com/blog/get-quick-error-count-for-each-phpstan-level</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When I come to a new project, I want to make a rough idea of what I'm dealing with in a few minutes. I usually check `composer.json` and [measure the lines](/blog/easy-and-quick-way-to-measure-lines-of-code-in-php).

Then, I'd love to run PHPStan and get a rough idea of the current state. But are there baselines, custom extensions, global ignores, or no PHPStan at all?
 ]]>
            </summary>

            <updated>Fri, 10 May 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How adding Type Declarations makes Your Code Dangerous ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-adding-type-declarations-makes-your-code-dangerous" />
            <id>https://tomasvotruba.com/blog/how-adding-type-declarations-makes-your-code-dangerous</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ ...and how to avoid it.

[Type coverage](/blog/how-to-measure-your-type-coverage) is a way to gradually add type declarations to your PHP project—step by step, one by one. It's a PHPStan package that helps you maintain a specific minimal level from 0 % to 100 %.
<br><br>
Once we reach high coverage of 80-90 %, we feel safer. But our code can actually be in worse, even dangerous, shape.
 ]]>
            </summary>

            <updated>Wed, 01 May 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Master the Change ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/master-the-change" />
            <id>https://tomasvotruba.com/blog/master-the-change</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When we upgrade a new project to the best version possible, the latest PHP and framework versions, it's not only about changing syntax sugar to a more fancy one.

It's about the vast focus shift in project management so far. It's a change to master. I want to share the basic rules we apply to make the "impossible" upgrades successful and steady.
 ]]>
            </summary>

            <updated>Wed, 17 Apr 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Finalize Classes - Automated and Safe ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/finalize-classes-automated-and-safe" />
            <id>https://tomasvotruba.com/blog/finalize-classes-automated-and-safe</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Final classes have [many](https://ocramius.github.io/blog/when-to-declare-classes-final/) [great](https://tomasvotruba.com/blog/2019/01/24/how-to-kill-parents) [benefits](https://matthiasnoback.nl/2018/09/final-classes-by-default-why/) for future human readers of your code.

They have even more benefits for static analysis and Rector rules.

But what if we have a project with 1000+ classes and 10 minutes and want to automate the finalization process safely?
 ]]>
            </summary>

            <updated>Thu, 07 Mar 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Rector Book 2024 Release with Brand new Chapter ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/rector-book-2024-release-with-brand-new-chapter" />
            <id>https://tomasvotruba.com/blog/rector-book-2024-release-with-brand-new-chapter</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I'm happy to introduce the latest update to our book - *Rector, the Power of Automated Refactoring*, along with Rector version 0.19.5 from this week.

This release includes 2 new commands, brand new configuration with smart IDE autocomplete, brand new chapter and DX improvements to help you master code refactoring with ease.
 ]]>
            </summary>

            <updated>Mon, 05 Feb 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 3 Signs Your Project is Becoming Legacy - Mock Rottening ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/3-signs-your-project-is-becoming-legacy-mock-rottening" />
            <id>https://tomasvotruba.com/blog/3-signs-your-project-is-becoming-legacy-mock-rottening</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In [the first post](/blog/3-signs-your-project-is-becoming-legacy-and-how-to-avoid-them), we looked at the long-term effects of our decisions. Turning a legacy project into a fresh one is a matter of the "just do it" approach.

But there are 3 things we should take with care even if our project seems outside the legacy project category. The second of those is mocks.
 ]]>
            </summary>

            <updated>Sat, 03 Feb 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Get Json output for PHPUnit 10 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/get-json-output-for-phpunit-10" />
            <id>https://tomasvotruba.com/blog/get-json-output-for-phpunit-10</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Early this year, I created a few custom Rector rules for our client. It modified the code based on the PHPUnit error result report.

The only problem is that PHPUnit outputs a string. So, I had to parse it manually with regexes.

Having a JSON output would make my life easier. I'm used to PHP tools that provide the JSON out of the box, but I could not find it in PHPUnit.
 ]]>
            </summary>

            <updated>Sat, 27 Jan 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Zen Config in ECS 12 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/zen-config-in-ecs" />
            <id>https://tomasvotruba.com/blog/zen-config-in-ecs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Easy Coding Standard focuses on easy run, setup, and use. From composer requirement through the automated setup to the config.

The config was based on rather cumbersome Symfony closure service configs. But last year, I [switched the DI container to Laravel](/blog/experiment-how-i-replaced-symfony-di-with-laravel-container-in-ecs).

Eventually, this opened the door to further innovation that I'll introduce today.
 ]]>
            </summary>

            <updated>Sun, 14 Jan 2024 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Books I enjoyed Reading in 2023 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/5-books-i-enyjoed-reading-in-2023" />
            <id>https://tomasvotruba.com/blog/5-books-i-enyjoed-reading-in-2023</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I've read over a dozen books in 2023. Here are 5 favorites that influenced me the most.
 ]]>
            </summary>

            <updated>Sat, 30 Dec 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 3 Signs Your Project is Becoming Legacy - Arrays Creep ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/3-signs-your-project-is-becoming-legacy-arrays-creep" />
            <id>https://tomasvotruba.com/blog/3-signs-your-project-is-becoming-legacy-arrays-creep</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In [the first post](/blog/3-signs-your-project-is-becoming-legacy-and-how-to-avoid-them), we looked at the long-term effects of our decisions. Turning a legacy project into a fresh one is a matter of the "just do it" approach.

But there are 3 things we should take with care even if our project seems outside the legacy project category. First of those are arrays.
 ]]>
            </summary>

            <updated>Thu, 28 Dec 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 3 Signs Your Project is Becoming Legacy and How to Avoid Them ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/3-signs-your-project-is-becoming-legacy-and-how-to-avoid-them" />
            <id>https://tomasvotruba.com/blog/3-signs-your-project-is-becoming-legacy-and-how-to-avoid-them</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Taking care of a software project long-term is not about immediate action but routine and regular checks.

We have to know we're heading in the right direction; otherwise, we might end up trapped in a legacy project that is hard to get out of.

When clients contact our [Rector team](https://getrector.com/hire-team) for help with their project, **they often share a few common treats**. I wish they would contact me 2 years earlier for a week of consulting. Their project would be in a much better shape.

Based on experience with 100+ legacy projects, I can see what decisions will result in long term positive results and what will take your project astray.
 ]]>
            </summary>

            <updated>Fri, 17 Nov 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Autowire Multiple Instances of Same Type in Symfony and Laravel ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-autowire-multiple-instances-of-same-type-in-symfony-laravel" />
            <id>https://tomasvotruba.com/blog/how-to-autowire-multiple-instances-of-same-type-in-symfony-laravel</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you work with Symfony from 2 through 7? Then you know the main challenge in the upgrade path is to trim your YAML configs to a minimum.

**Where we needed 300+ lines in configs, we are now good with 2**. How to get there fast and reliable?

I'll show a trick we use in the PHP project to get there once and for all.
 ]]>
            </summary>

            <updated>Wed, 01 Nov 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to make your Tool Commands List Easy to Ready ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-make-your-tool-commands-list-easy-to-read" />
            <id>https://tomasvotruba.com/blog/how-make-your-tool-commands-list-easy-to-read</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you use Symfony-console based tools? If you're using Composer, Rector, PHPSpec, PHPStan, ECS or [Class Leak](https://github.com/TomasVotruba/class-leak), you probably know the long list of commands you can use.

In most of the times, most of command you read are not part of the real package. Do we really need them?
 ]]>
            </summary>

            <updated>Fri, 13 Oct 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ From Symfony to Laravel - 5 Steps to Prepare your Symfony Project for Migration ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/from-symfony-to-laravel-5-steps-to-prepare-your-symfony-project-for-migration" />
            <id>https://tomasvotruba.com/blog/from-symfony-to-laravel-5-steps-to-prepare-your-symfony-project-for-migration</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Framework migration is a challenge few choose to take - yet in some cases, it makes sense for business, project health, and pure joy from coding.

Once you know [the recipe](https://getrector.com/blog/how-to-migrate-legacy-php-applications-without-stopping-development-of-new-features), it's clear the switch [is doable](https://getrector.com/blog/success-story-of-automated-framework-migration-from-fuelphp-to-laravel-of-400k-lines-application).

Today, we'll look at the steps to prepare your Symfony project for future Laravel migration.
 ]]>
            </summary>

            <updated>Wed, 06 Sep 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ From Symfony to Laravel - Can Laravel even Compiler Pass ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/from-symfony-to-laravel-can-laravel-even-compiler-pass" />
            <id>https://tomasvotruba.com/blog/from-symfony-to-laravel-can-laravel-even-compiler-pass</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you want to migrate your Symfony project to Laravel and not sure if it "handles it"? Switching containers is pretty [straightforward](/blog/experiment-how-i-replaced-symfony-di-with-laravel-container-in-ecs) for the most parts.

But can Laravel handle advanced features such as compiler passes?
 ]]>
            </summary>

            <updated>Fri, 25 Aug 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to take Advantage of 3rd party Dependency Injection Container ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-take-advantage-of-3rd-party-dependency-container" />
            <id>https://tomasvotruba.com/blog/how-to-take-advantage-of-3rd-party-dependency-container</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When Nuno sent me a Pest plugin for type coverage that runs [TomasVotruba/type-coverage](https://github.com/TomasVotruba/type-coverage), I looked for the PHPStan container use.

Why? Because the type-coverage package is PHPStan rules that easily plugin into PHPStan. But what if you want to use them in a tool that has a different container?

I've found the solution the hard way - so it might be useful to share it with you to save you the trouble.
 ]]>
            </summary>

            <updated>Thu, 24 Aug 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Easy and Quick way to Measure lines of Code in PHP ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/easy-and-quick-way-to-measure-lines-of-code-in-php" />
            <id>https://tomasvotruba.com/blog/easy-and-quick-way-to-measure-lines-of-code-in-php</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The famous [phploc](https://github.com/sebastianbergmann/phploc) package to measure project size was archived by Sebastian on Jan 10, 2023. I used this package to get feedback on [CLI apps vendor shrink](/blog/unleash-the-power-of-simplicity-php-cli-app-with-minimal-dependencies) and for [fast estimation of project size in Rector upgrades](https://getrector.com/hire-team).

**That's why I needed a replacement**. Fast!
 ]]>
            </summary>

            <updated>Sun, 20 Aug 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Removing Service from Laravel Container is not that Easy ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/removing-service-from-laravel-container-is-not-that-easy" />
            <id>https://tomasvotruba.com/blog/removing-service-from-laravel-container-is-not-that-easy</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last month I successfully [switched the Symfony container for Laravel one](/blog/experiment-how-i-replaced-symfony-di-with-laravel-container-in-ecs) in Easy Coding Standard.

The tiny container is a joy to work with - it consists of 2 files I can read and understand all its features. **I wanted to put this package into pressure test**, so I migrated the project I work on daily - [Rector](https://github.com/rectorphp/rector).
 ]]>
            </summary>

            <updated>Fri, 18 Aug 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Remove Transitional Dependencies You don&#039;t Need ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-remove-transitional-dependencies-you-dont-need" />
            <id>https://tomasvotruba.com/blog/how-to-remove-transitional-dependencies-you-dont-need</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the last post [I shared a trick](/blog/unleash-the-power-of-simplicity-php-cli-app-with-minimal-dependencies) on how to **reduce CLI project /vendor size by 70 %**. Today we'll trim off a bit more with the no-so-known composer feature.
 ]]>
            </summary>

            <updated>Wed, 16 Aug 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Unleash the Power of Simplicity: PHP CLI App with Minimal Dependencies ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/unleash-the-power-of-simplicity-php-cli-app-with-minimal-dependencies" />
            <id>https://tomasvotruba.com/blog/unleash-the-power-of-simplicity-php-cli-app-with-minimal-dependencies</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I have a couple of open-source CLI apps like Rector, ECS, Class Leak, Config Transformer, Monorepo Builder and Lines, and private ones like Cleaning Checklist, Fixai, Private Rector and Entropy. All of them run in the command line, and some of them [are downgraded to PHP 7.2](/blog/how-to-release-php-81-and-72-package-in-the-same-repository).

In every project, there is the rule, the fewer dependencies you have, the less work to maintain them. This applies twice to CLI apps distributed with scoped and downgraded /vendor included.

How to achieve this goal? It's not what I thought.
 ]]>
            </summary>

            <updated>Mon, 31 Jul 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Experiment: How I replaced Symfony DI with Laravel Container in ECS ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/experiment-how-i-replaced-symfony-di-with-laravel-container-in-ecs" />
            <id>https://tomasvotruba.com/blog/experiment-how-i-replaced-symfony-di-with-laravel-container-in-ecs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This year I've been learning Laravel and quickly adapting to most of my tools. I've made 2 packages - [Punchcard](/blog/introducing-punchcard-object-configs-for-laravel) to handle configs and [Bladestan](/blog/introducing-bladestan-phpstan-analysis-of-blade-templates) for static analysis of Blade templates using PHPStan.

The component I wanted to put in tests was [Laravel Container](/blog/what-i-prefer-about-laravel-dependency-injection-over-symfony). Everything went well on small projects, but what about packages with 10 000 000+ downloads?

This week, I gave it a try on ECS, and this is how it went.
 ]]>
            </summary>

            <updated>Tue, 25 Jul 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to avoid Maintaining Classes you Don&#039;t Use ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-avoid-maintaining-classes-you-dont-use" />
            <id>https://tomasvotruba.com/blog/how-to-avoid-maintaining-classes-you-dont-use</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ PHPStan and static analysis help us with detect unused private methods. I also made a package to handle [unused public methods](/blog/can-phpstan-find-dead-public-methods).

But we can do better. When we remove dead parts of our code, we sometime leak classes that are never used. But we still have to maintain them, upgrade them and test them.

Do you want to avoid spending time and money on something you don't use?
 ]]>
            </summary>

            <updated>Tue, 18 Jul 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Two Kinds of Legacy Code Upgrade ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/two-kinds-of-legacy-code-upgrade" />
            <id>https://tomasvotruba.com/blog/two-kinds-of-legacy-code-upgrade</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I often speak with project owners or CTOs, who ask for help with legacy project upgrades. They typically want something like "upgrade to PHP 8.0" or "upgrade to Symfony 5.4". There are two ways to do that.

Which one is the best for you? Let's ask the important question first.
 ]]>
            </summary>

            <updated>Mon, 10 Jul 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Moving from Disqus to Twitter to make Know-how Sharing Easier ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/moving-from-disqus-to-twitter-to-make-knowhow-sharing-easier" />
            <id>https://tomasvotruba.com/blog/moving-from-disqus-to-twitter-to-make-knowhow-sharing-easier</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Discussion were always important part of my blog. To share know-how with you, my reader, learn something new and look for better solution. Last few years the main "fire chat" place moves from private channels like comments under post, to public ones like Twitter and Reddit.

As knowledge becomes dispersed across various platforms, comments often become repetitive and diluted. Furthermore, Disqus has its own set of user-tracking issues. So, how can we make a change for the better?
 ]]>
            </summary>

            <updated>Wed, 19 Apr 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ What I prefer about Laravel Dependency Injection over Symfony ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/what-i-prefer-about-laravel-dependency-injection-over-symfony" />
            <id>https://tomasvotruba.com/blog/what-i-prefer-about-laravel-dependency-injection-over-symfony</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Regarding Laravel, one of the biggest "no"s in 2022 was how it handles passing services around the project. I'm not talking about the facades or active records but **the static reflection container**.

At first, it raised my blood pressure - we have a dependency injection, and everything must be passed via the constructor, right?

Then I remembered a wise saying: "There are no best solutions, only trade-offs."
 ]]>
            </summary>

            <updated>Fri, 31 Mar 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Introducing Bladestan - PHPStan analysis of Blade templates ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/introducing-bladestan-phpstan-analysis-of-blade-templates" />
            <id>https://tomasvotruba.com/blog/introducing-bladestan-phpstan-analysis-of-blade-templates</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This Tuesday, I was a guest in [2nd podcast of PHP Portugal](https://twitter.com/VotrubaT/status/1639241043248836610) folks. It was fun as always, and apart from GPT questions, I got asked about the Laravel open-source packages like [Punchcard](https://github.com/tomasVotruba/punchcard).

I promised to put the 2nd package this week, so here it is.
 ]]>
            </summary>

            <updated>Fri, 24 Mar 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ To Route or To Action - That is the Question ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/to-route-or-to-action-thats-the-question" />
            <id>https://tomasvotruba.com/blog/to-route-or-to-action-thats-the-question</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This week I've been working a lot on GPT in [Testgenai.com](https://testgenai.com/). I am learning more and more about Laravel as a side effect.

During browsing open-source projects written in Laravel, I've noticed the syntax I have been dreaming of since I started to use invokable controllers. What was it? Can it make code cleaner or more complex? [I asked on Twitter](https://twitter.com/VotrubaT/status/1635401027171287041) and got such a variety of replies, that it deserves a blog post.
 ]]>
            </summary>

            <updated>Wed, 15 Mar 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Introducing Punchcard - Object Configs for Laravel ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/introducing-punchcard-object-configs-for-laravel" />
            <id>https://tomasvotruba.com/blog/introducing-punchcard-object-configs-for-laravel</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ What would you like to ride on a highway: a city bike or a Tesla car? **To move fast, we have to feel safe**.

Last month I had [made a head jump to Laravel](/blog/why-I-migrated-this-website-from-symfony-to-laravel) ecosystem. The migration went very well, as most of the code is intuitive. There was just one clear bottle-neck: the array configs.
 ]]>
            </summary>

            <updated>Wed, 08 Mar 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why I Migrated This Website From Symfony To Laravel ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/why-I-migrated-this-website-from-symfony-to-laravel" />
            <id>https://tomasvotruba.com/blog/why-I-migrated-this-website-from-symfony-to-laravel</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ It's been exactly a week since I migrated this website from Symfony to Laravel. I had never done such a migration before and feared the pitfalls waiting for me.

The migration itself was easy and swift. It took me 2 trips on Lisbon trains, one afternoon in a cafe, and a few hours at the hotel to finish. I'll talk about the process later, and it's a fascinating set of techniques.

 **You kept me asking "why", so here it is.**
 ]]>
            </summary>

            <updated>Sun, 26 Feb 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to ask DaVinci and Codex to get the right answer ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-can-we-generate-unit-tests-part-3-how-to-ask-davinci-and-codex-to-get-the-right-answer" />
            <id>https://tomasvotruba.com/blog/how-can-we-generate-unit-tests-part-3-how-to-ask-davinci-and-codex-to-get-the-right-answer</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last week, I kicked off the first post about [tips and tricks with GPT](/blog/lets-share-fails-and-tricks-with-gpt). In the meantime, Marcel posted a great practical piece on [GPT and solutions based on exception messages](https://beyondco.de/blog/ai-powered-error-solutions-for-laravel).


Today, we look into 2 pre-trained models that GPT provides - DaVinci and Codex - and how to talk to them to get what we need.
 ]]>
            </summary>

            <updated>Tue, 14 Feb 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Run Config Transformer Everyday to keep YAML Away ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/run-config-transformer-in-ci-everyday-to-keep-yaml-away" />
            <id>https://tomasvotruba.com/blog/run-config-transformer-in-ci-everyday-to-keep-yaml-away</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Have you moved your Symfony configs from YAML to PHP with the help of [Config Transformer](/blog/2020/07/27/how-to-switch-from-yaml-xml-configs-to-php-today-with-migrify/)? Do you use [the PHP benefits daily](/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs)?


But how do you **make sure no YAML is leaking**  from a new developer or in test configs?
 ]]>
            </summary>

            <updated>Sun, 12 Feb 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Lets Share Fails and Tricks with GPT ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/lets-share-fails-and-tricks-with-gpt" />
            <id>https://tomasvotruba.com/blog/lets-share-fails-and-tricks-with-gpt</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last week, I had many interesting discussions about OpenAI and GPT on [Laracon in Porto](https://laracon.eu/). Especially with [Marcel Pociot](https://twitter.com/marcelpociot).

I've learned much more in 2 days than on the Internet since December.

That feels great, and tips seem basic but effective. But as in any other fresh area, finding out about them takes a lot of work. I want to embrace sharing in the GPT community, so here is cherry-pick list of failures and tricks from people **who were generous to share it with me**.
 ]]>
            </summary>

            <updated>Tue, 31 Jan 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Good Bye, Monorepo ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/good-bye-monorepo" />
            <id>https://tomasvotruba.com/blog/good-bye-monorepo</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I've been using monorepo for almost a decade, and I was thrilled with that. Yet, in recent years I've noticed a few glitches in the workflow. The more popular the package became, the more visible frictions were.


How do I see the monorepo approach in 2023, and what do I want to do differently?
 ]]>
            </summary>

            <updated>Sat, 28 Jan 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How can we Generate Unit Tests - Part 2: Building Scoring Script ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-can-we-generate-unit-tests-part-2-building-scoring-script" />
            <id>https://tomasvotruba.com/blog/how-can-we-generate-unit-tests-part-2-building-scoring-script</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I kicked off the [unit test generator](/blog/how-can-we-generate-unit-tests-part-1-testability-score) idea with the first post a week ago. It was a great [success on Reddit](https://www.reddit.com/r/PHP/comments/103vtkt/how_can_we_generate_unit_tests_part_1_testability/), and I'm happy there is interest in the PHP community.


I often got asked about the **testability score**.
How does it work, and how can it be measured in actual code? Well, let's find out.
 ]]>
            </summary>

            <updated>Thu, 12 Jan 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How can we Generate Unit Tests - Part 1: Testability Score ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-can-we-generate-unit-tests-part-1-testability-score" />
            <id>https://tomasvotruba.com/blog/how-can-we-generate-unit-tests-part-1-testability-score</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ As you have noticed, apart from writing micro-packages for PHPStan, my passion is exploring the field of **generated unit tests**. I want to share my thoughts on this topic with you to get your feedback and find a path to the best solution.


You will learn a lot about making man-like working/thinking tools.


I am still determining where this goes, but I love the journey. Let's dive in.
 ]]>
            </summary>

            <updated>Wed, 04 Jan 2023 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to release PHP 8.1 and 7.2 package in the Same Repository ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-release-php-81-and-72-package-in-the-same-repository" />
            <id>https://tomasvotruba.com/blog/how-to-release-php-81-and-72-package-in-the-same-repository</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In a post from autumn, we looked at how to [develop packages in monorepo on PHP 8.1 and release a downgraded version on PHP 7.2](/blog/how-to-develop-sole-package-in-php81-and-downgrade-to-php72/).


But having 2 repositories to work with still feels crappy. Which one should we use? Where do people contribute? Where do we report issues? Everyone needs clarification, and **time is wasted on explaining complexity**.

I knew we could do better... we want **one repository**. Today I'll show you how to get there with 39 lines of GitHub Action workflow (including comments).
 ]]>
            </summary>

            <updated>Fri, 30 Dec 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Measure Your Type Coverage ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-measure-your-type-coverage" />
            <id>https://tomasvotruba.com/blog/how-to-measure-your-type-coverage</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When we come to a new code base, we look for a code quality metric that will tell us how healthy the code base is. We can have CI tools like PHPStan and PHPUnit. PHPStan reports missing or invalid types, and PHPUnit reports failing tests.


But how do we know if 10 passing or 100 passing tests is enough? What if there are over 10 000 cases we should test?
 ]]>
            </summary>

            <updated>Mon, 07 Nov 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Develop Sole Package in PHP 8.1 and Downgrade to PHP 7.2 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-develop-sole-package-in-php81-and-downgrade-to-php72" />
            <id>https://tomasvotruba.com/blog/how-to-develop-sole-package-in-php81-and-downgrade-to-php72</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The PHP downgrades are a thing. Most beneficial for package developers who want to move forward to the latest PHP features but also want to **keep easy access to the broad PHP community and legacy projects**.


The downgrade of a tool is a no-brainer - [we downgrade the whole tool](https://getrector.com/blog/how-to-bump-minimal-version-without-leaving-anyone-behind) including vendor, and we know it will run on PHP 7.2.

But how to achieve the same with the package with separated dependencies?
 ]]>
            </summary>

            <updated>Mon, 25 Jul 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 8 News in Config Transformer that Converts Symfony YML to PHP ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/8-news-in-config-transformer-that-converts-symfony-yml-to-php" />
            <id>https://tomasvotruba.com/blog/8-news-in-config-transformer-that-converts-symfony-yml-to-php</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ If you have not switched your [Symfony configs from YAML to PHP](/blog/2020/07/27/how-to-switch-from-yaml-xml-configs-to-php-today-with-migrify/), there no better time like present.


This month we tested the ConfigTransformer to its limit. It had to deal with edge-cases from Symfony 2.8 all the way through Symfony 3.4. With features that were removed for years. As a result, we added default processing of `*.yaml` and `.yml` syntax at the same time and support for scalars like `::hi` and `'hello::'`.


That's just the tip of the iceberg. **What are the 5 new features you'll be able to enjoy in the upcoming release**?
 ]]>
            </summary>

            <updated>Mon, 18 Jul 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Can PHPStan find Dead Public Methods ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/can-phpstan-find-dead-public-methods" />
            <id>https://tomasvotruba.com/blog/can-phpstan-find-dead-public-methods</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This bold question has been around PHP Internet for many years... [at least since 2008](https://stackoverflow.com/questions/11532/how-can-i-find-unused-functions-in-a-php-project). In 2017 I added [dead public method sniff](https://github.com/symplify/symplify/pull/466) to Symplify Coding Standard.


It runs on bare PHP tokens without any type or AST, so the capability was limited. Yet it was able to detect a few unused methods. Now, 5 years later, we maybe have a better solution.
 ]]>
            </summary>

            <updated>Mon, 04 Jul 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Twig Smoke Rendering - Fortune Favors the Bold ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/twig-smoke-rendering-fortune-favors-the-bold" />
            <id>https://tomasvotruba.com/blog/twig-smoke-rendering-fortune-favors-the-bold</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we set on [journey of fails](/blog/twig-smoke-rendering-journey-of-fails) with ups and downs. Well, mostly downs. I'm trying to be honest about the blind path process behind the final published work.


We made it through heaven and hell. Now we're rested and back to continue. Can we smoke render twig templates, or shall we give up?
 ]]>
            </summary>

            <updated>Mon, 27 Jun 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Twig Smoke Rendering - Journey of Fails ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/twig-smoke-rendering-journey-of-fails" />
            <id>https://tomasvotruba.com/blog/twig-smoke-rendering-journey-of-fails</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In previous post, we explored [the "whys" for Twig Smoke Rendering](/blog/twig-smoke-rendering-why-do-we-even-need-it).


Today we will set on the journey towards this tool and mainly. Get ready for failure, demotivation, and despair. As with every new invention, the fuel can make us faster or burn us to death.
 ]]>
            </summary>

            <updated>Mon, 20 Jun 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Twig Smoke Rendering - Why do we Even Need it ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/twig-smoke-rendering-why-do-we-even-need-it" />
            <id>https://tomasvotruba.com/blog/twig-smoke-rendering-why-do-we-even-need-it</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Two weeks ago [our upgrade team started](https://getrector.com/hire-team) to upgrade Twig 1 to 2 and Latte 2 to 3 for two clients. There was no test that covers the templates, just a few integration ones that might have invoked a few % of happy paths render. Not good enough.


We **need a CI test to be sure** templates are working. I had an initial idea, but knowing the value of external input, I asked on [Twitter for brainstorming](https://twitter.com/VotrubaT/status/1537029650379116544). I'm happy I did. Alexander Schranz came with [a tip](https://twitter.com/alex_s_/status/1537030374651572225) that led me on a 2-week journey, and I would love to share it with you today.
 ]]>
            </summary>

            <updated>Mon, 13 Jun 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Pitfalls of Upgrade to Native PHP Enums and How to Avoid Them ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/five-pitfalls-of-upgrade-to-native-php-enums-and-how-to-avoid-them" />
            <id>https://tomasvotruba.com/blog/five-pitfalls-of-upgrade-to-native-php-enums-and-how-to-avoid-them</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Native PHP Enums came almost a year ago in PHP 8.1. It's pretty easy to add a new enum. But how do we handle the old hacks we used to use before enums were legal in PHP land? MyCLabs, Spatie, or constants list.


Today we'll upgrade them all. Is it a simple constant to enum replace? Surprisingly, there are **few blind paths we have to be aware of**.
 ]]>
            </summary>

            <updated>Mon, 06 Jun 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Make Configs like RectorConfig or ECSConfig for your Symfony Project ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-make-configs-like-rector-config-or-ecs-config-for-your-symfony-project" />
            <id>https://tomasvotruba.com/blog/how-to-make-configs-like-rector-config-or-ecs-config-for-your-symfony-project</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We've introduced a new way to configure PHP tools on Symfony DI. A way that is decoupled brings new methods with autocomplete and validates your input. I talk about [RectorConfig](https://getrector.com/blog/new-in-rector-012-introducing-rector-config-with-autocomplete) and [ECSConfig](https://tomasvotruba.com/blog/new-in-ecs-simpler-config/).


At first, I thought it was not possible. Symfony is very strict about this and does not allow any extensions. After a few days of hacking Symfony, I found a space to squash `<x>Config` class. After meeting with [Sebastian Schreiber](https://twitter.com/schreiberten) last week, we found an even better generic solution.


Are you interested in a better developer experience for your Symfony project? Keep reading.
 ]]>
            </summary>

            <updated>Mon, 30 May 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ New in ECS: Simpler Config ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/new-in-ecs-simpler-config" />
            <id>https://tomasvotruba.com/blog/new-in-ecs-simpler-config</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ ECS runs on Symfony container configuration to build the service model. While it brings automated autowiring, array autowiring, and native container features, the downside is that ECS configuration syntax is complex and talkative.


We decided to simplify it so ECS is truly easy to use.
 ]]>
            </summary>

            <updated>Mon, 09 May 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to test Symfony Routes to make Huge Refactoring Safe ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-test-symfony-routes-to-make-huge-refactorings-safe" />
            <id>https://tomasvotruba.com/blog/how-to-test-symfony-routes-to-make-huge-refactorings-safe</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The beauty of [pattern refactoring](/blog/2019/04/15/pattern-refactoring/) with Rector is transforming thousands of elements at once. Like nuclear chain reaction. But to do it safely, we need a high-quality test to ensure the code still works.


Does a high-quality test mean *a lot of* tests? Not necessarily. Instead of writing many tests to cover all our routes, we can write one smart one. How?
 ]]>
            </summary>

            <updated>Mon, 02 May 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Remove Dead Mock Calls from PHPUnit Tests ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-remove-dead-mock-calls-from-phpunit-tests" />
            <id>https://tomasvotruba.com/blog/how-to-remove-dead-mock-calls-from-phpunit-tests</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We're going to visit a foreign country where living costs are just 1/3 of ours. Let's say from UK or Germany to Brno, Czechia. We're organizing a bachelor party for our best friend.


The night has come, and our group walks around the city and drinks beers, the groom wears baby piggy clothes, and we're happily celebrating. We're losing one more wingman that will settle down with a beautiful wife and soon-to-come child. It's fun and exciting. We've never been abroad before with so many friends to celebrate the next step in man's life.
 ]]>
            </summary>

            <updated>Mon, 25 Apr 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Constant Lists That Give Context to your Integers and Strings ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/5-constant-lists-that-give-context-to-your-integers-and-strings" />
            <id>https://tomasvotruba.com/blog/5-constant-lists-that-give-context-to-your-integers-and-strings</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ [Native enums](https://php.watch/versions/8.1/enums) is a new PHP 8.1 feature. This feature brings more focus on *what* enums are and *where* we can use them.

**Not on PHP 8.1 yet?** Don't worry, before that, enums were emulated by public constants. Some constant lists are already part of your favorite framework, ORM, or utils package for years.


Today we look at 5 constant lists that you can use today to replace that `int` or `string` and give it a context.
 ]]>
            </summary>

            <updated>Mon, 07 Mar 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Create Symfony Kernel for Tests with Different Configs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-create-symfony-kernel-for-tests-with-different-configs" />
            <id>https://tomasvotruba.com/blog/how-to-create-symfony-kernel-for-tests-with-different-configs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ How can we create 2 tests scenarios for the Symfony Kernel project with 2 different parameters? How can we inject 2 different instances of the same interface? How can we do it in the same way we already configure both of them?


Today we'll look at a little trick that allows us to create Symfony Kernel with different configs.
 ]]>
            </summary>

            <updated>Mon, 07 Feb 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Get Rid of Mixed Callables with PHPStan ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/get-rid-of-mixed-callables-with-phpstan" />
            <id>https://tomasvotruba.com/blog/get-rid-of-mixed-callables-with-phpstan</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Working with PHPStan on level 8 is a luxury, at least for a project where you've just introduced it. To give you a practical non-open-source perspective: **we're at level 5 after 2 years of hard work**.


In this level, we've noticed that PHPStan skips expression on variables that it resolved as `mixed`. Level 5 already provides valuable checks that we wanted for all **method calls and property fetches**. So [we added custom rule to report those](/blog/not-all-mixed-types-are-equally-useless).


After we cut the low-hanging fruit, we discovered the same way are skipped all *callable* types. How to deal with those?
 ]]>
            </summary>

            <updated>Mon, 31 Jan 2022 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Not all Mixed Types are Equally Useless ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/not-all-mixed-types-are-equally-useless" />
            <id>https://tomasvotruba.com/blog/not-all-mixed-types-are-equally-useless</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you have a big project where you try to raise the PHPStan level as high as possible? Yet, you're stuck on level 4 or 5 with thousands of errors? We all have one and try to chip away a few errors now and then.


The `mixed` type is the worst of all of them. Fixing all `mixed` types to a specific type is a nightmare for the REST of your life (pun intended). But what if there are places where fixing `mixed` type **brings much more value than** in the others?
 ]]>
            </summary>

            <updated>Mon, 22 Nov 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Run Naked Unit Tests in a New Legacy Project ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-run-naked-unit-tests-in-a-new-legacy-project" />
            <id>https://tomasvotruba.com/blog/how-to-run-naked-unit-tests-in-a-new-legacy-project</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You know the situation. You come to a new project that you should upgrade and refactor. It has some tests that ~~you~~ long-term developer can run locally. But the automated CI that runs tests on every commit is missing.

Shall we start refactoring and adding CI tools like PHPStan or ECS? **How about using what is already there**? The tests.

But the tests require this PHP extension, those environment variables, this external service, and these few Docker images to be running.


What if we can **find the naked unit tests** and run them today by ourselves?
 ]]>
            </summary>

            <updated>Mon, 08 Nov 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Decomposing Symfony Kernel: What does Minimal Symfony Bundle Do ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/decomposing-symfony-kernel-what-does-minimal-symfony-bundle-do" />
            <id>https://tomasvotruba.com/blog/decomposing-symfony-kernel-what-does-minimal-symfony-bundle-do</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we looked at [When Symfony Http Kernel is a Too Big Hammer to Use](/blog/when-symfony-http-kernel-is-too-big-hammer-to-use). We talked about the enormous content this package provides, but we don't need it.


Today we'll have a little self-reflecting pause in the middle of the 4-post journey. We'll look at the main glue in Symfony Kernel - the Bundle. **Can we find a way to decompose it and use it without Kernel?**
 ]]>
            </summary>

            <updated>Mon, 01 Nov 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ When Symfony Http Kernel is a Too Big Hammer to Use ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/when-symfony-http-kernel-is-too-big-hammer-to-use" />
            <id>https://tomasvotruba.com/blog/when-symfony-http-kernel-is-too-big-hammer-to-use</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I've been a big fan of Symfony components for ages. I use them as core bricks of my projects [migrate other frameworks to it](/blog/2019/08/26/how-we-migrated-54-357-lines-of-code-nette-to-symfony-in-2-people-under-80-hours), and every 6 months, I'm excited about what new features are coming in the next minor release.


But, one tough spot has been bothering me for the last 4 years. I tried to find my way out of it, hack around it or accept it. In March 2021, we [downgrade Rector 0.10 from PHP 8 to 7.1](https://getrector.com/blog/2021/03/22/rector-010-released-with-php71-support#rector-on-php-7-1-and-7-2-without-docker), and the issue became visible more than ever.


I knew there was a time for a change.
 ]]>
            </summary>

            <updated>Mon, 25 Oct 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Commands from Easy CI that Makes Your CI Stronger ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/5-commands-from-easy-ci-that-makes-your-ci-stronger" />
            <id>https://tomasvotruba.com/blog/5-commands-from-easy-ci-that-makes-your-ci-stronger</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Sometimes my clients need a specific CI check that spots tiny but annoying bugs, and they cannot be discovered by PHPStan, Rector, or coding standard tool. It can be unresolved conflict `<<<<<<`, invalid config syntax, or forgotten commented code.


Usually, we write specific PHP commands just for the particular project and let them rotten in spaghetti time. Instead, I cherry-pick those commands to **a package called `symplify/easy-ci`**. That way, I can use them in any project and improve them.


Today we'll look at 5 commands you can use in your CI. **They might save you from bugs that no other tool can check**.
 ]]>
            </summary>

            <updated>Mon, 18 Oct 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Introducing up-to 16 Times Faster Easy Coding Standard ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/introducing-up-to-16-times-faster-easy-coding-standard" />
            <id>https://tomasvotruba.com/blog/introducing-up-to-16-times-faster-easy-coding-standard</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you use [Easy Coding Standard](https://github.com/symplify/easy-coding-standard)? Do you find **extremely useful and easy to use, but a little slow on a huge code base**?


If you [follow me carefully on Twitter](https://twitter.com/votrubaT), you already know that the ECS got a new parallel run feature. I wanted to test it in a circle of early adopters first, so we make the run as smooth as possible for you.


Today, we're sharing the ECS Parallel run with the public, so you **can cut down ECS run times from minutes to seconds**.
 ]]>
            </summary>

            <updated>Mon, 11 Oct 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 7 Steps to Start with Parallel Run in PHP CLI App ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/7-steps-to-start-with-parallel-run-in-php-cli-app" />
            <id>https://tomasvotruba.com/blog/7-steps-to-start-with-parallel-run-in-php-cli-app</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ To be honest, I have no idea what I'm doing. I've read a couple of posts about parallel processes in PHP, but most got me confused even more than before. Too much vague theory links to dozens of open-source packages, 5 alternatives to one operation, and other education faults.


What I missed **was a to-do list for a 6-year old PHP programmer**. Straightforward, with everyday terminology developers, already know.


Do you want to have **a better idea of how to add a parallel run to one of PHP CLI apps**?<br>
<br>
This post will get you from 0 to padawan in a couple of minutes.
 ]]>
            </summary>

            <updated>Mon, 04 Oct 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Hidden Productivity Costs of Parallel Run ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/hidden-productivity-costs-of-parallel-run" />
            <id>https://tomasvotruba.com/blog/hidden-productivity-costs-of-parallel-run</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Have you enabled parallel run in PHPStan and ECS? You know the speed gain is brutal. On the other hand, there are **few hidden costs in developer experience** I haven't faced before.


What are they, and how to mitigate their impact?
 ]]>
            </summary>

            <updated>Mon, 27 Sep 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Parallel in PHP for Dummies Cooking a Family Dinner ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/parallel-in-php-for-dummies-cooking-a-family-dinner" />
            <id>https://tomasvotruba.com/blog/parallel-in-php-for-dummies-cooking-a-family-dinner</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Would you like to **understand parallel in PHP apps**?
<br>
Do you have just **60 seconds**?
 ]]>
            </summary>

            <updated>Mon, 20 Sep 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ STAMP #5: How do we Know Types of Template Variables ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/stamp-5-how-do-we-know-types-of-template-variables" />
            <id>https://tomasvotruba.com/blog/stamp-5-how-do-we-know-types-of-template-variables</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we finished the conversion of [TWIG to PHP, run PHPStan on temporary PHP file and got list of found errors](/blog/stamp-4-how-to-run-phpstan-rules-on-temporary-php-file). We've done a full circle, and PHPStan analyses our TWIG templates.


I've shared the intro post [on Reddit](https://www.reddit.com/r/PHP/comments/qbwudj/stamp_0_static_analysis_of_templates), that sparked many exciting questions.<br>
Today we'll answer one of them.
 ]]>
            </summary>

            <updated>Mon, 13 Sep 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ STAMP #4: How to Run PHPStan Rules on Temporary PHP File ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/stamp-4-how-to-run-phpstan-rules-on-temporary-php-file" />
            <id>https://tomasvotruba.com/blog/stamp-4-how-to-run-phpstan-rules-on-temporary-php-file</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we finished the conversion of [TWIG template to clean and objective PHP](/blog/stamp-3-how-to-turn-twig-helper-functions-to-origin-object) that PHPStan can analyze.


Today, we'll discover the last missing pieces of the puzzle. How to run PHPStan rules in temporarily compiled PHP code.
 ]]>
            </summary>

            <updated>Mon, 06 Sep 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ STAMP #3: How to Turn TWIG Helper Functions to Origin Object ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/stamp-3-how-to-turn-twig-helper-functions-to-origin-object" />
            <id>https://tomasvotruba.com/blog/stamp-3-how-to-turn-twig-helper-functions-to-origin-object</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we looked at [*how* to turn Messy TWIG PHP to something useful](/blog/stamp-2-how-to-turn-messy-twig-php-to-something-useful) in general.

Today we'll look at how to **change TWIG helper functions to their original object form**.
 ]]>
            </summary>

            <updated>Mon, 30 Aug 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ STAMP #2: How to Turn Messy TWIG PHP to Something Useful ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/stamp-2-how-to-turn-messy-twig-php-to-something-useful" />
            <id>https://tomasvotruba.com/blog/stamp-2-how-to-turn-messy-twig-php-to-something-useful</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we looked [at *how* to compile TWIG to raw PHP](/blog/stamp-1-how-to-compile-twig-to-php). It's one step forward, but it's not enough.


Today we look at *how* we turn **the raw PHP code to the code PHPStan understands**.
 ]]>
            </summary>

            <updated>Mon, 23 Aug 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ STAMP #1: How to Compile Twig to PHP ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/stamp-1-how-to-compile-twig-to-php" />
            <id>https://tomasvotruba.com/blog/stamp-1-how-to-compile-twig-to-php</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we looked [at *why* and *when* static analysis of templates matter](/blog/stamp-static-analysis-of-templates). Today we look at how to prepare a starting point for Twig templates.


How can we analyze templates with PHPStan which understands only PHP? There are 2 ways: we could teach PHPStan the language of Twig - a new "TWIGStan" tool.


The other option is to take it from the other end - convert Twig to PHP.
 ]]>
            </summary>

            <updated>Mon, 16 Aug 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ STAMP #0: Static Analysis of Templates ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/stamp-static-analysis-of-templates" />
            <id>https://tomasvotruba.com/blog/stamp-static-analysis-of-templates</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today we have static analysis checking every line of our PHP code - with PHPStan, Psalm, and PHPStorm. With php-parser and abstract syntax tree, we can do **instant changes across hundreds of files** in a second, with a precision of human hair.


With all this power and utils having our back, we can see templates as the next low-hanging fruit that needs our attention.
 ]]>
            </summary>

            <updated>Mon, 09 Aug 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Easily Protect your Code Base from Commented PHP Code ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-easily-protected-your-code-base-from-commented-php-code" />
            <id>https://tomasvotruba.com/blog/how-to-easily-protected-your-code-base-from-commented-php-code</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When it comes to merging huge pull-request, here and there, a bit of commented code slips to our codebase. Do you trust your reckless developers to check every single line? Are you sure?


We **cherish our developers' attention** so we come with a simple solution that we added to our CI. Now we know for sure. Do you think you have 0 % unwanted commented code? I dare you to have more.
 ]]>
            </summary>

            <updated>Mon, 02 Aug 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How I made Huge Mistake with Interpretation of Laravel Downloads ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-i-made-huge-mistake-with-interpretation-of-laravel-downloads" />
            <id>https://tomasvotruba.com/blog/how-i-made-huge-mistake-with-interpretation-of-laravel-downloads</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The [PHP FW Trends](/blog/sunsetting-php-framework-trends) project was introduced 2 years ago to compare download statistics over "what they say on the internet". The methodology is based on Packagist data, which worked but had some flaws.


Also, monorepo and split packages downloads lead to a problem when one monorepo download has hidden 10-30 package downloads. **There is no way to detect what packages are downloaded or used exactly**, so [this project should be stopped to avoid showing miss-leading](/blog/2020/03/09/art-of-letting-go/) data far from reality.
 ]]>
            </summary>

            <updated>Mon, 26 Jul 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ A Week in a Life of Employed Open&amp;#8209;Source Developer ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/a-week-in-a-life-of-employed-open-source-developer" />
            <id>https://tomasvotruba.com/blog/a-week-in-a-life-of-employed-open-source-developer</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Would you contribute an open-source project if it would help your private one? How do you measure such cost-effectiveness? Maybe it's better to fork the package to your own or create your single local service. But who will maintain it and write a test for it? Who will upgrade it when PHP 8 is in EOL?


I want to share my point of view on prisoners' dilemma, which you maybe know from your daily work.
 ]]>
            </summary>

            <updated>Mon, 12 Jul 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Scope Your PHP Tool in 10 Steps ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-scope-your-php-tool-in-10-steps" />
            <id>https://tomasvotruba.com/blog/how-to-scope-your-php-tool-in-10-steps</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you know PHPStan, ECS, [Monorepo Builder](https://github.com/symplify/monorepo-builder), PHPUnit, [Config Transformer](https://github.com/symplify/config-transformer) or Rector?


In the previous post, we explored [why are these tools scoped](/blog/why-do-we-scope-php-tools), where scoping makes sense and where not so much.


**Do you maintain a PHP tool that runs in the command line**? Today we'll look at 10 steps on how you can scope it too.
 ]]>
            </summary>

            <updated>Thu, 08 Jul 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why do we Scope PHP Tools ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/why-do-we-scope-php-tools" />
            <id>https://tomasvotruba.com/blog/why-do-we-scope-php-tools</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you know PHPStan, ECS, [Monorepo Builder](https://github.com/symplify/monorepo-builder), PHPUnit, [Config Transformer](https://github.com/symplify/config-transformer) or Rector?


What do they have in common? They're PHP tools you install with composer and then run in your command line. Hm, what else? **They're all scoped with help of [php-scoper](https://github.com/humbug/php-scoper).**


Do you want to make your tool resistant to any conflict with any project dependencies? Today I'll show you how.
 ]]>
            </summary>

            <updated>Mon, 05 Jul 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Replace Single Node with Two Nodes in Abstract Syntax Tree ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-replace-single-node-with-two-nodes-in-abstract-syntax-tree" />
            <id>https://tomasvotruba.com/blog/how-to-replace-single-node-with-two-nodes-in-abstract-syntax-tree</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Already over 120 people bought [the Rector book](/blog/rector-the-power-of-automated-refactoring-book-released) that we released just a month ago. The continuously growing interest in abstract syntax technology makes me very happy.


It leads to more developers **who can write their own custom Rector rules to improve their specific projects**. That leads to more "how-to" questions in the Rector repository. I've decided to answer one of the frequent ones today.
 ]]>
            </summary>

            <updated>Mon, 28 Jun 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to make Upgrade Safe with Bridge Testing ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-make-upgrade-safe-with-bridge-testing" />
            <id>https://tomasvotruba.com/blog/how-to-make-upgrade-safe-with-bridge-testing</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Upgrading can go smooth without no bugs and just work. We can make our customer happy, even though we don't have any tests.

**The older I am, the more I care about safety**. Not just for now, but for tomorrow and for my safety of my colleagues. Also for the developers, who will work on the project even though I'm long gone.

That's why before I start upgrading one approach to another, I want to prepare a safe environment. No razors, no matches, and a couple of tests. The bridge testing technique is one of the safety nets I use while refactoring to new technology.
 ]]>
            </summary>

            <updated>Mon, 21 Jun 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Doctrine Annotations and Attributes Living Together in Peace ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/doctrine-annotations-and-attributes-living-together-in-peace" />
            <id>https://tomasvotruba.com/blog/doctrine-annotations-and-attributes-living-together-in-peace</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In previous post [How to Refactor Custom Doctrine Annotations to Attributes](/blog/how-to-refactor-custom-doctrine-annotations-to-attributes) we looked on how to make the `@annotation` to `#[Attribute]` transition.


Last week, we started refactoring in [my favorite long-term project](https://www.startupjobs.cz/startup/scrumworks-s-r-o), and we came to a challenging situation. When we started to move all annotations to attributes at once, we lost control over the results. It was also impossible because 3rd party annotations were not attributes ready.


We had to **support annotations and attributes at the same time**. Do you have plenty of custom annotations yourself? In this post, you'll learn to build a bridge with both annotations and attributes on board.
 ]]>
            </summary>

            <updated>Mon, 14 Jun 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why Should We Talk about Our Mistakes in PHP Community ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/why-should-we-talk-about-our-mitakes-in-php-community" />
            <id>https://tomasvotruba.com/blog/why-should-we-talk-about-our-mitakes-in-php-community</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Sometimes we fell in love with technology or a tool. We see only the best in it, and we want everyone to know it. We're spreading the love on a wave of serotonin. We're spreading the knowledge and helping others.


As we grow and learn, we realize the path we took is not as epic as we thought. We change a direction and pick a better alternative. That's how we learn in everyday life, and it's only natural.


But what if we promote technology in a post, and that post is still out there? Readers learn from it and follow the path, even though we know it's two years old and a blind road to station frustration. What then?
 ]]>
            </summary>

            <updated>Mon, 07 Jun 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How I Redesigned my Website the Way I Refactor Legacy Projects ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-i-redesigned-my-website-the-way-i-refactor-legacy-projects" />
            <id>https://tomasvotruba.com/blog/how-i-redesigned-my-website-the-way-i-refactor-legacy-projects</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I have wanted to redesign my website since Autumn 2020. I felt it's overly detailed with attention shotgun feeling. Because of intensive && extensive work on Rector to make it better, I could not get to it on the book with Matthias and writing posts. With no deadline, there is no rush, right?

I had to hack around my brain to make it happen. It would be a shame to release Rector book on the old design, so I took [the book release](/blog/rector-the-power-of-automated-refactoring-book-released/) as a co-task.

The first hour I struggled with the redesign approach, I realized I could use the skill I use daily - refactoring legacy.
 ]]>
            </summary>

            <updated>Thu, 03 Jun 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Refactor Custom Doctrine Annotations to Attributes ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-refactor-custom-doctrine-annotations-to-attributes" />
            <id>https://tomasvotruba.com/blog/how-to-refactor-custom-doctrine-annotations-to-attributes</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ PHP 8 came with [attributes](https://php.watch/versions/8.0/attributes) 7 months ago. Symfony 5.2 now supports `#[Symfony\Component\Routing\Annotation\Route]` attribute, Nette 3.1 has `#[Nette\DI\Attributes\Inject]` attribute and Doctrine ORM 2.9 is now released with `#[Doctrine\ORM\Mapping\Entity]` attributes.

You're probably already using those [thanks to Rector](https://github.com/rectorphp/rector/blob/main/docs/rector_rules_overview.md#annotationtoattributerector). That was the easy part. The more challenging part is **custom `@annotation` classes**. Last weekend I refactored a couple of those, and this is what I found out.
 ]]>
            </summary>

            <updated>Mon, 31 May 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How Exception to the Convention Does More Harm than Good ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-exception-to-the-convention-does-more-harm-than-good" />
            <id>https://tomasvotruba.com/blog/how-exception-to-the-convention-does-more-harm-than-good</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We have a project, and to make it easier, we use specific standards. E.g., we use spaces in every file.


But sometimes, we get to a situation when these standards are stressful. We don't understand them and just want them to bend over. How does our short-term need for pleasure affects **long-term well-being** of the project?
 ]]>
            </summary>

            <updated>Mon, 24 May 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Rector - The Power of Automated Refactoring Book Released ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/rector-the-power-of-automated-refactoring-book-released" />
            <id>https://tomasvotruba.com/blog/rector-the-power-of-automated-refactoring-book-released</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In October 2020, we had a short call about Rector with [Matthias Noback](https://matthiasnoback.nl/). He asked insightful questions to the bone of the Rector workflow, and we also had great fun chatting. Soon we started to talk more and more and decided to write a book about Rector together. With 2&nbsp;points of view - **the user and the maintainer**.


It's been an adventurous journey for the past seven months, and today, we're proud to launch the first release of this book.
 ]]>
            </summary>

            <updated>Mon, 17 May 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Write GitHub Actions for Gitlab Too ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/write-github-actions-for-gitlab-too" />
            <id>https://tomasvotruba.com/blog/write-github-actions-for-gitlab-too</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In a recent post [How can We use GitHub Actions in Gitlab?](/blog/how-can-we-use-github-actions-in-gitlab), we looked at the idea, how both services could **the use same CI recipe**. As a Gitlab CI user, you can use some GitHub Actions to do the work for you.

Today we look at **how to write such action** to provide an excellent developer experience for both.
 ]]>
            </summary>

            <updated>Mon, 10 May 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ PHPStan Generics for Dummies - With 2 Parents ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/phpstan-generics-for-dummies-with-two-parents" />
            <id>https://tomasvotruba.com/blog/phpstan-generics-for-dummies-with-two-parents</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In previous post we talked about how to [promote generics to parent class](/blog/2021/01/04/phpstan-abstract-parent-generics-dummies/).
There we learned how to tell parent class what generic type we use (typically from `ProductRepository` and `AbstractRepository`).

Today we take the same use case and **add one more parent class**.

That must be easy, right?
 ]]>
            </summary>

            <updated>Mon, 03 May 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Dependency Juggling Code Smell ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/dependency-juggling-code-smell" />
            <id>https://tomasvotruba.com/blog/dependency-juggling-code-smell</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The best way to pass dependencies is via constructor injection. Only in services, we need the dependency in. I've noticed that **sometimes the dependency is passed way too early**, just to be passed to another service as a method argument.


Why is it a code smell, and how can we avoid it?
 ]]>
            </summary>

            <updated>Mon, 26 Apr 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How can We use GitHub Actions in Gitlab ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-can-we-use-github-actions-in-gitlab" />
            <id>https://tomasvotruba.com/blog/how-can-we-use-github-actions-in-gitlab</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ One of my customers is building a monorepo, so we prepared a prototype on GitHub to test it out. It uses [Monorepo Split GitHub Action](/blog/monorepo-split-github-action-20-with-gitlab-split-is-out/) and works well.


You know [I'm a big fan of GitHub](/blog/best-time-to-switch-gitlab-to-github), so when client asked me: **"how can we do it in Gitlab?"**
<br>
I was like: "that's not possible... you need to switch to GitHub".
 ]]>
            </summary>

            <updated>Mon, 19 Apr 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 2 Ways to Write Big Numbers More Readable ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2ways-to-write-big-numbers-more-readable" />
            <id>https://tomasvotruba.com/blog/2ways-to-write-big-numbers-more-readable</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Have you seen a number in your code that does not make any sense? We don't talk about 1, 2, or 3. I mean big numbers like 965039008. How would you spell it when support asks you for your account ID?


**There are two ways to make big numbers more readable**. Instant and easy ways that I found mostly by accident. We use them both in one big project, and it makes our daily number work so much easier I want to share them with you.
 ]]>
            </summary>

            <updated>Mon, 12 Apr 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Monorepo Split GitHub Action 2.0 with Gitlab split is Out! ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/monorepo-split-github-action-20-with-gitlab-split-is-out" />
            <id>https://tomasvotruba.com/blog/monorepo-split-github-action-20-with-gitlab-split-is-out</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ [The version 1.0 was released 6 months ago](/blog/2020/11/09/new-in-symplify-9-monorepo-split-with-github-action). Compared to its ancestors, it speed up the split from **2 minutes to 10 seconds**.


After 6 months of collecting feedback and adding new features, version 2.0 is here!

**How to use it with GitLab split repositories and custom git hosting?**
 ]]>
            </summary>

            <updated>Mon, 05 Apr 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Traverse PHPDoc and Modify It ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/how-to-traverse-phpdoc-and-modify-it" />
            <id>https://tomasvotruba.com/blog/how-to-traverse-phpdoc-and-modify-it</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Traversing and modifying PHP code is possible thanks to the amazing tool [php-parser](https://github.com/nikic/PHP-Parser) written by Nikita Popov. Rector can work thanks to **node traverser**, which can get to any node abstract syntax tree. Do you want to replace all numbers with `1000`? I wrote about it in [How to change PHP code with Abstract Syntax Tree](/blog/2017/11/06/how-to-change-php-code-with-abstract-syntax-tree/).

But what about docblocks - how **can we rename classes in `@var` annotation or replace `integer` with `int`**?


Is that even possible without using complex nested structures or regular expressions?
 ]]>
            </summary>

            <updated>Mon, 29 Mar 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Never Forget Symfony Config Options Again ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/never-forget-symfony-config-options-again" />
            <id>https://tomasvotruba.com/blog/never-forget-symfony-config-options-again</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Have you switched your Symfony configs from **stringy YAML to typed PHP**? If not, [do it now](/blog/2020/07/27/how-to-switch-from-yaml-xml-configs-to-php-today-with-migrify/). Here is [at least 10 reasons why](/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs/).
Only then you'll start to notice a code smell that was there in every YAML configs.


Just now, the code smell is too smelly to ignore.
 ]]>
            </summary>

            <updated>Mon, 15 Mar 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ It&#039;s not Null, it&#039;s Enum ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/its-not-null-null-its-enum" />
            <id>https://tomasvotruba.com/blog/its-not-null-null-its-enum</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last weekend I got into reading a good old post [Null Hell](https://afilina.com/null-hell) by Afilina, a fellow legacy archeologist. Null parameters are evil, which turns code into "maybe" and "just in case" conditions with ifs everywhere.


I was wondering how difficult it is to get rid of nullable parameters in a project. I made myself a challenge: **get rid of nullable params over the weekend**. This is what happened.
 ]]>
            </summary>

            <updated>Mon, 22 Feb 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Tree Coding vs. Bush Coding ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2021/02/11/tree-coding-vs-bush-coding" />
            <id>https://tomasvotruba.com/blog/2021/02/11/tree-coding-vs-bush-coding</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ How does circular reference look like? It is a point where you wait for your doctor; they wait for a state to accept the vaccine, and the state waits on people like you to come to the doctor. **Who has the responsibility?** Who can change the state?


In the past, we used singletons and static calls to get anything anywhere instantly. But soon, we got into the circular references trap. Now **we moved to dependency injection** and this problem does not exist anymore... or does it?
 ]]>
            </summary>

            <updated>Thu, 11 Feb 2021 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why Coding Standards Should Not Be Part of CI ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/12/28/why-coding-standards-should-not-be-part-of-ci" />
            <id>https://tomasvotruba.com/blog/2020/12/28/why-coding-standards-should-not-be-part-of-ci</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Why do you use coding standards? To standardize the design of your code so that any contributor will produce somewhat similar PHP code.


Where do we use it? In CI pipelines on every pull-request, locally in a command line or within PHPStorm.
**Now take these 3 places and drop coding standard from them.**
 ]]>
            </summary>

            <updated>Mon, 28 Dec 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 New Combos opened by Symfony 5.2 and PHP 8.0 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/12/21/5-new-combos-opened-by-symfony-52-and-php-80" />
            <id>https://tomasvotruba.com/blog/2020/12/21/5-new-combos-opened-by-symfony-52-and-php-80</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Conjunction of 2 releases came in December 2020, Symfony 5.2 and [PHP 8.0](https://getrector.com/blog/2020/11/30/smooth-upgrade-to-php-8-in-diffs).
I wanted to give them a fresh try, so I've updated `composer.json` in 3 projects, run the Rector upgrade set, and this happened...
 ]]>
            </summary>

            <updated>Mon, 21 Dec 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ New in Symplify 9: More than 110 PHPStan Rules ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/12/14/new-in-symplify-9-more-than-110-phpstan-rules" />
            <id>https://tomasvotruba.com/blog/2020/12/14/new-in-symplify-9-more-than-110-phpstan-rules</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In Symplify 8, a bunch of PHP rules was part of the symplify/coding-standard package.
It was a mix of too many tools, so we decided to **decouple a new package - symplify/phpstan-rules**.


During summer 2020, our Rector team grew from 1 member to 4. To keep onboarding smooth, we started to use PHPStan **to help with code-reviews in Rector**. We got obsessed with [moving human code-reviews to CI](/blog/2019/11/18/how-to-delegate-code-reviews-to-ci/).


Was it worth it? Hell yea!
 ]]>
            </summary>

            <updated>Mon, 14 Dec 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ New in Symplify 9: Documentation Generator for PHP CS Fixer, Code Sniffer, PHPStan and Rector Rules ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/11/30/new-in-symplify-9-documentation-generator-for-php-cs-fixer-code-sniffer-phpstan-rector-rules" />
            <id>https://tomasvotruba.com/blog/2020/11/30/new-in-symplify-9-documentation-generator-for-php-cs-fixer-code-sniffer-phpstan-rector-rules</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Rector is providing rules, so is PHPStan and PHP CS Fixer, and Code Sniffer. If you use only 5-10 rules and want to share them with the world, you create a README and describe them.

In Rector, we now have over 640 rules, in Symplify 110 rules for PHPStan and 15 rules for PHP CS Fixer. **How can we handle documentation for this amount of rules without going crazy?**
 ]]>
            </summary>

            <updated>Mon, 30 Nov 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to make a Dynamic Matrix in GitHub Actions ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/11/16/how-to-make-dynamic-matrix-in-github-actions" />
            <id>https://tomasvotruba.com/blog/2020/11/16/how-to-make-dynamic-matrix-in-github-actions</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you want [split monorepo](/blog/2020/11/09/new-in-symplify-9-monorepo-split-with-github-action) for each package?
Instead of 20 workflows with copy-paste steps, you can define **just one with a static matrix for packages**.


Yet, nothing in real life is static but rather dynamic. A new package can be added, old can be removed.
How could we automate this even more with a **dynamic matrix?**
 ]]>
            </summary>

            <updated>Mon, 16 Nov 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Split Test Monorepo with Composer 2 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/10/19/how-to-split-test-monorepo-with-composer-2" />
            <id>https://tomasvotruba.com/blog/2020/10/19/how-to-split-test-monorepo-with-composer-2</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ [Composer 2 was released](https://twitter.com/packagist/status/1319945203797708800) this week. It brings **massive `composer install/update` performance** improvement of [150-200 %](https://blog.packagist.com/composer-2-0-is-now-available).

That means [faster feedback](/blog/2020/01/13/why-is-first-instant-feedback-crucial-to-developers/) from CI and faster monorepo testing.

Today, we'll look on how to use Composer in Github Actions with monorepo split testing and what to avoid.
 ]]>
            </summary>

            <updated>Mon, 19 Oct 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How We Stopped Merging Pull Requests ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/10/12/how-we-stopped-merging-pull-requests" />
            <id>https://tomasvotruba.com/blog/2020/10/12/how-we-stopped-merging-pull-requests</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ What comes before merging a pull request? Code-review, feedback from developers, and fixes to make the reviewer happy. After that, we only need the tests, coding standard, PHPStan, and Rector to pass in the CI.


Here is an idea - **don't merge any pull-request from now on**...
 ]]>
            </summary>

            <updated>Mon, 12 Oct 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Add Colors to Continuous Integration Output ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/09/28/how-to-add-colors-to-continuous-integration-output" />
            <id>https://tomasvotruba.com/blog/2020/09/28/how-to-add-colors-to-continuous-integration-output</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today I have a tip for your CI. I learned this tip from [Jan Mikes](https://github.com/JanMikes).

A small tip that made my everyday work with CI more colorful.
 ]]>
            </summary>

            <updated>Mon, 28 Sep 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Symfony AutoBind Parameter is Dead, Long live Constant Parameters ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/09/21/symfony-autobind-parameter-is-dead-long-live-constant-parameters" />
            <id>https://tomasvotruba.com/blog/2020/09/21/symfony-autobind-parameter-is-dead-long-live-constant-parameters</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I wrote the [Do you Autowire Services in Symfony? You can Autowire Parameters Too](/blog/2018/11/05/do-you-autowire-services-in-symfony-you-can-autowire-parameters-too/) almost 2 years ago. It seemed like a good idea at that time, to save manual YAML config wiring.


Now, with [PHP configs](/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs/) on the Symfony markets, auto bind parameters became obsolete.


Welcome **constant parameters**.
 ]]>
            </summary>

            <updated>Mon, 21 Sep 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Apply Coding Standard on PHP Snippets in Markdown Files ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/09/14/how-to-apply-coding-standard-on-php-snippets-in-markdown-files" />
            <id>https://tomasvotruba.com/blog/2020/09/14/how-to-apply-coding-standard-on-php-snippets-in-markdown-files</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Have you been asking this question since the inventions of coding standards? Do you write `README.md`?
If you maintain an open-source project, you do.


Coding standards are a matter of adding a few lines into `composer.json` and your favorite CI.
**But what about `README.md` files?

Who will take care of them?** Should we accept clean code in `/src`, but crap code in PHP snippets in Markdown? What if someone reading `README.md` will adopt its bad coding habits?


I say: "We shall not!"
 ]]>
            </summary>

            <updated>Mon, 14 Sep 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How Static Methods Kill You Like Corona ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/08/31/how-static-methods-kills-you-like-corona" />
            <id>https://tomasvotruba.com/blog/2020/08/31/how-static-methods-kills-you-like-corona</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you know [the Broken Window theory](https://blog.codinghorror.com/the-broken-window-theory/)? It's a social pattern in code, a great post written by a guy behind one small manual website - StackOverflow.


If you combine this theory and Static Methods in Your code, you'll get Corona. As we already know, it might or might not be deadly. How it spreads, what are ways to protect, can we cure it?
 ]]>
            </summary>

            <updated>Mon, 31 Aug 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ What if We Remove Strings from Symfony Extension Configuration ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/08/24/what-if-we-remove-strings-from-symfony-extension-configuratoin" />
            <id>https://tomasvotruba.com/blog/2020/08/24/what-if-we-remove-strings-from-symfony-extension-configuratoin</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You can tell I'm a [huge fan PHP configs](/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs/). To be honest, I don't care; I'm just extremely lazy.


Yet, my laziness got me itching when I see **configuration of extensions**.
 ]]>
            </summary>

            <updated>Mon, 24 Aug 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Get Rid of Magic, Static and Chaos from Latte Filters ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/08/17/how-to-get-rid-of-magic-static-and-chaos-from-latte-filters" />
            <id>https://tomasvotruba.com/blog/2020/08/17/how-to-get-rid-of-magic-static-and-chaos-from-latte-filters</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ [In the previous post](/blog/2020/08/10/4-ways-to-make-your-nette-project-more-readable/), we looked at how to avoid array magic and duplicates of Latte in Presenter and Components.

Today we'll leverage those tips to make your code around Latte filters **easy and smooth to work with**.
 ]]>
            </summary>

            <updated>Mon, 17 Aug 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Give Away 1500 € in 1 Tweet and Help 25 People Learn Something New ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/08/03/how-give-away-1500-eur--in-1-tweet-and-help-25-people-learn-something-new" />
            <id>https://tomasvotruba.com/blog/2020/08/03/how-give-away-1500-eur--in-1-tweet-and-help-25-people-learn-something-new</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ What makes one give?


For me, it's a combination of gratitude, abundance, and inspiration in the surrounding.
 ]]>
            </summary>

            <updated>Mon, 03 Aug 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Switch from YAML Configs to PHP Today with Symplify ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/07/27/how-to-switch-from-yaml-xml-configs-to-php-today-with-migrify" />
            <id>https://tomasvotruba.com/blog/2020/07/27/how-to-switch-from-yaml-xml-configs-to-php-today-with-migrify</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In [previous post](/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs/), we looked 10 reasons to switch from YAML to PHP configs. Still asking *why*? I dare you to [disagree with 1 reason there](/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs/).


If you have 1 config file, you already are on PHP side now. Close this post and enjoy life.


But what if you have 10 or even 100 YAML configs? Are you doing to close down for a weekend to switch your code base?

Or maybe... **5 minute job**?
 ]]>
            </summary>

            <updated>Mon, 27 Jul 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Update Hundreds of Test Fixtures with Single PHPUnit run ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/07/20/how-to-update-hundreds-of-test-fixtures-with-single-phpunit-run" />
            <id>https://tomasvotruba.com/blog/2020/07/20/how-to-update-hundreds-of-test-fixtures-with-single-phpunit-run</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In [previous post](/blog/2020/07/13/the-most-effetive-test-i-found-in-7-years-of-testing/), we look at the benefits of visual snapshot testing for lazy people. How bare *input/output* code in a single file makes tests easy to read for new contributors.


Today, we look at **how to maintain visual snapshot tests**.


Let's say we need to add `declare(strict_types=1);` to output part of 100 test fixtures? Would you add it manually in every single file?
 ]]>
            </summary>

            <updated>Mon, 20 Jul 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 10 Cool Features You Get after switching from YAML to PHP Configs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs" />
            <id>https://tomasvotruba.com/blog/2020/07/16/10-cool-features-you-get-after-switching-from-yaml-to-php-configs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You've probably noticed [Symfony is moving towards PHP configuration](https://github.com/symfony/symfony/issues/37186). If you're on XML or YAML, you'll most likely migrate to PHP with upcoming Symfony 6.

There are already tools that [can help you migrate today](https://twitter.com/VotrubaT/status/1283003111074922497) - **so it's not a matter of work, but a matter of choice**.

Today we look at 10 cool features you get by switching to PHP configs that make you an even lazier programmer.
 ]]>
            </summary>

            <updated>Thu, 16 Jul 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The most Effective Test I found in 7 years of Testing ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/07/13/the-most-effetive-test-i-found-in-7-years-of-testing" />
            <id>https://tomasvotruba.com/blog/2020/07/13/the-most-effetive-test-i-found-in-7-years-of-testing</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you test your projects with automated tests? If not, would you like to start?
Do you work with application, integration, functional, unit, and Selenium layers and drive you crazy? Do you spend more time writing tests than the actual code behind them?


I want my **tests to be simple, effective, and fun to write and maintain**. Today, we look at one approach used by [PHP itself](https://github.com/php/php-src), `nikic/php-parser`. It's so good I'm surprised not everyone is using it.
 ]]>
            </summary>

            <updated>Mon, 13 Jul 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Cleaning Lady Notes: From Class Mess to PSR-4 Step by Step With Confidence ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/07/06/cleaning-lady-notes-from-class-mess-to-psr4-step-by-step-with-confidence" />
            <id>https://tomasvotruba.com/blog/2020/07/06/cleaning-lady-notes-from-class-mess-to-psr4-step-by-step-with-confidence</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today I'm starting a new post series - *Cleaning Notes*. These posts are for people who are [aspiring legacy migrators](/blog/2020/06/29/how-will-programming-look-like-in-2025/) with a vision to improve private PHP ecosystem and bring joy to coding with gigantic applications again. The same vision we have in the Rector team.


In this series, you can learn about my experience, tricks, tips, and what fucked me up. So you **save some frustration, where is not needed, discover hidden shortcuts and cool tools you never saw before**.


We start with the most problematic topic in PHP legacy, that every project needs, but almost none has - **transition to [PSR-4](https://www.php-fig.org/psr/psr-4)**.
 ]]>
            </summary>

            <updated>Mon, 06 Jul 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Patch a Package in Vendor, Yet Allow its Updates ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/07/02/how-to-patch-package-in-vendor-yet-allow-its-updates" />
            <id>https://tomasvotruba.com/blog/2020/07/02/how-to-patch-package-in-vendor-yet-allow-its-updates</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ While working with legacy code upgrades, we often need to fix a line or two in 3rd party package in `/vendor`.

You can fork it, but by that, you **take manual responsibility** for all the package updates.
You can copy a package locally, which is faster, but **disables package updates**.


Or... you can use "composer patches"?
 ]]>
            </summary>

            <updated>Thu, 02 Jul 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How Will Programming look like in 2025 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/06/29/how-will-programming-look-like-in-2025" />
            <id>https://tomasvotruba.com/blog/2020/06/29/how-will-programming-look-like-in-2025</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We often read about best practices in coding, what framework has new features, or what is new in PHP X. How one can change this to that, why is this technique good or bad, or what new package you can download to your project.
<br>
That's only past or present.

I'm just finishing the reading of [The Inevitable](https://www.amazon.com/The-Inevitable-Kevin-Kelly-audiobook/dp/B01EB3OR32), written by Wired magazine founder, that focuses solely on the future. Inspired by this book, today, **we look at the future of programming**.
 ]]>
            </summary>

            <updated>Mon, 29 Jun 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why Class Constants Should be Typed ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/06/22/why-class-constants-should-be-typed" />
            <id>https://tomasvotruba.com/blog/2020/06/22/why-class-constants-should-be-typed</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you use PHP 7.4 [typed properties](/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds/)? Do you know why?

I use them, so **I don't have to think and validate the property type** every time. We just know its type or PHP would crash otherwise.

Until PHP 7.4 this was not possible and code was kinda crappy.
Where are we now with constant type? Do you trust your class constants type?
 ]]>
            </summary>

            <updated>Mon, 22 Jun 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Drop RobotLoader and let Composer Deal with Autoloading ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/06/08/drop-robot-loader-and-let-composer-deal-with-autoloading" />
            <id>https://tomasvotruba.com/blog/2020/06/08/drop-robot-loader-and-let-composer-deal-with-autoloading</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Using 2 tools for one thing, in this case 2 packages to autoload classes, are sign of an architecture smell. Many applications I see contain RobotLoader for historical reasons. I will borrow this from psychology: pathological behavioral patterns tear us down in the present, but were useful in past.


The best way to deal with them is acknowledge their purpose and then, let them go and enjoy the gift of present.
 ]]>
            </summary>

            <updated>Mon, 08 Jun 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The Bulletproof Event Naming For Symfony Event Dispatcher ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/05/25/the-bulletproof-event-naming-for-symfony-event-dispatcher" />
            <id>https://tomasvotruba.com/blog/2020/05/25/the-bulletproof-event-naming-for-symfony-event-dispatcher</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I wrote [intro to Symfony\EventDispatcher](/blog/2019/08/05/standalone-symfony-event-dispatcher-from-the-scratch/) and how to use it with simple event.


But when it comes to dispatching events, you can choose from 4 different ways. Which one to choose and why? Today I will show you pros and cons of them to make it easier for you.
 ]]>
            </summary>

            <updated>Mon, 25 May 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The Future of Pehapkari Meetups and Training - You ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/05/18/the-future-of-pehapkari-meetups-and-trainings-you" />
            <id>https://tomasvotruba.com/blog/2020/05/18/the-future-of-pehapkari-meetups-and-trainings-you</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last 2 months gave lot of time to reflect my activities, work and hobbies. One of the topic I think about a lot is our Czech PHP Community - [Pehapkari](https://pehapkari.cz). I felt like last year I'm not giving it as much energy as before. But why?
 ]]>
            </summary>

            <updated>Mon, 18 May 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Upgrade to Symplify 8 - From Sniffs to PHPStan Rules ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/05/04/how-to-upgrade-to-symplify-8-from-sniffs-to-phpstan-rules" />
            <id>https://tomasvotruba.com/blog/2020/05/04/how-to-upgrade-to-symplify-8-from-sniffs-to-phpstan-rules</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Since Symplify 7.3, you might notice a few deprecation notices in your coding standards. As Symplify 8 release is [synced with Symfony cycle](/blog/2017/10/30/what-can-you-learn-from-menstruation-and-symfony-releases/), both will be released at the end of May.

What to do with these deprecations? Why were these sniffs dropped? How to handle upgrades in 1 hour?
 ]]>
            </summary>

            <updated>Mon, 04 May 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Hydrate Arrays to Objects via Constructor ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/04/20/how-to-hydrate-arrays-to-objects-via-constructor" />
            <id>https://tomasvotruba.com/blog/2020/04/20/how-to-hydrate-arrays-to-objects-via-constructor</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ One technology evolution sparks naturally another one. When electricity became accessible to masses, a huge industry of home-electric tools became possible. Like this tool, I currently write on.


The same thing happens in software, just exponentially faster. Like tokens and AST sparked [tools that change your code](/blog/2018/10/22/brief-history-of-tools-watching-and-changing-your-php-code/).


Recently, I introduced [Symfony Static Dumper](/blog/2020/03/16/statie-is-dead-long-live-symfony-static-dumper/) that uses YAML to store data in your Symfony application. You where this goes... how can **we turn this YAML into objects**?
 ]]>
            </summary>

            <updated>Mon, 20 Apr 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Migrate Spaghetti to 304 Symfony 5 Controllers Over Weekend ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/04/13/how-to-migrate-spaghetti-to-304-symfony-5-controllers-over-weekend" />
            <id>https://tomasvotruba.com/blog/2020/04/13/how-to-migrate-spaghetti-to-304-symfony-5-controllers-over-weekend</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ During Easter weekend, usually, people take a break and have a rest. Instead, we used these 4 days of *holiday* to migrate the 304-controller application. At least that was the goal on Friday.


Me in my colleague in the migrated project accepted the challenge. We got into many minds and code-traps. We'd like to share this experience with you and **inspire those who are still stuck on non-MVC code** and think it might take weeks or even months to switch to a framework.
 ]]>
            </summary>

            <updated>Mon, 13 Apr 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Doctrine Entity Typed Properties With PHP 7.4 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/03/23/doctrine-entity-typed-properties-with-php74" />
            <id>https://tomasvotruba.com/blog/2020/03/23/doctrine-entity-typed-properties-with-php74</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Recently we've upgraded our [Czech PHP community website](https://pehapkari.cz) to PHP 7.4. As a side effect, it broke most of our entities.
Do you love how making language more strict reveals weak points in your code just by using it?

Today we'll look at **the impact of typed properties on weak points of Doctrine entities and how to solve them**.
 ]]>
            </summary>

            <updated>Mon, 23 Mar 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Art of Letting Go ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/03/09/art-of-letting-go" />
            <id>https://tomasvotruba.com/blog/2020/03/09/art-of-letting-go</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Recently I come to a dead end with one of my projects. I felt it doesn't bring value to me, to people that use it, and to neither to the open-source community. I felt sour about it for the last 3 months, confused about what to do next.
 ]]>
            </summary>

            <updated>Mon, 09 Mar 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ We Do Not Need Senior Developers, We Need Senior Codebases ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/03/02/we-do-not-need-senior-developers-we-need-senior-code-bases" />
            <id>https://tomasvotruba.com/blog/2020/03/02/we-do-not-need-senior-developers-we-need-senior-code-bases</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ "We're looking for a Senior PHP Developer."

 "Are you a senior or a junior?"

 "How many senior developers does your company have?"

These and similar questions come to appear when you're looking for a job. The IT market says it needs more senior developers.


I think there is more than enough. What we need are **senior codebases**.
 ]]>
            </summary>

            <updated>Mon, 02 Mar 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Test Monorepo After Split Before Actual Split ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/02/10/how-to-test-monorepo-after-split-before-actual-split" />
            <id>https://tomasvotruba.com/blog/2020/02/10/how-to-test-monorepo-after-split-before-actual-split</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In 14 months old post [How to Test Monorepo in 3 Layers](/blog/2018/11/22/how-to-test-monorepo-in-3-layers/#3-after-split-testing) we talked about testing monorepo in 3 layers. So you can be sure every package works as it should.

3 layers are testing in a monorepo, testing package directory, and testing after a split.
**The latter takes a huge amount of time**. The time we don't have to spare in 2020.

**How can we make it faster while keeping the test quality high?**
 ]]>
            </summary>

            <updated>Mon, 10 Feb 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to run Rector and PHPStan on Huge Project in 3 Seconds with PHPStorm ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/02/03/how-to-run-rector-and-phpstan-on-huge-project-in-3-seconds-with-phpstorm" />
            <id>https://tomasvotruba.com/blog/2020/02/03/how-to-run-rector-and-phpstan-on-huge-project-in-3-seconds-with-phpstorm</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today we'll look at the command line and run performance heavy dev tools like Rector or PHPStan on our projects. I'm guessing that it takes more than 10 seconds to run whatever project you use.

How would you like it be **less than 3 seconds with just one click** in PHPStorm?
 ]]>
            </summary>

            <updated>Mon, 03 Feb 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Switch Travis to GitHub Actions to Reduce Stress ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/01/27/switch-travis-to-github-actions-to-reduce-stress" />
            <id>https://tomasvotruba.com/blog/2020/01/27/switch-travis-to-github-actions-to-reduce-stress</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the previous post, we looked at [Why is First Instant Feedback Crucial to Developers?](/blog/2020/01/13/why-is-first-instant-feedback-crucial-to-developers/).


We know why now we look at *how*. How exactly migrate all jobs from Travis to GitHub Actions, **reduce stress from long feedback loops** and live a more healthy life as a programmer.


Yes, in code samples :)
 ]]>
            </summary>

            <updated>Mon, 27 Jan 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why is First Instant Feedback Crucial to Developers ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/01/13/why-is-first-instant-feedback-crucial-to-developers" />
            <id>https://tomasvotruba.com/blog/2020/01/13/why-is-first-instant-feedback-crucial-to-developers</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you *open-source*? Then you know that instant feedback is crucial to your contributors. The same applies to private companies.

There are **2 types of feedback**: from human and machine.

Which and how can we improve?
 ]]>
            </summary>

            <updated>Mon, 13 Jan 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Migrate Gedmo to KnpLabs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2020/01/06/migrate-gedmo-to-knplabs" />
            <id>https://tomasvotruba.com/blog/2020/01/06/migrate-gedmo-to-knplabs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ With [Symfony 5 upgrade](/blog/2019/09/09/how-we-upgraded-pehapkari-cz-from-symfony-4-to-5-in-25-days/), we need any *working* Doctrine behaviors.
<br>
Month later, we have [KnpLabs\DoctrineBehaviors 2.0](/blog/2019/12/30/doctrine-behaviors-2-0-reloaded/#how-do-you-migrate-from-gedmo-stof-to-knplabs-doctrinebehaviors) with full Symfony 5 support.

If you used older Doctrine Behaviors, you're covered with Rector migration path.
<br>
But what if you're using old broken Gedmo?

**I'll show you how you can migrate Gedmo to KnpLabs**.
 ]]>
            </summary>

            <updated>Mon, 06 Jan 2020 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Doctrine Behaviors 2.0 - Reloaded ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/12/30/doctrine-behaviors-2-0-reloaded" />
            <id>https://tomasvotruba.com/blog/2019/12/30/doctrine-behaviors-2-0-reloaded</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In [How we Upgraded Pehapkari.cz from Symfony 4 to 5 in 25 days](/blog/2019/09/09/how-we-upgraded-pehapkari-cz-from-symfony-4-to-5-in-25-days//) post, there is a section about Doctrine Behaviors in Symfony 5.


**None of stof, gedmo, nor KnpLabs is working with Symfony 5**. There are many issues in each of those projects asking for maintainers to merge PRs and tag it. One of those issues was heard, and the owner gave me maintainer access.


How does it look 3 weeks later?
 ]]>
            </summary>

            <updated>Mon, 30 Dec 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Things I Improve when I Get to new Repository ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/12/23/5-things-i-improve-when-i-get-to-new-repository" />
            <id>https://tomasvotruba.com/blog/2019/12/23/5-things-i-improve-when-i-get-to-new-repository</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I started to write this post as follow up for [clean and sustainable code](/blog/2019/12/16/8-steps-you-can-make-before-huge-upgrade-to-make-it-faster-cheaper-and-more-stable/) post. In the middle of writing, I've realized I have this approach to ever repository I meet.

Imagine it like a working desk. But not your usual stable place where you work every day. **Instead, you are assigned to a new desk of a former employee, who worked in the company for 5 years and as a bonus - it was the CTO**. For you, it's a mess.

What is the first thing we do? We'll **prepare it for hard work**.
 ]]>
            </summary>

            <updated>Mon, 23 Dec 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 8 Steps You Can Make Before Huge Upgrade to Make it Faster, Cheaper and More Stable ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/12/16/8-steps-you-can-make-before-huge-upgrade-to-make-it-faster-cheaper-and-more-stable" />
            <id>https://tomasvotruba.com/blog/2019/12/16/8-steps-you-can-make-before-huge-upgrade-to-make-it-faster-cheaper-and-more-stable</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ "How much will cost upgrade from Symfony 3 to Symfony 4 with Rector?"


Similar questions fill my personal and [Rector email](https://getrector.com/contact) in the last 3 months. It's hard to give a reasonable answer without actually seeing the repository, so I reply with follow-up questions to get get more details.


Yet, I've discovered there are few repeated patterns, that make the upgrade easier and that **most projects can do by themselves** before migration starts.
 ]]>
            </summary>

            <updated>Mon, 16 Dec 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Get Rid of Technical Debt or What We Would Have Done Differently 2 Years ago ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/12/09/how-to-get-rid-of-technical-debt-or-what-we-would-have-done-differently-2-years-ago" />
            <id>https://tomasvotruba.com/blog/2019/12/09/how-to-get-rid-of-technical-debt-or-what-we-would-have-done-differently-2-years-ago</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We talked about cleaning legacy code with Rector 2 months ago on 40th meetup of PHP friends in Prague.
<br>
Who is *we*? Me and CTO of the [company I worked for](https://spaceflow.io/en), a great leader and technical expert who taught me a lot, [Milan Mimra](https://www.linkedin.com/in/milanmimra).

The talk was not full of shallow tips, nor [about framework migration](/blog/2019/08/26/how-we-migrated-54-357-lines-of-code-nette-to-symfony-in-2-people-under-80-hours/). Instead, **we talked about small decisions that were made 2 years. Decisions, which took 3 months to get rid of**.
 ]]>
            </summary>

            <updated>Mon, 09 Dec 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The Single Best Skill to Master Command Line ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/11/25/the-single-best-skill-to-master-command-line" />
            <id>https://tomasvotruba.com/blog/2019/11/25/the-single-best-skill-to-master-command-line</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I have a confession to make. I'm very poor with memory stuff. My brain is using neurons to mostly process data, instead of keeping them.


I'm very poor with memory stuff. So I use shortcuts, both in brain and code, that make me look smart. I don't like remember stuff, **I won't enjoy them and use them**.


Accidentally, **my poor memory makes me the most productive programmer in the room**. And you can be too. How?
 ]]>
            </summary>

            <updated>Mon, 25 Nov 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Delegate Code Reviews to CI ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/11/18/how-to-delegate-code-reviews-to-ci" />
            <id>https://tomasvotruba.com/blog/2019/11/18/how-to-delegate-code-reviews-to-ci</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Are you doing code reviews? No? Yes?

**In both cases, you won't have too**. Just add a couple of YAML lines to your CI.
 ]]>
            </summary>

            <updated>Mon, 18 Nov 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ From 0 Doc Types to Full Type Declaration with Dynamic Analysis ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/11/11/from-0-doc-types-to-full-type-declaration-with-dynamic-analysis" />
            <id>https://tomasvotruba.com/blog/2019/11/11/from-0-doc-types-to-full-type-declaration-with-dynamic-analysis</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I wrote [How we Completed Thousands of Missing @var Annotations in a Day](/blog/2019/07/29/how-we-completed-thousands-of-missing-var-annotations-in-a-day/). If you have at least some annotations, you can use Rector to do the dirty work.

To be honest, open-source is the top 1 % code there is, but out **in the wild of ~~legacy~~ established PHP companies, it's a miracle to see just one `string` type declaration**.

Are these projects lost? Do you have to quit them? And what if the annotations are lying?
 ]]>
            </summary>

            <updated>Mon, 11 Nov 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Still on PHPUnit 4 Come to PHPUnit 8 Together in a Day ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/11/04/still-on-phpunit-4-come-to-phpunit-8-together-in-a-day" />
            <id>https://tomasvotruba.com/blog/2019/11/04/still-on-phpunit-4-come-to-phpunit-8-together-in-a-day</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last month I was on [PHPSW meetup](https://twitter.com/akrabat/status/1181998973588037632) in Bristol UK with Rector talk. To be honest, [Nette to Symfony migration under 80 hours](/blog/2019/08/26/how-we-migrated-54-357-lines-of-code-nette-to-symfony-in-2-people-under-80-hours/) was not a big deal there.


To my surprise, **upgrading PHPUnit tests was**. So I was thinking, let's take it from the floor in one go, from PHPUnit 4 to the latest PHPUnit 8.
 ]]>
            </summary>

            <updated>Mon, 04 Nov 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How we Migrated 54 357-lines Application from Nette to Symfony in 2 People under 80 Hours ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/08/26/how-we-migrated-54-357-lines-of-code-nette-to-symfony-in-2-people-under-80-hours" />
            <id>https://tomasvotruba.com/blog/2019/08/26/how-we-migrated-54-357-lines-of-code-nette-to-symfony-in-2-people-under-80-hours</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ It would take us **3 full-time months** to rewrite this code in 2017. In February 2019, we did it **in less than 3 weeks** with the help of automated tools. Why and how?
 ]]>
            </summary>

            <updated>Mon, 26 Aug 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How we Completed Thousands of Missing @var Annotations in a Day ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/07/29/how-we-completed-thousands-of-missing-var-annotations-in-a-day" />
            <id>https://tomasvotruba.com/blog/2019/07/29/how-we-completed-thousands-of-missing-var-annotations-in-a-day</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I'm currently working as Rector consultant for [Spaceflow](https://spaceflow.io/en), Prague-based rising startup with very nice codebase. One of the pre-requisites for Rector is to have code that static analyser can work with. PHPStan that Rector uses depends on `@var` annotations and not every property had that. Well... **over 2500 of them**.


I'll show you how we completed them without any manual change of the code and how you can do the same... today.
 ]]>
            </summary>

            <updated>Mon, 29 Jul 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Convert Listeners to Subscribers and Reduce your Configs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/07/22/how-to-convert-listeners-to-subscribers-and-reduce-your-configs" />
            <id>https://tomasvotruba.com/blog/2019/07/22/how-to-convert-listeners-to-subscribers-and-reduce-your-configs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I wrote [Don't Ever use Symfony Listeners](/blog/2019/05/16/don-t-ever-use-listeners/) 2 months ago (if you missed it, be sure to read it to better understand this 2nd part). It got many constructive comments, mostly focused on particular standalone sentences without context.

To my surprise, **none of the comments shown that listener beats subscriber**.<br>
But what can you do, if you'd like to try subscribers, but currently have over 100 listeners in your application?
 ]]>
            </summary>

            <updated>Mon, 22 Jul 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why use One-Time Migration Scripts ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/07/15/why-use-one-time-migration-scripts" />
            <id>https://tomasvotruba.com/blog/2019/07/15/why-use-one-time-migration-scripts</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ School system taught me to despise old books and consider them outdated, rather about stories than knowledge. I wanted to prove I'm right, so I've read [Pragmatic Programmer](https://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X) from 1999 and *you won't believe what happened*...
 ]]>
            </summary>

            <updated>Mon, 15 Jul 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 7 Tips to Write Flawless Issue Reports on Github ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/07/08/7-tips-to-write-flawless-issue-report-on-github" />
            <id>https://tomasvotruba.com/blog/2019/07/08/7-tips-to-write-flawless-issue-report-on-github</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Reporting issue is important for both you and the maintainer of the project. It can be a private issue in your local Gitlab repository, but open-source issues on Github have a much higher volume (obviously).


Do you want to be clear to the maintainer, be understood and resolve your issue quickly?
Here is how to write.
 ]]>
            </summary>

            <updated>Mon, 08 Jul 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Workflow Tips every PHP Developer Should Know ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/07/01/5-workflow-tips-every-php-developer-should-know" />
            <id>https://tomasvotruba.com/blog/2019/07/01/5-workflow-tips-every-php-developer-should-know</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I was surprised, how much of your attention got [5 Tips to Effective Work with Github Repository](/blog/2019/02/25/5-tips-to-effective-work-with-github-repository/) post.


So [I started to collect tips](https://github.com/TomasVotruba/tomasvotruba.com/issues/226) I use on training and mentoring that I don't even notice, but others find fascinating. Here is 5 of them.
 ]]>
            </summary>

            <updated>Mon, 01 Jul 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Do you use PHP_CodeSniffer and PHP CS Fixer PHPStorm Plugin You are Slow and Expensive ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/06/24/do-you-use-php-codesniffer-and-php-cs-fixer-phpstorm-plugin-you-are-slow-and-expensive" />
            <id>https://tomasvotruba.com/blog/2019/06/24/do-you-use-php-codesniffer-and-php-cs-fixer-phpstorm-plugin-you-are-slow-and-expensive</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ People keep asking me about IDE plugins [for Rector](https://www.reddit.com/r/phpstorm/comments/am1qzv/update_phpdoc_comment_action/efqpv8o) and Easy Coding Standard.
Do you want it too? Do you use one for PHP_CodeSniffer of PHP CS Fixer? Have you ever thought about the benefits and costs of them?
 ]]>
            </summary>

            <updated>Mon, 24 Jun 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Don&#039;t Ever use Symfony Listeners ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/05/16/don-t-ever-use-listeners" />
            <id>https://tomasvotruba.com/blog/2019/05/16/don-t-ever-use-listeners</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Another anti-pattern that deserves more attention than it has. I often see this in Symfony projects I consult and when I ask the dev *why* did he or she choose listener over subscriber, they don't really know - "it was in the Symfony documentation, you can read it there".


Not good enough. **So why you should never use a listener?**
 ]]>
            </summary>

            <updated>Thu, 16 May 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Alias as a Code Smell ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/05/02/alias-as-a-code-smell" />
            <id>https://tomasvotruba.com/blog/2019/05/02/alias-as-a-code-smell</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you have 2 class with the same name? `App\Entity\Product` and `App\Entity\Product`? Of course not. But **I bet you have at least 2 classes with the same *short name* `*\Product` and `*\Product`**.

And that smells... Why?
 ]]>
            </summary>

            <updated>Thu, 02 May 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Rector European Tour in May &amp; June 2019 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/29/rector-european-tour-in-may-june-2019" />
            <id>https://tomasvotruba.com/blog/2019/04/29/rector-european-tour-in-may-june-2019</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I asked Łukasz Chruściel if we see each other on one of the conferences I'm coming with Rector and he's like: "I haven't noticed any announcements that you will talk somewhere. Did you set up any long distance trip?"


Ops, I forgot to tell you. Let's fix it because I'd love to meet you and hear about your pain points.
 ]]>
            </summary>

            <updated>Mon, 29 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Don&#039;t Give Up Your PHP Code for Compiler Passes so Easily ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/25/don-t-give-up-your-php-code-for-compiler-passes-so-easily" />
            <id>https://tomasvotruba.com/blog/2019/04/25/don-t-give-up-your-php-code-for-compiler-passes-so-easily</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Sometimes you need to achieve very simple operation - e.g. get all services of a certain type in a certain order or key name. When we start to use a PHP framework, we tend to underestimate our PHP skills and look for *the framework* way.


**Who cares if we use 50 lines in 3 files PHP files and 1 YAML file instead of 1 factory in 20 lines.** We're cool!
 ]]>
            </summary>

            <updated>Thu, 25 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Symfony 4.2 is used Twice More than Symfony 3.4 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/18/symfony-4-2-is-used-2-times-more-than-symfony-3-4" />
            <id>https://tomasvotruba.com/blog/2019/04/18/symfony-4-2-is-used-2-times-more-than-symfony-3-4</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ PHP itself is very quickly adopted. Last Packagist stats from 2018/11 [report 32,6 %](https://blog.packagist.com/php-versions-stats-2018-2-edition) people are using PHP 7.2. That's a very nice number, great job y' all!


But most of our code is not just plain PHP. **It's framework-locked PHP**. How is framework adoption?
 ]]>
            </summary>

            <updated>Thu, 18 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Pattern Refactoring ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/15/pattern-refactoring" />
            <id>https://tomasvotruba.com/blog/2019/04/15/pattern-refactoring</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In [Removing Static - There and Back Again](/blog/2019/04/01/removing-static-there-and-back-again/) post we tried looked at anti-patterns in legacy code from a new point of view. It can be static in your code, it can be active record pattern you needed for fast bootstrapping of your idea, it can be moving from the code in controllers to command bus.

**They can be coupled in your code in hundreds of classes. That's a big problem, you might think, but it's only single pattern**.
 ]]>
            </summary>

            <updated>Mon, 15 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ What You Lose by Switching to Symfony ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/08/what-you-lose-by-switching-to-symfony" />
            <id>https://tomasvotruba.com/blog/2019/04/08/what-you-lose-by-switching-to-symfony</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Switching one framework for another is nowadays getting easier and easier. What you could do for months only on your private projects, where income and delivering features are not important, is now an option for big websites with millions of lines of code. What seems like a divorce and switching a partner, is now as simple as changing your shoes from work to jogging ones.

"Ok, we get it, it's simple. But why, what is the gain?"
 ]]>
            </summary>

            <updated>Mon, 08 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Upgrade Twig from Underscored to Namespaces ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/04/how-to-upgrade-twig-from-underscored-to-namespaces" />
            <id>https://tomasvotruba.com/blog/2019/04/04/how-to-upgrade-twig-from-underscored-to-namespaces</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Symfony [recently announced a new version of Twig](https://symfony.com/blog/new-in-twig-namespaced-classes) with namespaces as we know it. Before PHP 5.2 there was `Underscored_Namespace` - I remember because that was the first version I used.


Today I'll show you how to upgrade from `_` to `\\` in few ~~minutes~~ seconds.
 ]]>
            </summary>

            <updated>Thu, 04 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Removing Static - There and Back Again ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/04/01/removing-static-there-and-back-again" />
            <id>https://tomasvotruba.com/blog/2019/04/01/removing-static-there-and-back-again</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The more companies I meet, the more I see `static` and `new` everywhere. Not like `new Product`, but rather `new ProductRepository(new Database())`. Not just Laravel, but across all PHP frameworks. I wish frameworks could prevent antipatterns, but they don't, do they?


Instead of "refactor all the things" step by step, class by class, I'd **like share my thoughts when exploring full automated path**. I look for feedback to improve this process.
 ]]>
            </summary>

            <updated>Mon, 01 Apr 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Mock Final Classes in PHPUnit ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/28/how-to-mock-final-classes-in-phpunit" />
            <id>https://tomasvotruba.com/blog/2019/03/28/how-to-mock-final-classes-in-phpunit</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you prefer composition over inheritance? Yes, that's great. Why aren't your classes `final` then? Oh, you have tests and you mock your classes. **But why is that a problem?**
 ]]>
            </summary>

            <updated>Thu, 28 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Instantly Migrate Nette\Tester to PHPUnit ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/25/how-to-instantly-migrate-nette-tester-to-phpunit" />
            <id>https://tomasvotruba.com/blog/2019/03/25/how-to-instantly-migrate-nette-tester-to-phpunit</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We had 🍺 after PHP meetup in Prague and Tomas asked me:
<br>
"We don't use Nette, but we still have many tests in Tester. Can Rector migrate them to PHPUnit?"
<br>
"Hold my 🍺"
 ]]>
            </summary>

            <updated>Mon, 25 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Migrate PhpSpec to PHPUnit ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/21/how-to-instantly-migrate-phpspec-to-phpunit" />
            <id>https://tomasvotruba.com/blog/2019/03/21/how-to-instantly-migrate-phpspec-to-phpunit</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I'm happy that more and more people try to use Rector upgrade and migrate their code-bases to the ones they really want for a long time.

Last week I was approached by 2 different people with single need - **migrate their tests to PHPUnit**.
 ]]>
            </summary>

            <updated>Thu, 21 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Detect Dead PHP Code in Code Review in 7 Snippets ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/18/how-to-detect-dead-php-code-in-code-review-in-7-snippets" />
            <id>https://tomasvotruba.com/blog/2019/03/18/how-to-detect-dead-php-code-in-code-review-in-7-snippets</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ After few long Nette to Symfony migration series, it's time for relax.
<br>
Let's look at 7 snippets of PHP code, that [happily takes your attention](/blog/2018/05/21/is-your-code-readable-by-humans-cognitive-complexity-tells-you/) but **is never run**.
 ]]>
            </summary>

            <updated>Mon, 18 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why we Migrated from Nette to Symfony in 3 Weeks - Part 3 - Brain Drain Dead Packages-Lock ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/11/why-we-migrated-from-nette-to-symfony-in-3-weeks-part-3" />
            <id>https://tomasvotruba.com/blog/2019/03/11/why-we-migrated-from-nette-to-symfony-in-3-weeks-part-3</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you want to **migrate your project from Nette to Symfony**? In [the part 2](/blog/2019/03/07/why-we-migrated-from-nette-to-symfony-in-3-weeks-part-2/) we looked at **escaping semver hell**.


Today we'll look on **package vendor-locks** caused by brain drain.
 ]]>
            </summary>

            <updated>Mon, 11 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why we Migrated from Nette to Symfony in 3 Weeks - Part 2 - Escaping Semantic Hell ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/07/why-we-migrated-from-nette-to-symfony-in-3-weeks-part-2" />
            <id>https://tomasvotruba.com/blog/2019/03/07/why-we-migrated-from-nette-to-symfony-in-3-weeks-part-2</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you want to **migrate your project from Nette to Symfony**? In [part 1](/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1/) we showed you how to get your project ready, why it's important to make team commitment and what you can automate.


Today we'll look on one of the core reasons for this migration - **escaping to semantic hell**.
 ]]>
            </summary>

            <updated>Thu, 07 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to turn Laravel from Static to Dependency Injection in one Day ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day" />
            <id>https://tomasvotruba.com/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ A framework is just a tool. Each teaches you coding habits you need to use them effectively.
Like Laravel gives you speed at prototyping with static "facades". But the applications grows, so does the team, so does your skill and **you start to prefer constructor injection**.


What then? Switch framework or rewrite? But what if all you need is to **switch single pattern**?
 ]]>
            </summary>

            <updated>Mon, 04 Mar 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Upgrade Symfony 2.8 to 3.4 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/02/28/how-to-upgrade-symfony-2-8-to-3-4" />
            <id>https://tomasvotruba.com/blog/2019/02/28/how-to-upgrade-symfony-2-8-to-3-4</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Are you Symfony programmer? Do you work on a successful project? Then upgrading the Symfony project is a work you can't avoid.
Almost a year ago I wrote about [Five and Half Steps to Migrate from Symfony 2.8 LTS to Symfony 3.4 LTS in Real PRs](https://blog.shopsys.com/5-5-steps-to-migrate-from-symfony-2-8-lts-to-symfony-3-4-lts-in-real-prs-50c98eb0e9f6).


Now it's much easier to jump from one LTS to another - with **instant upgrades**.
 ]]>
            </summary>

            <updated>Thu, 28 Feb 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Tips to Effective Work with Github Repository ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/02/25/5-tips-to-effective-work-with-github-repository" />
            <id>https://tomasvotruba.com/blog/2019/02/25/5-tips-to-effective-work-with-github-repository</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The best programmers aren't the smartest in the field. They're lazy, **they know their tools well** and **they know good tools** other programmers don't.


Do you know the following tips?
 ]]>
            </summary>

            <updated>Mon, 25 Feb 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How we Migrated from Nette to Symfony in 3 Weeks - Part 1 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1" />
            <id>https://tomasvotruba.com/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ On the break of January/February 2019, we **migrated whole [Entrydo](https://entry.do) project from Nette to Symfony**. It was API backend with no templates, but still, it wasn't as easy as I expected.


Many ☕ and 🍺 were drunk during this migration. 0 programmers were too frustrated to give up.
<br>
Yet, you'd laugh if you knew what took us the most time.
 ]]>
            </summary>

            <updated>Thu, 21 Feb 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why Config Coding Sucks ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/02/14/why-config-coding-sucks" />
            <id>https://tomasvotruba.com/blog/2019/02/14/why-config-coding-sucks</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Rector and static analysis help us to work with code better, but it also helps us spot new weak-points of our PHP code.


One of the biggest evils is *config coding*. **How it can hurt you and how get rid of it**?
 ]]>
            </summary>

            <updated>Thu, 14 Feb 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ New in Rector: Asterisk Type Match ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/02/04/new-in-rector-asterisk-type-match" />
            <id>https://tomasvotruba.com/blog/2019/02/04/new-in-rector-asterisk-type-match</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Rector had started just recently helping **instantly refactor private commercial projects**. Not just from legacy to modern PHP, but also **from one PHP framework to another**. I won't tell you which ones as the work is in progress, but when it's finished, you'll be the first to hear.

The positive side effect of Rector helping to migrate real commercial project **are new features in its core** that is free and open-source Today with little, yet powerful *asterisk type match*.
 ]]>
            </summary>

            <updated>Mon, 04 Feb 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 2 Files that Your Symfony Application Misses ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/01/28/2-files-that-your-symfony-application-misses" />
            <id>https://tomasvotruba.com/blog/2019/01/28/2-files-that-your-symfony-application-misses</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Following files are supported by PHPStorm and Symfony plugin for years (since 2016) and they make working with a code so elegant. **Yet, I came across them just recently.**


They immediately became must-have of each repository with Symfony code.
 ]]>
            </summary>

            <updated>Mon, 28 Jan 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Kill Parents ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/01/24/how-to-kill-parents" />
            <id>https://tomasvotruba.com/blog/2019/01/24/how-to-kill-parents</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I see too many skilled developers missing `final` in every class they use. So I reposed [When to declare classes final](http://ocramius.github.io/blog/when-to-declare-classes-final) - 4 years old post that shows you *why*. If you should learn just one skill this year, read and learn this one.

It's easier said than done, but the more parents you kill, the better you get at it. Today, we look on 3 effective ways to kill them.
 ]]>
            </summary>

            <updated>Thu, 24 Jan 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How Writing Posts Helps you to Become Better Programmer ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2019/01/17/how-writing-posts-helps-you-to-become-better-programmer" />
            <id>https://tomasvotruba.com/blog/2019/01/17/how-writing-posts-helps-you-to-become-better-programmer</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I love to write about my packages. Why? The code you type **you know**, **you know** the name of variables, **you know** how to interface looks, you know the architecture. It's like raising your own child and **knowing** his favorite ice-cream...
 ]]>
            </summary>

            <updated>Thu, 17 Jan 2019 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Your Most Favorite Posts in 2018 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/31/your-most-favorite-posts-in-2018" />
            <id>https://tomasvotruba.com/blog/2018/12/31/your-most-favorite-posts-in-2018</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ It's a holiday, we want to rest and enjoy time with our families. Hence I won't bother you with a complex topic, but finish this year with the simple post instead. A post about the most read post in 2018.


**Was it Symfony? Doctrine? PHP or...**
 ]]>
            </summary>

            <updated>Mon, 31 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How To Convert All Your Symfony Service Configs to Autodiscovery ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/27/how-to-convert-all-your-symfony-service-configs-to-autodiscovery" />
            <id>https://tomasvotruba.com/blog/2018/12/27/how-to-convert-all-your-symfony-service-configs-to-autodiscovery</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you use Symfony autodiscovery services registration everywhere and your configs have no extra lines?
Skip this post and rather read another one.

But if **you have many configs with manual service registration**, tagging, and autowiring, keep reading. I'll show you how you can convert them easily be new Symplify package.
 ]]>
            </summary>

            <updated>Thu, 27 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Thank You ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/24/thank-you" />
            <id>https://tomasvotruba.com/blog/2018/12/24/thank-you</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This was an amazing year for me. I made so many things happen - I won't write about them since you can see them on [the homepage]() and [my Github](https://github.com/tomasvotruba).


I want to write about you, my dear reader and contributor. **I would not make it this far without you in 2018.**
 ]]>
            </summary>

            <updated>Mon, 24 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Function create_function() is Deprecated in PHP 7.2 - How to Migrate ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/17/function-create-function-is-deprecated-in-php-72-how-to-migrate" />
            <id>https://tomasvotruba.com/blog/2018/12/17/function-create-function-is-deprecated-in-php-72-how-to-migrate</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ If there would be "Miss Deprecation of PHP 7.2", `create_function()` would definitely win. They can be **very complex, tricky and very hard convert to PHP code**. Moreover without tests.


Do you have over 5 `create_function()` pieces in your code? Let's see how to migrate them.
 ]]>
            </summary>

            <updated>Mon, 17 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Kirill Smelov&#039;s PHPStorm Tips in 9 Gifs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/13/kirill-smelov-s-phpstorm-tips-in-9-gifs" />
            <id>https://tomasvotruba.com/blog/2018/12/13/kirill-smelov-s-phpstorm-tips-in-9-gifs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last week we hosted [Kirill Smelov](https://twitter.com/wbasrs) in Friends of PHP meetup in Prague. Usually, I know most of tricks people show in PHPStorm talks or they pick too complicated cases - like SSH to Docker via PHPStorm GUI.


Kirill's talk was completely different, **I could not stop taking notes** about simple yet less known features of PHPStorm.


Instead of watching the 45-min talk, **enjoy 9 cherry picked tips in 4,5-min gifs**. I've dropped a few of my own daily habits. Enjoy!
 ]]>
            </summary>

            <updated>Thu, 13 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The Rocket Science Behind Migration of Docblock Types to PHP Typehints ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/10/rocket-science-behind-migration-of-docblock-types-to-php-typehints" />
            <id>https://tomasvotruba.com/blog/2018/12/10/rocket-science-behind-migration-of-docblock-types-to-php-typehints</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ What if you could add scalar typehints `int`, `bool`, `string`, `null` to all parameter type and return type by running a CLI command? But also all classes, `parent`, `self` and `$this`?

Do you think it's an easy task to move `@param int $number` to `(int $number)`?
 ]]>
            </summary>

            <updated>Mon, 10 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Don&#039;t Learn to Code ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/06/dont-learn-to-code" />
            <id>https://tomasvotruba.com/blog/2018/12/06/dont-learn-to-code</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you know what each letter in S.O.L.I.D. means? Do you know commonly used design patterns? Do you know the most popular PHP frameworks? Do know what [cyclomatic complexity](/blog/2018/05/21/is-your-code-readable-by-humans-cognitive-complexity-tells-you/) is?


Don't learn to code. **Learn how to think.**
 ]]>
            </summary>

            <updated>Thu, 06 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ IT Bloggers, Deprecate Your Posts to Stop Spreading Legacy ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/12/03/it-bloggers-deprecate-your-posts-to-stop-spreading-legacy" />
            <id>https://tomasvotruba.com/blog/2018/12/03/it-bloggers-deprecate-your-posts-to-stop-spreading-legacy</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you blog about IT? Do you blog for more than a year? There is a big chance **you're spreading already outdated information**.

The problem is, your readers see that as *the best practise*... did you know the Earth is flat?

How to prevent that and keep your content quality high?
 ]]>
            </summary>

            <updated>Mon, 03 Dec 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 14 Tips to Write PHP Code that is Hard to Maintain and Upgrade ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/11/26/14-tips-to-write-php-code-that-is-hard-to-maintain-and-upgrade" />
            <id>https://tomasvotruba.com/blog/2018/11/26/14-tips-to-write-php-code-that-is-hard-to-maintain-and-upgrade</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today I'll show you how to own your company. All you need to do is write code that no-one can read, is hard to refactor and creates technical debt. It's not easy, because if other programmers spot you're writing legacy code, you're busted.


If you keep a low profile of very smart architect and do it right, you'll be the only one in the company who knows what is going on and you'll have a value of gold. Learn how to be **successful living vendor lock**!
 ]]>
            </summary>

            <updated>Mon, 26 Nov 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Test Monorepo in 3 Layers ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/11/22/how-to-test-monorepo-in-3-layers" />
            <id>https://tomasvotruba.com/blog/2018/11/22/how-to-test-monorepo-in-3-layers</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you have a monorepo, with 2 packages at least, autoloaded with composer and splitting works?
Good! Now you're about to set up testing and code quality tools.


How to make testing so tight no bug can escape?
 ]]>
            </summary>

            <updated>Thu, 22 Nov 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ When You Should Use Monorepo and When Local Packages ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/11/19/when-you-should-use-monorepo-and-when-local-packages" />
            <id>https://tomasvotruba.com/blog/2018/11/19/when-you-should-use-monorepo-and-when-local-packages</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Recently I gave [a few talks about monorepo in PHP](/talks/#monorepo/) and how to integrate it to companies in a useful way. I'm very happy to see many people already use it and know what problems it solves.


Before monorepo hype takes over private PHP projects, I think **you should know about its limits**: When is the best time for you to go monorepo? When you gain less complexity while integrating it? How can you make the transition better? Is it really needed?
 ]]>
            </summary>

            <updated>Mon, 19 Nov 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Get PHP 7.4 Typed Properties to Your Code in Few Seconds ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds" />
            <id>https://tomasvotruba.com/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ PHP 5.6 and 7.0 is going to be dangerous [since 2019](http://php.net/supported-versions.php), PHP 7.1 is new baseline and PHP 7.3 is just about to be released in the end of 2018.


Is this **the best time to upgrade your code to PHP 7.4**?
 ]]>
            </summary>

            <updated>Thu, 15 Nov 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Will Autowired Arrays Finally Deprecate Tags in Symfony and Nette ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/11/12/will-autowired-arrays-finally-deprecate-tags-in-symfony-and-nette" />
            <id>https://tomasvotruba.com/blog/2018/11/12/will-autowired-arrays-finally-deprecate-tags-in-symfony-and-nette</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ To be clear: we talk about those tags that only have a name. No priority, no level, no event name, nothing, **just the name**. If you're not sure why these tags are bad, read *[Drop all Service Tags in Your Nette and Symfony Applications](/blog/2017/02/12/drop-all-service-tags-in-your-nette-and-symfony-applications/)* first.

I'm very happy to see that collectors are getting to the core of DI components of PHP frameworks. Tags, extensions, compiler passes and `autoconfigure` now became workarounds. Collectors are now in the best place they can... **the PHP code**.
 ]]>
            </summary>

            <updated>Mon, 12 Nov 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Fatal error: Uncaught Error: [] operator not supported for strings in ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/11/08/fatal-error-uncaught-error-operator-not-supported-for-strings-in" />
            <id>https://tomasvotruba.com/blog/2018/11/08/fatal-error-uncaught-error-operator-not-supported-for-strings-in</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ That's right! PHP 5.6 and 7.0 are entering EOL - end of ~~line~~ life this December. Social networks, Slacks, Twitter, Reddit are [full](https://www.reddit.com/r/PHP/comments/9syr3m/php_56_eol_end_of_life_end_of_2018_and_php_7) of it. Are you running PHP 7.1? Good, come next year when PHP 7.1 is *eoling*.


For the rest of you, what will you do when PHP will tell you the message in the title?
 ]]>
            </summary>

            <updated>Thu, 08 Nov 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why AST Fixes your Coding Standard Better than Tokens ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/10/25/why-ast-fixes-your-coding-standard-better-than-tokens" />
            <id>https://tomasvotruba.com/blog/2018/10/25/why-ast-fixes-your-coding-standard-better-than-tokens</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In the last post [*Brief History of Tools Watching and Changing Your PHP Code*](/blog/2018/10/22/brief-history-of-tools-watching-and-changing-your-php-code/) we saw there are over **dozen tools in PHP that can modify code**. So there is no surprise coding standard tools are "upgrading" code from PHP 5.6 to PHP 7.2 without knowing types and that AST is moving `false` to `!`.

Should coding standard upgrade your code? Should AST make your code cleaner? Should AST take of coding standard changes? **Which is born for it?** ]]>
            </summary>

            <updated>Thu, 25 Oct 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Brief History of Tools Watching and Changing Your PHP Code ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/10/22/brief-history-of-tools-watching-and-changing-your-php-code" />
            <id>https://tomasvotruba.com/blog/2018/10/22/brief-history-of-tools-watching-and-changing-your-php-code</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ From coding standard tools, over static analysis to instant upgrade tools. This post is going to be a geeky history trip.
Which tool was first? How they **build on shoulders of each other**? ]]>
            </summary>

            <updated>Mon, 22 Oct 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How I Almost Missed My Talk in PHP Asia Conference ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/10/18/how-i-almost-missed-my-talk-in-php-asia-conference" />
            <id>https://tomasvotruba.com/blog/2018/10/18/how-i-almost-missed-my-talk-in-php-asia-conference</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last month you could not call me, cause I was on a month trip to Asia. For fun? Of course, ~~but also~~ for [PHP Conference Asia](https://2018.phpconf.asia) where I talked about [Rector](https://github.com/rectorphp/rector).

It was my first trip to Asia ever, so obviously, it went wrong... ]]>
            </summary>

            <updated>Thu, 18 Oct 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ What is Your Third Door - Book Review ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/10/15/what-is-your-third-door-book-review" />
            <id>https://tomasvotruba.com/blog/2018/10/15/what-is-your-third-door-book-review</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you live in a big house? Then I guess you know this problem. There is the main door, there is the garden door and most people use these.
 <br>
 <br>
 But what if the police come to bring you in for your financial frauds and child porn, **what door do you take to run**?
 ]]>
            </summary>

            <updated>Mon, 15 Oct 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Hi, my name is Tom - Concat vs. Sprintf vs. In-String Variable ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/10/11/hi-my-name-is-tom-conctat-vs-in-sprintf-vs-in-string-variables" />
            <id>https://tomasvotruba.com/blog/2018/10/11/hi-my-name-is-tom-conctat-vs-in-sprintf-vs-in-string-variables</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ My recent post about [lovely exceptions](/blog/2018/09/17/7-tips-to-write-exceptions-everyone-will-love/) opened very interesting question. [In comments bellow the post](/blog/2018/09/17/7-tips-to-write-exceptions-everyone-will-love/#comment-4100904216), [in Reddit thread](https://www.reddit.com/r/PHP/comments/9hehv6/7_tips_to_write_exceptions_everyone_will_love/e6d3hic) and [on  Twitter](https://mobile.twitter.com/geekovo/status/1043185111309713408).

A questions about **connecting string with variables**.
You have 3 options. Each has its strong and weak points. How do you pick the right one?
 ]]>
            </summary>

            <updated>Thu, 11 Oct 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Open-Source Behind The Scenes - Finding the Rector Vision ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/09/27/open-source-behind-the-scenes-finding-the-rector-vision" />
            <id>https://tomasvotruba.com/blog/2018/09/27/open-source-behind-the-scenes-finding-the-rector-vision</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Open-source is not only about programming, maintaining, adding new features and spreading the word. It's also about other decisions of the maintainer, that are hidden from users.


I often ask myself: What values should it spread around the world? Where do I take time and money to develop it? How should it scale? How to make it useful to both people and me?
 ]]>
            </summary>

            <updated>Thu, 27 Sep 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ New in Symplify 5: 3 News in EasyCodingStandard to Smoother Your Experience ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/09/24/new-in-symplify-5-3-news-in-easy-coding-standard-to-smoother-your-experience" />
            <id>https://tomasvotruba.com/blog/2018/09/24/new-in-symplify-5-3-news-in-easy-coding-standard-to-smoother-your-experience</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Let's get lazier and lazier.
 ]]>
            </summary>

            <updated>Mon, 24 Sep 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 7 Tips to Write Exceptions Everyone Will Love ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/09/17/7-tips-to-write-exceptions-everyone-will-love" />
            <id>https://tomasvotruba.com/blog/2018/09/17/7-tips-to-write-exceptions-everyone-will-love</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ `InvalidArgumentException`, `FileNotFoundException`, `InternalException`.


Have you ever had that feeling, that **you've seen that exception before and you know what it means and how to solve?** What if that would be clear even for those who see it for the first time? It would save yours and their time.


Exceptions are not just error state. **Exceptions are the new documentation**.
 ]]>
            </summary>

            <updated>Mon, 17 Sep 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Your Brain is Your Garden ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/09/13/your-brain-is-your-garden" />
            <id>https://tomasvotruba.com/blog/2018/09/13/your-brain-is-your-garden</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ After a few technical and open-source posts, it's time [for brain hacking](/blog/2018/05/03/how-do-you-treat-your-own-first-ai/). Thanks to the recent boom of AI, neuroscience starts to overlap with human psychology. When it comes to learning methods, humans and computers are more alike than ever before.


To overcome [AI disruption](/blog/2017/12/04/life30-what-will-you-do-when-ai-takes-over-the-world/), you'll be valuable by actually making AI or by hacking your brain to be super-adaptable and irreplaceable.
 ]]>
            </summary>

            <updated>Thu, 13 Sep 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Advices I Would Love to Get Before Starting to Maintain an Open Source ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/09/10/5-advices-i-would-love-to-get-before-starting-to-maintain-open-source" />
            <id>https://tomasvotruba.com/blog/2018/09/10/5-advices-i-would-love-to-get-before-starting-to-maintain-open-source</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I wasn't always confident while making public every single line of PHP code I write. I had to take many blind paths, spend a night full of stress coding in unknown waters and make a lot of over-complicated code that backfired to me months later.


They say "experience cannot be passed and it must be experienced" and I agree with that, but still **there are some shortcuts that would speed-up my path to joyful open-source coding** I have today. Here are 5 of them.
 ]]>
            </summary>

            <updated>Mon, 10 Sep 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 4 Ways to Add Global Option or Argument to Symfony Console Application ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/09/03/4-ways-to-add-global-option-or-argument-to-symfony-console-application" />
            <id>https://tomasvotruba.com/blog/2018/09/03/4-ways-to-add-global-option-or-argument-to-symfony-console-application</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I'm working on [ChangelogLinker](https://github.com/symplify/changeloglinker), a package that makes managing `CHANGELOG.md` very easy - it generates it. It a CLI Application with a [3 Console Commands](https://github.com/Symplify/ChangelogLinker/tree/master/src/Console/Command). All was good, until **I needed to add an argument to all commands at once**... and in lazy, extensible, maintainable way.
 ]]>
            </summary>

            <updated>Mon, 03 Sep 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Ways I Fucked Up Open Source Code: Mock Everything and Test Units ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/30/ways-i-fucked-up-open-source-code-mock-everything-and-test-units" />
            <id>https://tomasvotruba.com/blog/2018/08/30/ways-i-fucked-up-open-source-code-mock-everything-and-test-units</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In a normal job, decisions are made by those above you. They pay you and when it goes down, you leave in 2 months. Open-source code is different because **you're the one making choices but also the one who deals with results when it fails**. Moreover, if you love the project and want to spend years with it.

Today I'll show you one of my many fuckups - let's mock units!
 ]]>
            </summary>

            <updated>Thu, 30 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why and How to Avoid the Memory Lock ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/27/why-and-how-to-avoid-the-memory-lock" />
            <id>https://tomasvotruba.com/blog/2018/08/27/why-and-how-to-avoid-the-memory-lock</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When you close the door of my home, they're closed and you need a key to get in. But what if your door has door handle? You have to also lock them.


Instead of just closing the door you have to close the door and *that one more thing*. Why is that a bad thing in the code and how to avoid it?
 ]]>
            </summary>

            <updated>Mon, 27 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 9 Features of PHPStorm Symfony Plugin You Should Not Miss in Gifs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/23/9-features-of-symfony-plugin-you-should-not-miss-in-gifs" />
            <id>https://tomasvotruba.com/blog/2018/08/23/9-features-of-symfony-plugin-you-should-not-miss-in-gifs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ After very successful [PHP 7.3 diffs post](/blog/2018/08/16/whats-new-in-php-73-in-30-seconds-in-diffs/), let's dive to gifs of [Symfony Plugin for PHPStorm](https://plugins.jetbrains.com/plugin/7219-symfony-plugin). You might know them, but they **might surprise you like they did surprise me**. Let's go!
 ]]>
            </summary>

            <updated>Thu, 23 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ What&#039;s New in PHP 7.3 in 30 Seconds in Diffs ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/16/whats-new-in-php-73-in-30-seconds-in-diffs" />
            <id>https://tomasvotruba.com/blog/2018/08/16/whats-new-in-php-73-in-30-seconds-in-diffs</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ No time but eager to hear PHP news? PHP 7.3 is out in December 2018 and it brings [173 changes](https://github.com/php/php-src/blob/PHP-7.3/NEWS). Which are the most useful ones?
 ]]>
            </summary>

            <updated>Thu, 16 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Hidden Gems of PHP Packages: Symfony\Finder and SplFileInfo ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/13/hidden-gems-of-php-packages-symfony-finder-and-spl-file-info" />
            <id>https://tomasvotruba.com/blog/2018/08/13/hidden-gems-of-php-packages-symfony-finder-and-spl-file-info</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The series on not-so-well-known packages that might save your ass more than you think continues.
Today we look on **files as objects**.
 ]]>
            </summary>

            <updated>Mon, 13 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Stylish and Standard Console Output with Symfony Style ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/06/stylish-and-standard-console-output-with-symfony-style" />
            <id>https://tomasvotruba.com/blog/2018/08/06/stylish-and-standard-console-output-with-symfony-style</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Even if you don't use any component from Symfony or even installed one, you can use this trick in your PHP CLI App.


It's simple, provides standard and makes your output look like a design from Apple - useful and nice at the same time.
 ]]>
            </summary>

            <updated>Mon, 06 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Gotchas of the Bin File in PHP CLI Applications ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/08/02/5-gotchas-of-the-bin-file-in-php-cli-applications" />
            <id>https://tomasvotruba.com/blog/2018/08/02/5-gotchas-of-the-bin-file-in-php-cli-applications</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This post focuses on bin files. It's the smallest part of PHP CLI Application, so I usually start with it.


Yet, there are still a few blind paths you can struggle with. I'll drop a few extra tricks to make your bin file clean and easy to maintain.
 ]]>
            </summary>

            <updated>Thu, 02 Aug 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Hidden Gems of PHP Packages: Nette\Utils ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/07/30/hidden-gems-of-php-packages-nette-utils" />
            <id>https://tomasvotruba.com/blog/2018/07/30/hidden-gems-of-php-packages-nette-utils</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ In this series, I will show you **not-so-known PHP packages, that I happily use in my daily workflow**. They're hard to describe in few words for their various features, but awesome and simple to use.


Today we start with [Nette\Utils](https://github.com/nette/utils) package.
 ]]>
            </summary>

            <updated>Mon, 30 Jul 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 5 Signs You Should Never Have a Talk Abroad ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/07/23/5-signs-should-never-have-a-talk-abroad" />
            <id>https://tomasvotruba.com/blog/2018/07/23/5-signs-should-never-have-a-talk-abroad</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I find PHP meetups abroad more and more valuable to my programming life. They're the best place to diverse my skills and knowledge without eating dump and self-proclaiming Twitter feeds.

Wait, don't rush to your train ticket so fast to enjoy the presence of great developers, interesting topic, surprisingly open-minded people and tasty beer afterward.

I'm about to tell you why you should not do it.
 ]]>
            </summary>

            <updated>Mon, 23 Jul 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Notes from &#039;Peace is Every Step&#039; Book ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/07/12/20-notes-from-peace-is-every-step-book" />
            <id>https://tomasvotruba.com/blog/2018/07/12/20-notes-from-peace-is-every-step-book</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Zen To Done, Deep Work, ZenHabits... You've probably noticed I'm a fan of Leo Babauta. The first person I met on the Internet who explained to me that I'm not weird, but a minimalist.


Leo [writes](https://zenhabits.net) minimalist tips from daily life that is easy to relate to. Thanks to quotes in his posts I got chance to meet *Thich Nhat Hanh*, a Buddhist monk who helped to restore peace between the USA and Vietnam...


...and recently I've finished reading his book *Peace Is Every Step: The Path of Mindfulness in Everyday Life*. What was it about?
 ]]>
            </summary>

            <updated>Thu, 12 Jul 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 6 Reasons Why Doctrine is Alive and Kicking ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/07/09/6-reasons-why-doctrine-is-alive-and-kicking" />
            <id>https://tomasvotruba.com/blog/2018/07/09/6-reasons-why-doctrine-is-alive-and-kicking</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Almost 1,5 year ago I wrote *Why is Doctrine Dying*. I didn't use *dead*, because it's is just state of time being. Open-source projects - like people - tend to find themselves on the top, being stuck or struggling with the right path from time to time. It's a completely normal process of evolution.

I don't know if that post helped it, but since then many **things changed for better in Doctrine project**. Saying that this post deprecates my old view and celebrate changes.

**May this be an inspiration for open-source projects that find themselves stuck and the maintainers that find themselves unhappy**.
 ]]>
            </summary>

            <updated>Mon, 09 Jul 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Convert Latte Templates to Twig in 27 Regular Expressions ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/07/05/how-to-convert-latte-templates-to-twig-in-27-regular-expressions" />
            <id>https://tomasvotruba.com/blog/2018/07/05/how-to-convert-latte-templates-to-twig-in-27-regular-expressions</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Statie - a tool for generating static open-sourced website like this blog or [Pehapkari.cz](https://github.com/pehapkari/pehapkari.cz) - runs on YAML and Symfony DI Container. That way it's easy to understand by the PHP community worldwide.


But there are some pitfalls left. Like templates - being Latte the only one is a pity. Twig is often requested feature and one of the last big reasons not to use Statie.


Well, **it was**. Statie now supports [Twig](https://github.com/symplify/symplify/pull/892).


**Are you a Twig fan? As a side effect, I made 27 regular expression to handle 80 % of the Latte to Twig migration for you.**
 ]]>
            </summary>

            <updated>Thu, 05 Jul 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Don&#039;t Read Books ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/06/28/dont-read-books" />
            <id>https://tomasvotruba.com/blog/2018/06/28/dont-read-books</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You're probably thinking: "He's joking, right? That's kind of that title, that is a parody to show us we should do the opposite. You won't get us again, Tomas."

**No, I really don't think we should read books nor feel bad for not reading them**. And now talk about those non-fiction books with the knowledge that readers want to use in their lives.

Do you still think this is sarcasm? Keep on reading.
 ]]>
            </summary>

            <updated>Thu, 28 Jun 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 14 Surprising Tips from Selling is Human to Influence Others ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/06/18/14-surprising-tip-from-selling-is-human-to-influence-others" />
            <id>https://tomasvotruba.com/blog/2018/06/18/14-surprising-tip-from-selling-is-human-to-influence-others</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Recently, I've read [Selling is Human](https://www.youtube.com/watch?v=nKrBitIQrgo&feature=youtu.be&t=290) by Daniel Pink. He's famous for [Pinkcast](https://www.danpink.com/pinkcast) - an espresso of knowledge. I like him, because he's often right to the point, with examples, stories, and science.


What can we learn about selling?
Lucky for you, you don't have to read the whole book - here are the top 10 points I found very useful.
 ]]>
            </summary>

            <updated>Mon, 18 Jun 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Collector Pattern for Dummies ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/06/14/collector-pattern-for-dummies" />
            <id>https://tomasvotruba.com/blog/2018/06/14/collector-pattern-for-dummies</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I wrote *[Why is Collector Pattern so Awesome](/blog/2018/03/08/why-is-collector-pattern-so-awesome/)* a while ago, but I got feeling and feedback that it's way too complicated.


The pattern itself is simple, but put in framework context, it might be too confusing to understand.


That's why we look on collector pattern in minimalistic plain PHP way today.
 ]]>
            </summary>

            <updated>Thu, 14 Jun 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Turn Mocks from Nightmare to Solid Kiss Tests ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/06/11/how-to-turn-mocks-from-nightmare-to-solid-kiss-tests" />
            <id>https://tomasvotruba.com/blog/2018/06/11/how-to-turn-mocks-from-nightmare-to-solid-kiss-tests</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ [Martin Hlaváč](http://mhlavac.net) had a very nice talk about testing in [Berlin PHP Meetup](http://www.bephpug.de/2018/06/05/june.html) last week (while I hosted with [Rector](https://github.com/rectorphp/rector)), and one of the topic was mocking.


I often see developers fighting with this, in places they don't have to, just because this topic is so widespread all over the internet and unit tools.


Did you know there is easier and more clear way to do "mocking"?
 ]]>
            </summary>

            <updated>Mon, 11 Jun 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Migrate From PHP CS Fixer to ECS in 6 Steps ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/06/07/how-to-migrate-from-php-cs-fixer-to-easy-coding-standard" />
            <id>https://tomasvotruba.com/blog/2018/06/07/how-to-migrate-from-php-cs-fixer-to-easy-coding-standard</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ We looked at how to migrate from PHP_CodeSniffer to Easy Coding Standard on Monday. But what if your weapon of choice is PHP CS Fixer and you'd to run also some sniffs?

There are **a few simple A → B changes**, but one has to know about them or will get stuck. Let's learn about them.
 ]]>
            </summary>

            <updated>Thu, 07 Jun 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Migrate From PHP_CodeSniffer to ECS in 7 Steps ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/06/04/how-to-migrate-from-php-code-sniffer-to-easy-coding-standard" />
            <id>https://tomasvotruba.com/blog/2018/06/04/how-to-migrate-from-php-code-sniffer-to-easy-coding-standard</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last year, I helped [Shopsys CS](https://github.com/shopsys/coding-standards) and [LMC CS](https://github.com/lmc-eu/php-coding-standard) to migrate from PHP_CodeSniffer to ECS.

There are a few simple A → B changes, but one has to know about them or will get stuck.

Do you also use PHP_CodeSniffer and give it ECS a try? Today we look at how to migrate step by step.
 ]]>
            </summary>

            <updated>Mon, 04 Jun 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Symfony vs Laravel vs Nette - Which PHP Framework Should You Choose ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/05/31/symfony-vs-laravel-vs-nette-which-php-framework-you-should-choose" />
            <id>https://tomasvotruba.com/blog/2018/05/31/symfony-vs-laravel-vs-nette-which-php-framework-you-should-choose</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I have been asked this question over hundred times, in person, as [a post request](https://github.com/TomasVotruba/tomasvotruba.com/issues/278). When to use Symfony? How is Laravel better than Symfony? What are Nette killer features compared to Symfony and Laravel?


Today, we look on the answer.
 ]]>
            </summary>

            <updated>Thu, 31 May 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Build Your First Symfony Console Application with Dependency Injection Under 4 Files ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/05/28/build-your-first-symfony-console-application-with-dependency-injection-under-4-files" />
            <id>https://tomasvotruba.com/blog/2018/05/28/build-your-first-symfony-console-application-with-dependency-injection-under-4-files</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Series about PHP CLI Apps continues with 3rd part about writing Symfony Console Application with Dependency Injection in the first place. Not last, not second, **but the first**.

Luckily, is easy to start using it and very difficult to
 ]]>
            </summary>

            <updated>Mon, 28 May 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Test Private Services in Symfony ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/05/17/how-to-test-private-services-in-symfony" />
            <id>https://tomasvotruba.com/blog/2018/05/17/how-to-test-private-services-in-symfony</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ 2 versions of Symfony are affected by this dissonance between services and tests.
**Do you use Symfony 3.4 or 4.0? Do you want to test your services, but struggle to get them in a clean way?**


Today we look at possible solutions.
 ]]>
            </summary>

            <updated>Thu, 17 May 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Load --config With Services in Symfony Console ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/05/14/how-to-load-config-with-services-in-symfony-console" />
            <id>https://tomasvotruba.com/blog/2018/05/14/how-to-load-config-with-services-in-symfony-console</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ PHP CLI apps usually accept config, to setup their behavior. For PHPUnit it's `phpunit.xml`, for PHP CS Fixer it's `.php_cs`, for ECS it's `ecs.php`, for PHPStan it's `phpstan.neon` and so on.


In the first post about PHP CLI Apps I wrote about [poor DI support in PHP CLI projects](/blog/2018/05/07/why-you-should-combine-symfony-console-and-dependency-injection/).


Today we look on the first barrier that leads most people to prefer static over DI - **how to load config with services**.
 ]]>
            </summary>

            <updated>Mon, 14 May 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why You Should Combine Symfony Console and Dependency Injection ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/05/07/why-you-should-combine-symfony-console-and-dependency-injection" />
            <id>https://tomasvotruba.com/blog/2018/05/07/why-you-should-combine-symfony-console-and-dependency-injection</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I saw 2 links to Symfony\Console in [today's Week of Symfony](http://symfony.com/blog/a-week-of-symfony-592-30-april-6-may-2018) (what a time reference, huh?).
There are plenty of such posts out there, even in Pehapkari community blog: [Best Practice for Symfony Console in Nette](https://pehapkari.cz/blog/2017/06/02/best-practice-for-symfony-console-in-nette) or [Symfony Console from the Scratch](/blog/2019/08/12/standalone-symfony-console-from-scratch/).

But nobody seems to write about **the greatest bottleneck of Console applications - static cancer**. Why is that?
 ]]>
            </summary>

            <updated>Mon, 07 May 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How Do You Treat Your Own First AI ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/05/03/how-do-you-treat-your-own-first-ai" />
            <id>https://tomasvotruba.com/blog/2018/05/03/how-do-you-treat-your-own-first-ai</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Artificial intelligence is at boom the last couple of years. I wrote about AI and its relation to [jobs development](/blog/2017/12/04/life30-what-will-you-do-when-ai-takes-over-the-world/) in following years.

Now we'll try to look a bit closer. Not in time, but in space. Take a look around you, what do you see?
Do you see *your own first* AI already? And how do you treat it?
 ]]>
            </summary>

            <updated>Thu, 03 May 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Programming = Climbing a Huge Mountain ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/04/30/programming-climbing-a-huge-mountain" />
            <id>https://tomasvotruba.com/blog/2018/04/30/programming-climbing-a-huge-mountain</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Let's take a break after 2 long code-posts from last week and enjoy bit of philosophy. I apply *the mountain climber* in programming for last 2 years and it really helps me to overcome difficult spots.


Today we'll climb together.
 ]]>
            </summary>

            <updated>Mon, 30 Apr 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How I Got into Static Trap and Made Fool of Myself ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/04/26/how-i-got-into-static-trap-and-made-fool-of-myself" />
            <id>https://tomasvotruba.com/blog/2018/04/26/how-i-got-into-static-trap-and-made-fool-of-myself</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ PHP story with code examples, copy-cat killers, just a little bit of static, consistency, sniffs and way to prevent all that ever happening ever again.
 ]]>
            </summary>

            <updated>Thu, 26 Apr 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 4 Tips To Get Emotions to Your Blogging About Programming ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/04/19/4-tips-to-get-emotions-to-your-blogging-about-programming" />
            <id>https://tomasvotruba.com/blog/2018/04/19/4-tips-to-get-emotions-to-your-blogging-about-programming</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Last week I wrote about [top 5 bloghacks](/blog/2018/04/12/the-best-5-of-256-bloghacks-book/) I found in this book.

Today I'll share with you **5 tips that proven useful during my programming/self-education career**.
 ]]>
            </summary>

            <updated>Thu, 19 Apr 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ The Best 5 of 256 Bloghacks Book ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/04/12/the-best-5-of-256-bloghacks-book" />
            <id>https://tomasvotruba.com/blog/2018/04/12/the-best-5-of-256-bloghacks-book</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Have you heard of [*256 Bloghacks* book](http://www.yegor256.com/256-bloghacks.html) by Yegor? Do you think about reading it, but just don't have the time and money?


This post is *the best of* selection just for you and if you feel you like it, you can buy it and read as a whole.
 ]]>
            </summary>

            <updated>Thu, 12 Apr 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Try PSR-12 on Your Code Today ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/04/09/try-psr-12-on-your-code-today" />
            <id>https://tomasvotruba.com/blog/2018/04/09/try-psr-12-on-your-code-today</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ The standard is still behind the door, but feedback, before it gets accepted, is very important. After accepting it will be written down and it will be difficult to change anything.


Try PSR-12 today and see, how it works for your code.
 ]]>
            </summary>

            <updated>Mon, 09 Apr 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ New in Coding Standard 4: Long Line Breaks Automated and 3 Legacy Prevention Fixers ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/03/29/new-in-coding-standard-4-long-line-breaks-automated-and-3-legacy-prevention-fixers" />
            <id>https://tomasvotruba.com/blog/2018/03/29/new-in-coding-standard-4-long-line-breaks-automated-and-3-legacy-prevention-fixers</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Legacy code prevention, lines automated and clear naming of classes in huge projects.
That all is coming to Coding Standard 4 (still in alpha).


Are you curious what work will now these 4 news fixers handle for you? Look inside.
 ]]>
            </summary>

            <updated>Thu, 29 Mar 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How Teaching Suicides Itself by Killing the Passion ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/03/22/how-teaching-suicides-itself-by-killing-the-passion" />
            <id>https://tomasvotruba.com/blog/2018/03/22/how-teaching-suicides-itself-by-killing-the-passion</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today I wanted to write about Rector showcase how to use it to [automate migration to Repository as Service in Symfony](/blog/2017/10/16/how-to-use-repository-with-doctrine-as-service-in-symfony/).


Instead I read [Teaching PHP to students](https://medium.com/@romaninsh/teaching-php-to-students-with-atk-500d50b49391) by Romans Malinovskis that got me thinking how outside education can easily kill any piece passion in children.


What if instead of outside-in - education first, we could do it inside-out - **passion first**?
 ]]>
            </summary>

            <updated>Thu, 22 Mar 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Criticize like a Senior Programmer ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/03/19/how-to-criticize-like-a-senior-programmer" />
            <id>https://tomasvotruba.com/blog/2018/03/19/how-to-criticize-like-a-senior-programmer</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ As I spend most of my socials online time on Github and PHP-related discussion, I've noticed **many people do so many wrong things** while giving critics.

I want to **correct this** once and for all, so I've prepared a guide for you.
 ]]>
            </summary>

            <updated>Mon, 19 Mar 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ NEON vs. YAML and How to Migrate Between Them ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/03/12/neon-vs-yaml-and-how-to-migrate-between-them" />
            <id>https://tomasvotruba.com/blog/2018/03/12/neon-vs-yaml-and-how-to-migrate-between-them</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you know `*.neon` format? It's config file format created in Czech Republic by [David Grudl](https://davidgrudl.com) (author of [Nette](https://github.com/nette/nette)) and if you're foreigner, you might know it from or [EasyCodingStandard](https://github.com/symplify/easy-coding-standard) and [PHPStan](https://github.com/phpstan/phpstan). Even suggested as [`composer.neon`](https://github.com/composer/composer/issues/3228).


And `*.yaml` is similar format used almost everywhere else.


**You spot the suffix is different, but what about syntax differences? And which one is better?**
 ]]>
            </summary>

            <updated>Mon, 12 Mar 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why is Collector Pattern so Awesome ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/03/08/why-is-collector-pattern-so-awesome" />
            <id>https://tomasvotruba.com/blog/2018/03/08/why-is-collector-pattern-so-awesome</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ How to achieve *open for extension* and *closed for modification* [one of sOlid principals](https://github.com/jupeter/clean-code-php#openclosed-principle-ocp)?

Why Collector pattern beats config tagging? How to use the in Symfony application? How it turns locked architecture into scaling one?
 ]]>
            </summary>

            <updated>Thu, 08 Mar 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Rector: Part 3 - Why Instant Upgrades ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/03/05/rector-part-3-why-instant-upgrades" />
            <id>https://tomasvotruba.com/blog/2018/03/05/rector-part-3-why-instant-upgrades</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Why are instant upgrades better than old school *manual upgrades*? Why is the path to find exact before/after like hell-road?
Why you should use Rector and when?
 ]]>
            </summary>

            <updated>Mon, 05 Mar 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Rector: Part 2 - Maturity of PHP Ecosystem and Founding Fathers ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/02/26/rector-part-2-maturity-of-php-ecocystem-and-founding-fathers" />
            <id>https://tomasvotruba.com/blog/2018/02/26/rector-part-2-maturity-of-php-ecocystem-and-founding-fathers</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ What it took for Rector to be born?


Paradigm shift, ecosystem maturity, need for speed to solve common problems community has. **And a great team you share [your work with](https://austinkleon.com/show-your-work) that feedbacks and reflects.**
 ]]>
            </summary>

            <updated>Mon, 26 Feb 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Rector: Part 1 - What and How ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/02/19/rector-part-1-what-and-how" />
            <id>https://tomasvotruba.com/blog/2018/02/19/rector-part-1-what-and-how</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Rector is a PHP tool that handles 2 things: **instant upgrades** and **architecture refactorings**.


What exactly Rector does and how does it work?
 ]]>
            </summary>

            <updated>Mon, 19 Feb 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Sleep Shorter to Get 62 % Smarter ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/02/12/sleep-shorter-to-get-62-percent-smarter" />
            <id>https://tomasvotruba.com/blog/2018/02/12/sleep-shorter-to-get-62-percent-smarter</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Even though I see [University as very poor place to learn something useful](/blog/2017/11/13/7-tips-you-should-know-before-going-to-university/), I studied Psychology in Brno for 3 years.


*Psychological Impacts of Polyphasic Sleep* is the topic of my [bachelor thesis](https://is.muni.cz/th/363896/fss_b/Tomas-Votruba-Psychological-Impacts-of-Polyphasic-Sleep.pdf) I wrote in 2012. In the end it gave me clear answer to question: **can we sleep less than 4,5 hours a night to get smarter?**
 ]]>
            </summary>

            <updated>Mon, 12 Feb 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Deal With Haters in Comments and Github ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/01/29/how-to-deal-with-haters-in-comments-and-github" />
            <id>https://tomasvotruba.com/blog/2018/01/29/how-to-deal-with-haters-in-comments-and-github</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ That's what I was asked yesterday for about 5th person already. How do I deal with that when I write an article, when I tweet or comment on Github and someone is throwing dirt on me?
 ]]>
            </summary>

            <updated>Mon, 29 Jan 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Clean and Decoupled Controllers, Commands and Event Subscribers Once and for All with Delegator Pattern ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2018/01/08/clean-and-decoupled-controllers-commands-and-event-subscribers-once-and-for-all-with-delegator-pattern" />
            <id>https://tomasvotruba.com/blog/2018/01/08/clean-and-decoupled-controllers-commands-and-event-subscribers-once-and-for-all-with-delegator-pattern</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you write your application for **better future sustainability** or just to get paid for it today?
If you're the first one, you care about design patterns. I'm happy to see you!

Today I will show you **why and how to use *delegator pattern*** in your application so it makes it to the pension.
 ]]>
            </summary>

            <updated>Mon, 08 Jan 2018 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Composer Local Packages for Dummies ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/12/25/composer-local-packages-for-dummies" />
            <id>https://tomasvotruba.com/blog/2017/12/25/composer-local-packages-for-dummies</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This is the simplest way to start using `/packages` directory in your application, that **leads to cleaner code, maintainable architecture** and is **the best to start testing**.
 ]]>
            </summary>

            <updated>Mon, 25 Dec 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Life 3.0: What Will You Do When AI Takes Over the World ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/12/04/life30-what-will-you-do-when-ai-takes-over-the-world" />
            <id>https://tomasvotruba.com/blog/2017/12/04/life30-what-will-you-do-when-ai-takes-over-the-world</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you remember cell phones? Those that could only call and send SMS. I bought a Nokia phone that could **also play mp3s** when I was 14 years old.
Who would have thought **we could play movies and use internet on those phones** just 10 years later.


Artificial Intelligence is now in same level as mobile phones playing mp3s. Or **maybe it already took over the world without knowing us**, as *Life 3.0* story unveils...
 ]]>
            </summary>

            <updated>Mon, 04 Dec 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Write Interesting Jobs Offers for Programmers ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/11/20/how-to-write-interesting-job-offers-for-programmers" />
            <id>https://tomasvotruba.com/blog/2017/11/20/how-to-write-interesting-job-offers-for-programmers</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ A few years watching the labor market from a position of PHP programmers from the perspective of companies. With both sides have a good relationship. I think what they need and what is bothering you. **I see that they want each other, just communication is little stuck**.


I gave feedback on Jobs.cz, Skrz.cz and few more ads and this is **summary of tips, which I want to share with every company trying to hire programmer**.
 ]]>
            </summary>

            <updated>Mon, 20 Nov 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 7 Tips You Should Know Before Going To University ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/11/13/7-tips-you-should-know-before-going-to-university" />
            <id>https://tomasvotruba.com/blog/2017/11/13/7-tips-you-should-know-before-going-to-university</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ It's been 4 years since I finished university without having any degree out of it. During those 4 years, I was asked about university by people I could count on the fingers of one hand. And the about the degree? **Not one.**


**I recently talked with one high-school guy and I realized that college is still seen as something sacred, important and mostly from no other than teachers and parents**. I told myself that I'll write down my insights and advice that I would give my 8 years younger self. **If you are 18-19 years're considering what to do next, go ahead**.
 ]]>
            </summary>

            <updated>Mon, 13 Nov 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to change PHP code with Abstract Syntax Tree ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/11/06/how-to-change-php-code-with-abstract-syntax-tree" />
            <id>https://tomasvotruba.com/blog/2017/11/06/how-to-change-php-code-with-abstract-syntax-tree</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Today we can do amazing things with PHP. Thanks to AST and [nikic/php-parser](https://github.com/nikic/PHP-Parser) we can create very **narrow artificial intelligence, which can work for us**.


Let's create first its synapse!
 ]]>
            </summary>

            <updated>Mon, 06 Nov 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ What can You Learn from Menstruation and Symfony Releases ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/10/30/what-can-you-learn-from-menstruation-and-symfony-releases" />
            <id>https://tomasvotruba.com/blog/2017/10/30/what-can-you-learn-from-menstruation-and-symfony-releases</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I [wrote about monorepo and how it turned me into lazy programmer](/blog/2017/01/31/how-monolithic-repository-in-open-source-saved-my-laziness/) before.


As monorepo is use [more and more](https://blog.shopsys.com/how-to-maintain-multiple-git-repositories-with-ease-61a5e17152e0), we should look at it again.
Today from a bit atypical point of view: **combined with bit of blood and sunshine**.


Are you ready?
 ]]>
            </summary>

            <updated>Mon, 30 Oct 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ IMbox Zero ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/10/23/imbox-zero" />
            <id>https://tomasvotruba.com/blog/2017/10/23/imbox-zero</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You have probably heard about Inbox Zero. [ZTD](https://zenhabits.net/zen-to-done-ztd-the-ultimate-simple-productivity-system) technique, **to keep your email inbox clean and your brain well rested**.


Let's take it a step further into 2017 - **to instant messaging**.
 ]]>
            </summary>

            <updated>Mon, 23 Oct 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to use Repository with Doctrine as Service in Symfony ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/10/16/how-to-use-repository-with-doctrine-as-service-in-symfony" />
            <id>https://tomasvotruba.com/blog/2017/10/16/how-to-use-repository-with-doctrine-as-service-in-symfony</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Dependency injection with autowiring is super easy [since Symfony 3.3](/blog/2017/05/07/how-to-refactor-to-new-dependency-injection-features-in-symfony-3-3/). Yet on my mentoring I still meet service locators.


Mostly due to traditional registration of Doctrine repositories.


The way out from *service locators* to *repository as service* was [described](https://matthiasnoback.nl/2014/05/inject-a-repository-instead-of-an-entity-manager) by many [before](https://medium.com/@adamquaile/composition-over-inheritance-in-doctrine-repositories-f6a53a026f60) and **now we put it into Symfony 3.3 context**.
 ]]>
            </summary>

            <updated>Mon, 16 Oct 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Get the Most Valuable Feedback You Can Get ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/10/09/how-to-get-the-most-valuable-feedback-you-can-get" />
            <id>https://tomasvotruba.com/blog/2017/10/09/how-to-get-the-most-valuable-feedback-you-can-get</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Feedback is one of the best way to improve yourself. To make it really work it have to be able to get to you. "That's wrong" usually doesn't work as the person giving the feedback intended.


If the feedback is **honest, understandable, from trustful person who knows your history and values** it can make your mind shine for the brighter future with gratitude.


How to get such feedback?
 ]]>
            </summary>

            <updated>Mon, 09 Oct 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 3 non-IT Books That Help you to Become Better Programmer ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/09/25/3-non-it-books-that-help-you-to-become-better-programmer" />
            <id>https://tomasvotruba.com/blog/2017/09/25/3-non-it-books-that-help-you-to-become-better-programmer</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I love reading books. It helps me to create much deeper and persistent neural connections than any other form of self-education.


These books accidentally help me to **write more readable code, create understandable and smart architecture** or **manage open-source in more polite and leading way**.


Are you tired of reading technical books? Take a rest with these 3.
 ]]>
            </summary>

            <updated>Mon, 25 Sep 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How PHP Coding Standard Tools Actually Work ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/07/31/how-php-coding-standard-tools-actually-work" />
            <id>https://tomasvotruba.com/blog/2017/07/31/how-php-coding-standard-tools-actually-work</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you use <a href="https://github.com/PHP-CS-Fixer/PHP-CS-Fixer">PHP CS Fixer</a> or <a href="https://github.com/squizlabs/PHP_CodeSniffer">PHP_CodeSniffer</a>? Do you know the way they work is ~80 % the same? Do you wonder how they work under the hood?


Today I will share <strong>3 main pillars of their architecture</strong>.
 ]]>
            </summary>

            <updated>Mon, 31 Jul 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Write Custom Fixer for PHP CS Fixer 3 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/07/24/how-to-write-custom-fixer-for-php-cs-fixer-24" />
            <id>https://tomasvotruba.com/blog/2017/07/24/how-to-write-custom-fixer-for-php-cs-fixer-24</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You already know [how coding standard tools work with tokens and how to write a Sniff](/blog/2017/07/17/how-to-write-custom-sniff-for-code-sniffer-3/).


 Today we'll explore another tool - [PHP CS Fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) and we get **from finding the smelly spot to fixing it**.
 ]]>
            </summary>

            <updated>Mon, 24 Jul 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Write Custom Sniff for Code Sniffer 3+ ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/07/17/how-to-write-custom-sniff-for-code-sniffer-3" />
            <id>https://tomasvotruba.com/blog/2017/07/17/how-to-write-custom-sniff-for-code-sniffer-3</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ When I give talks about coding standards, I ask people 2 questions: do you use coding standards? Do you write your own sniffs? On average, above 50 % uses it, but only 1-2 people wrote their own sniff.


PSR-2 is great for start, but main power is in those own sniffs. Every project has their own need, every person has different preferences.


I Google then and found outdated or complicated sources, so I've decided to write down a reference post for those, who want to start with sniffs.
Let's look what will show all you need (and nothing more) to <strong>know to write your first sniff</strong>.
 ]]>
            </summary>

            <updated>Mon, 17 Jul 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to Deprecate PHP Package Without Leaving Anyone Behind ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/07/03/how-to-deprecate-php-package-without-leaving-anyone-behind" />
            <id>https://tomasvotruba.com/blog/2017/07/03/how-to-deprecate-php-package-without-leaving-anyone-behind</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ You create PHP open-source packages because you personally use them in your projects. <strong>And you take care of them.</strong>
In time you change a job or switch a programming language and you don't have time to take care of them properly. Number of issues and PRs grows and <strong>package is getting obsolete</strong>.


You can do 2 things in this situation: nothing like most people do or <strong>take responsibility, deprecate package and inform your users about better alternative</strong>.
 ]]>
            </summary>

            <updated>Mon, 03 Jul 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Thank you David Grudl ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/06/01/thank-you-david" />
            <id>https://tomasvotruba.com/blog/2017/06/01/thank-you-david</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ While using open-source, we rarely realize that there is one or few people behind it. <strong>People who work in their free time and put an effort in it</strong>.
We feel like using a product - it should work and when it doesn't, it's broken. And when our application is constantly broken, we will be angry for them.


But if our application is smooth and ready, do we love and say thank you?


I'd like to express <strong>my gratitude and tribute for you, <a href="https://davidgrudl.com/">David</a> - you made my programming life very joyful and curious experience</strong>.
 ]]>
            </summary>

            <updated>Thu, 01 Jun 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ How to refactor to new Dependency Injection features in Symfony 3.3 ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/05/07/how-to-refactor-to-new-dependency-injection-features-in-symfony-3-3" />
            <id>https://tomasvotruba.com/blog/2017/05/07/how-to-refactor-to-new-dependency-injection-features-in-symfony-3-3</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ This May will be released Symfony 3.3 with many DependencyInjection improvements.
Each of them is quite nice, <strong>but combined together - they are huge jump</strong> compare to what we have now.


Today I will show you what code can you drop and how to migrate it.
 ]]>
            </summary>

            <updated>Sun, 07 May 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Combine power of PHP_CodeSniffer and PHP CS Fixer in 3 lines ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/05/03/combine-power-of-php-code-sniffer-and-php-cs-fixer-in-3-lines" />
            <id>https://tomasvotruba.com/blog/2017/05/03/combine-power-of-php-code-sniffer-and-php-cs-fixer-in-3-lines</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ At time of publishing this article, PHP_CodeSniffer has over **5 381 stars** on Github and **210 default sniffs**,
PHP CS Fixer with **6 467 stars** brings you **160 fixers**.

Both powerful tools dealing with coding standards with **huge communities behind them**.
Can you imagine using them both and actually enjoy it? Today I will show you how.
 ]]>
            </summary>

            <updated>Wed, 03 May 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 3 Symfony and Laravel Patterns that Make Code Easy to Extend Without Modification ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/04/14/3-symfony-and-laravel-patterns-that-make-code-easy-to-extends-without-modification" />
            <id>https://tomasvotruba.com/blog/2017/04/14/3-symfony-and-laravel-patterns-that-make-code-easy-to-extends-without-modification</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Do you write open-source? If so, you probably get many PR and issues about adding new feature, that people miss.

You can add them and increase project complexity or deny them and increase people's frustration. Both sucks for somebody. I prefer win-win situations: <strong>keep complexity low and add new features</strong>.

Magic? No, <strong>just patterns</strong>! Today we look on 3 of them I found and fond in Symfony and Laravel world.
 ]]>
            </summary>

            <updated>Fri, 14 Apr 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Drop all Service Tags in Your Nette and Symfony Applications ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/02/12/drop-all-service-tags-in-your-nette-and-symfony-applications" />
            <id>https://tomasvotruba.com/blog/2017/02/12/drop-all-service-tags-in-your-nette-and-symfony-applications</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ What is tagging for? Why we should get rid of it?
Today I will show you, how to do it gradually without breaking the application.
 ]]>
            </summary>

            <updated>Sun, 12 Feb 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ Why I Switched Scrutinizer for PHPStan and You Should Too ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/01/28/why-I-switched-scrutinizer-for-phpstan-and-you-should-too" />
            <id>https://tomasvotruba.com/blog/2017/01/28/why-I-switched-scrutinizer-for-phpstan-and-you-should-too</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ I used Scrutinizer for a few years now for code coverage and code quality. Configuration was far complex, some issues appeared and build kept failing. But I really wanted a code quality checker for my open-source projects and this was the best tool available.

But last week I had an issue with simple `composer install` command and I have had enough. Then **my attention turned to PHPStan**, soon-to-be its replacement.
 ]]>
            </summary>

            <updated>Sat, 28 Jan 2017 00:00:00 +0000</updated>
        </entry>
            <entry>
            <title><![CDATA[ 7 rad, které bych si dal před odchodem na vysokou školu ]]></title>
            <link rel="alternate" href="https://tomasvotruba.com/blog/2017/01/15/7-rad-ktere-bych-si-dal-pred-odchodem-na-vysokou-skolu" />
            <id>https://tomasvotruba.com/blog/2017/01/15/7-rad-ktere-bych-si-dal-pred-odchodem-na-vysokou-skolu</id>

            <author>
                <name><![CDATA[ Tomas Votruba ]]></name>
            </author>

            <summary type="html">
                <![CDATA[ Už jsou to 4 roky, co jsem ukončil vysokou školu, aniž by mi za to dali titul. Během těch 4 let se mě na vysokou školu ptalo lidí, které bych spočítal na prstech jedné ruky. A na titul? Nikdo.

**Nedávno jsem si volal s jedním středoškolákem a zjistil jsem, že vysoká škola je stále brána jako něco posvátného, důležitého a hlavně bez vhledu nikoho jiného než učitelů a rodičů.** Řekl jsem si, že sepíšu svoje postřehy a rady, které bych si moc rád dal 8 let zpátky.

**Jestli je ti 18-19 let a zvažuješ co dál, pokračuj.**
 ]]>
            </summary>

            <updated>Sun, 15 Jan 2017 00:00:00 +0000</updated>
        </entry>
    
</feed>
