[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...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 *...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 extensio...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 you...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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).| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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!| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 ad...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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/...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
...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 %. Once we reach high coverage of 80-90 %, we feel safer. But our code can actually be in worse, even dangerous, shape.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
I've read over a dozen books in 2023. Here are 5 favorites that influenced me the most.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 ...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 Symf...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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!| Read about upgrades, static analysis, GPT, Symfony and Laravel
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).| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 sc...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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, b...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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."| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.**| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 wer...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 ...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 `'hell...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 ...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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**.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 fou...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 t...| Read about upgrades, static analysis, GPT, Symfony and Laravel
[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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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). ...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 **...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?**| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 ...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 EC...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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?| Read about upgrades, static analysis, GPT, Symfony and Laravel
Would you like to **understand parallel in PHP apps**? Do you have just **60 seconds**?| Read about upgrades, static analysis, GPT, Symfony and Laravel
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. Today we'll answer one of them.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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**.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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**.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 yo...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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.| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 techniq...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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 lea...| Read about upgrades, static analysis, GPT, Symfony and Laravel
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/)...| tomasvotruba.com
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?| tomasvotruba.com
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.| tomasvotruba.com
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 bu...| tomasvotruba.com
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 latte...| tomasvotruba.com
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. 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.| tomasvotruba.com
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.| tomasvotruba.com
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?| tomasvotruba.com
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?| tomasvotruba.com