I built Rector, which upgrades and refactors your codebase for you. Turns out the hard part was never the code.
So I write about the tooling here and coach leaders whose codebase got slow to deliver. I studied psychology before PHP - legacy code carries trauma, so I go for the core first, then the code follows. Lately I am also into Go tooling and agentic workflows.
Do these tools bring you value? Sponsor me on GitHub ♥
We lived in quiet and peaceful times in the PHP community about 11 months ago, in late 2025. We didn't have agents yet, we managed projects manually and we had our favorite frameworks and tools we used for years.
Then this weird package came to my attention, on Reddit, something written in Rust. Looked like a replacement for PHPStan. I thought it was AI slop (as most projects were popular for a month and then disappeared), so I ignored it.
Then in spring 2026, agents came. Mago was still there.
I was randomly drifting through Github trending PHP repositories, and checking how popular projects use rector.php. A lot of them use it extensively, with prepared sets and even levels.
What I didn't like to see is the skip section. It's like a baseline in PHPStan, but I take it really seriously. In 90 % of cases, it means something is broken in Rector and the user had to skip it to avoid unwanted changes over and over.
Feeling the frustration, I thought: Is there something we can do about it?
Easy Coding Standard got a new release last week with a couple of cool features and new dead docblock rules.
But the tool is only as powerful as its master. With agents, even more so. I've noticed people use ECS in an overly complex way, which is not needed... and definitely not fun. If it's longer than 15 lines, you're probably doing it wrong.
That's why I want to go back to basics and share my personal tips on what the ecs.php config should look like. Feed this to your agent, or learn it yourself.
Easy Coding Standard focuses on easy setup, easy run, and easy use. Last year we simplified the config to a single fluent line.
Today we ship ECS 13.2 - a release that makes ECS lighter to install, smarter about docblocks, and more fun to integreate to a large project, step by step.
Let's look at what's new.
PHPStan core gets you to level 10 with solid type checks. But some gems, the rules that catch your anti-patterns, live scattered across a dozen community packages most people never hear about.
I got tired of hunting through GitHub READMEs to find "is there a rule for this?", so I built a single searchable page that indexes 11 custom PHPStan rules packages.
We've all seen it: new Human() followed by three setName(), setAge(), setEmail() calls that are always there. Not optional - just pretending. These are constructor arguments in a fluent disguise, and they leave your objects half-valid every time someone forgets one.
So I made a small PHPStan extension to find them.
In previous parts (part 1 and part 2) we looked at a situation where we are stuck with Alice, Nelmio, Hautelook, Faker legacy mess and need a way out to modern maintainable Doctrine.
This is the final part. The upgrade is finished and closed for the time being. In an unexpected way, it was fast, easy to migrate to, and will be even easier to maintain. It took me a couple of months of deep thinking and experiments, because there was a trap solution that would take us 6-8 months of hard work and would create even more legacy code. Lesson learned: don't fall for marketing and GPT answers.
Let's look into it.
I switched this website from Symfony to Laravel 2,5 years ago, and I love Laravel Container ever since.
Symfony and Laravel containers are very similar - read this compare post 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?
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?
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.
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, 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.
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.
Using PHPStan is not just about getting to level 8 with less than 100 ignored cases. Yes, there are also official extensions 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.
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, 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.
Another year is gone, and it's tradition to pick 5 books I enjoyed reading in 2024.
In the first part, we've kicked off the plan 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.
Symfony 3 introduced a @required annotation (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?
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.
Final classes bring much more value than extends it lacks. It teaches composition over inheritance, makes upgrades easier, and even mocking is fine.
If you're lazy like me, you can automate the final keyword addition to your code - quickly, safely, and check it the CI!
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 that explains why the latter is better.
There are no sources about Symfony upgrades spanning multiple major versions—time to fix that.
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.
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.
The legacy projects we work with are often flooded with mocks. I already wrote 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.
The withConsecutive() method was deprecated in PHPUnit 9 and removed in PHPUnit 10. It sparked many questions, on StackOverflow, in various projets and GitHub.
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.
Recently, I listened to Lex Friedman's podcast with Pieter Levels. 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.
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.
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.
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.
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.
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?
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.
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.
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?
...and how to avoid it.
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.
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.
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.
In the first post, 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.
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.
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.
Eventually, this opened the door to further innovation that I'll introduce today.
I've read over a dozen books in 2023. Here are 5 favorites that influenced me the most.
In the first post, 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.
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 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.
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.
Do you use Symfony-console based tools? If you're using Composer, Rector, PHPSpec, PHPStan, ECS or 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?
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, it's clear the switch is doable.
Today, we'll look at the steps to prepare your Symfony project for future Laravel migration.
Do you want to migrate your Symfony project to Laravel and not sure if it "handles it"? Switching containers is pretty straightforward for the most parts.
But can Laravel handle advanced features such as compiler passes?
When Nuno sent me a Pest plugin for type coverage that runs 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.
The famous 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 and for fast estimation of project size in Rector upgrades.
That's why I needed a replacement. Fast!
Last month I successfully switched the Symfony container for Laravel one 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.
In the last post I shared a trick 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.
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.
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.
This year I've been learning Laravel and quickly adapting to most of my tools. I've made 2 packages - Punchcard to handle configs and Bladestan for static analysis of Blade templates using PHPStan.
The component I wanted to put in tests was Laravel Container. 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.
PHPStan and static analysis help us with detect unused private methods. I also made a package to handle unused 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?
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.
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?
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."
This Tuesday, I was a guest in 2nd podcast of PHP Portugal folks. It was fun as always, and apart from GPT questions, I got asked about the Laravel open-source packages like Punchcard.
I promised to put the 2nd package this week, so here it is.
This week I've been working a lot on GPT in 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 and got such a variety of replies, that it deserves a blog post.
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 ecosystem. The migration went very well, as most of the code is intuitive. There was just one clear bottle-neck: the array configs.
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.
Last week, I kicked off the first post about tips and tricks with GPT. In the meantime, Marcel posted a great practical piece on GPT and solutions based on exception messages.
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.
Have you moved your Symfony configs from YAML to PHP with the help of Config Transformer? Do you use the PHP benefits daily?
But how do you make sure no YAML is leaking from a new developer or in test configs?
Last week, I had many interesting discussions about OpenAI and GPT on Laracon in Porto. Especially with Marcel Pociot.
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.
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?
I kicked off the unit test generator idea with the first post a week ago. It was a great success on Reddit, 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.
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.
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.
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).
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?
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 including vendor, and we know it will run on PHP 7.2.
But how to achieve the same with the package with separated dependencies?
If you have not switched your Symfony configs from YAML to PHP, 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?
This bold question has been around PHP Internet for many years... at least since 2008. In 2017 I added dead public method sniff 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.
In the previous post, we set on 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?
In previous post, we explored the "whys" for Twig Smoke Rendering.
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.
Two weeks ago our upgrade team started 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. I'm happy I did. Alexander Schranz came with a tip that led me on a 2-week journey, and I would love to share it with you today.
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.
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 and ECSConfig.
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 last week, we found an even better generic solution.
Are you interested in a better developer experience for your Symfony project? Keep reading.
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.
The beauty of 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?
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.
Native 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.
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.
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.
After we cut the low-hanging fruit, we discovered the same way are skipped all callable types. How to deal with those?
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?
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?
In the previous post, we looked at When Symfony Http Kernel is a 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?
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, 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, and the issue became visible more than ever.
I knew there was a time for a change.
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.
Do you use 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, 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.
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?
This post will get you from 0 to padawan in a couple of minutes.
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?
Would you like to understand parallel in PHP apps?
Do you have just 60 seconds?
In the previous post, we finished the conversion of TWIG to PHP, run PHPStan on temporary PHP file and got list of found errors. We've done a full circle, and PHPStan analyses our TWIG templates.
I've shared the intro post on Reddit, that sparked many exciting questions.
Today we'll answer one of them.
In the previous post, we finished the conversion of TWIG template to clean and objective PHP 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.
In the previous post, we looked at 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.
In the previous post, we looked at how to compile TWIG to raw 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.
In the previous post, we looked at why and when static analysis of templates matter. 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.
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.
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.
The PHP FW 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 data far from reality.
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.
Do you know PHPStan, ECS, Monorepo Builder, PHPUnit, Config Transformer or Rector?
In the previous post, we explored why are these tools scoped, 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.
Do you know PHPStan, ECS, Monorepo Builder, PHPUnit, 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.
Do you want to make your tool resistant to any conflict with any project dependencies? Today I'll show you how.
Already over 120 people bought the Rector book 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.
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.
In previous post 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, 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.
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?
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 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.
PHP 8 came with 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. 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.
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?
In October 2020, we had a short call about Rector with Matthias Noback. 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 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.
In a recent post 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.
In previous post we talked about how to promote generics to parent class.
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?
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?
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 and works well.
You know I'm a big fan of GitHub, so when client asked me: "how can we do it in Gitlab?"
I was like: "that's not possible... you need to switch to GitHub".
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.
The version 1.0 was released 6 months ago. 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?
Traversing and modifying PHP code is possible thanks to the amazing tool 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.
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?
Have you switched your Symfony configs from stringy YAML to typed PHP? If not, do it now. Here is at least 10 reasons why. 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.
Last weekend I got into reading a good old post 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.
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?
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.
Conjunction of 2 releases came in December 2020, Symfony 5.2 and PHP 8.0.
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...
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.
Was it worth it? Hell yea!
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?
Do you want split monorepo 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?
Composer 2 was released this week. It brings massive composer install/update performance improvement of 150-200 %.
That means faster feedback 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.
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...
Today I have a tip for your CI. I learned this tip from Jan Mikes.
A small tip that made my everyday work with CI more colorful.
I wrote the 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 on the Symfony markets, auto bind parameters became obsolete.
Welcome constant parameters.
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!"
Do you know 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?
You can tell I'm a huge fan 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.
In the previous post, 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.
What makes one give?
For me, it's a combination of gratitude, abundance, and inspiration in the surrounding.
In previous post, we looked 10 reasons to switch from YAML to PHP configs. Still asking why? I dare you to disagree with 1 reason there.
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?
In previous post, 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?
You've probably noticed Symfony is moving towards PHP configuration. 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 - 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.
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, nikic/php-parser. It's so good I'm surprised not everyone is using it.
Today I'm starting a new post series - Cleaning Notes. These posts are for people who are aspiring legacy migrators 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.
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"?
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.
That's only past or present.
I'm just finishing the reading of The Inevitable, written by Wired magazine founder, that focuses solely on the future. Inspired by this book, today, we look at the future of programming.
Do you use PHP 7.4 typed properties? 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?
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.
I wrote intro to Symfony\EventDispatcher 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.
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. I felt like last year I'm not giving it as much energy as before. But why?
Since Symplify 7.3, you might notice a few deprecation notices in your coding standards. As Symplify 8 release is synced with Symfony cycle, 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?
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.
Recently, I introduced 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?
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.
Recently we've upgraded our Czech PHP community website 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.
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.
"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.
In 14 months old post How to Test Monorepo in 3 Layers 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?
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?
In the previous post, we looked at 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 :)
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?
With Symfony 5 upgrade, we need any working Doctrine behaviors.
Month later, we have KnpLabs\DoctrineBehaviors 2.0 with full Symfony 5 support.
If you used older Doctrine Behaviors, you're covered with Rector migration path.
But what if you're using old broken Gedmo?
I'll show you how you can migrate Gedmo to KnpLabs.
In 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?
I started to write this post as follow up for clean and sustainable code 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.
"How much will cost upgrade from Symfony 3 to Symfony 4 with Rector?"
Similar questions fill my personal and Rector email 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.
We talked about cleaning legacy code with Rector 2 months ago on 40th meetup of PHP friends in Prague.
Who is we? Me and CTO of the company I worked for, a great leader and technical expert who taught me a lot, Milan Mimra.
The talk was not full of shallow tips, nor about framework migration. Instead, we talked about small decisions that were made 2 years. Decisions, which took 3 months to get rid of.
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?
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.
I wrote 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?
Last month I was on PHPSW meetup in Bristol UK with Rector talk. To be honest, Nette to Symfony migration 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.
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?
I'm currently working as Rector consultant for Spaceflow, 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.
I wrote Don't Ever use Symfony 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.
But what can you do, if you'd like to try subscribers, but currently have over 100 listeners in your application?
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 from 1999 and you won't believe what happened...
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.
I was surprised, how much of your attention got 5 Tips to Effective Work with Github Repository post.
So I started to collect tips I use on training and mentoring that I don't even notice, but others find fascinating. Here is 5 of them.
People keep asking me about IDE plugins for Rector 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?
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?
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?
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.
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!
PHP itself is very quickly adopted. Last Packagist stats from 2018/11 report 32,6 % 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?
In 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.
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?"
Symfony recently announced a new version of Twig 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.
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.
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?
We had 🍺 after PHP meetup in Prague and Tomas asked me:
"We don't use Nette, but we still have many tests in Tester. Can Rector migrate them to PHPUnit?"
"Hold my 🍺"
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.
After few long Nette to Symfony migration series, it's time for relax.
Let's look at 7 snippets of PHP code, that happily takes your attention but is never run.
Do you want to migrate your project from Nette to Symfony? In the part 2 we looked at escaping semver hell.
Today we'll look on package vendor-locks caused by brain drain.
Do you want to migrate your project from Nette to Symfony? In 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.
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?
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.
Now it's much easier to jump from one LTS to another - with instant upgrades.
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?
On the break of January/February 2019, we migrated whole Entrydo 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.
Yet, you'd laugh if you knew what took us the most time.
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?
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.
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.
I see too many skilled developers missing final in every class they use. So I reposed 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.
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...
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...
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.
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.
I want to write about you, my dear reader and contributor. I would not make it this far without you in 2018.
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.
Last week we hosted Kirill Smelov 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!
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)?
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 is?
Don't learn to code. Learn how to think.
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?
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!
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?
Recently I gave a few talks about monorepo in PHP 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?
PHP 5.6 and 7.0 is going to be dangerous since 2019, 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?
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 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.
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 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?
In the last post 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?
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?
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 where I talked about Rector.
It was my first trip to Asia ever, so obviously, it went wrong...
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.
But what if the police come to bring you in for your financial frauds and child porn, what door do you take to run?
My recent post about lovely exceptions opened very interesting question. In comments bellow the post, in Reddit thread and on Twitter.
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?
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?
Let's get lazier and lazier.
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.
After a few technical and open-source posts, it's time for brain hacking. 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, you'll be valuable by actually making AI or by hacking your brain to be super-adaptable and irreplaceable.
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.
I'm working on ChangelogLinker, a package that makes managing CHANGELOG.md very easy - it generates it. It a CLI Application with a 3 Console Commands. All was good, until I needed to add an argument to all commands at once... and in lazy, extensible, maintainable way.
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!
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?
After very successful PHP 7.3 diffs post, let's dive to gifs of Symfony Plugin for PHPStorm. You might know them, but they might surprise you like they did surprise me. Let's go!
No time but eager to hear PHP news? PHP 7.3 is out in December 2018 and it brings 173 changes. Which are the most useful ones?
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.
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.
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.
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 package.
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.
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 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?
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.
Statie - a tool for generating static open-sourced website like this blog or 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.
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.
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.
Recently, I've read Selling is Human by Daniel Pink. He's famous for 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.
I wrote 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.
Martin Hlaváč had a very nice talk about testing in Berlin PHP Meetup last week (while I hosted with 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"?
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.
Last year, I helped Shopsys CS and LMC CS 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.
I have been asked this question over hundred times, in person, as a post request. 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.
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
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.
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.
Today we look on the first barrier that leads most people to prefer static over DI - how to load config with services.
I saw 2 links to Symfony\Console in today's Week of Symfony (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 or Symfony Console from the Scratch.
But nobody seems to write about the greatest bottleneck of Console applications - static cancer. Why is that?
Artificial intelligence is at boom the last couple of years. I wrote about AI and its relation to jobs development 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?
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.
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.
Last week I wrote about top 5 bloghacks I found in this book.
Today I'll share with you 5 tips that proven useful during my programming/self-education career.
Have you heard of 256 Bloghacks book 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.
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.
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.
Today I wanted to write about Rector showcase how to use it to automate migration to Repository as Service in Symfony.
Instead I read Teaching PHP to students 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?
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.
Do you know *.neon format? It's config file format created in Czech Republic by David Grudl (author of Nette) and if you're foreigner, you might know it from or EasyCodingStandard and PHPStan. Even suggested as composer.neon.
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?
How to achieve open for extension and closed for modification one of sOlid principals?
Why Collector pattern beats config tagging? How to use the in Symfony application? How it turns locked architecture into scaling one?
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?
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 that feedbacks and reflects.
Rector is a PHP tool that handles 2 things: instant upgrades and architecture refactorings.
What exactly Rector does and how does it work?
Even though I see University as very poor place to learn something useful, I studied Psychology in Brno for 3 years.
Psychological Impacts of Polyphasic Sleep is the topic of my bachelor thesis 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?
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?
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.
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.
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...
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.
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.
Today we can do amazing things with PHP. Thanks to AST and nikic/php-parser we can create very narrow artificial intelligence, which can work for us.
Let's create first its synapse!
I wrote about monorepo and how it turned me into lazy programmer before.
As monorepo is use more and more, we should look at it again. Today from a bit atypical point of view: combined with bit of blood and sunshine.
Are you ready?
You have probably heard about Inbox Zero. ZTD technique, to keep your email inbox clean and your brain well rested.
Let's take it a step further into 2017 - to instant messaging.
Dependency injection with autowiring is super easy since 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 by many before and now we put it into Symfony 3.3 context.
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?
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.
Do you use PHP CS Fixer or PHP_CodeSniffer? Do you know the way they work is ~80 % the same? Do you wonder how they work under the hood?
Today I will share 3 main pillars of their architecture.
You already know how coding standard tools work with tokens and how to write a Sniff.
Today we'll explore another tool - PHP CS Fixer and we get from finding the smelly spot to fixing it.
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 know to write your first sniff.
You create PHP open-source packages because you personally use them in your projects. And you take care of them. 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 package is getting obsolete.
You can do 2 things in this situation: nothing like most people do or take responsibility, deprecate package and inform your users about better alternative.
While using open-source, we rarely realize that there is one or few people behind it. People who work in their free time and put an effort in it. 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 my gratitude and tribute for you, David - you made my programming life very joyful and curious experience.
This May will be released Symfony 3.3 with many DependencyInjection improvements. Each of them is quite nice, but combined together - they are huge jump compare to what we have now.
Today I will show you what code can you drop and how to migrate it.
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.
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: keep complexity low and add new features.
Magic? No, just patterns! Today we look on 3 of them I found and fond in Symfony and Laravel world.
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.
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.
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.
Stuck on a codebase nobody wants to touch? Let's talk about it.