One of the harder bugs to debug are bugs dealing with mutable data. A while ago we ran into a problem where the last_modified date of entities was always 1 day off. See if you can spot the issue in the code below: class MyEntity { public function __construct ( public DateTime $lastModified ) {} } function saveEntity ( Notifier $notifier ) { $now = new DateTime (); $entity = new MyEntity ( $now );…
In JavaScript, there are a few ways to add an element to an array. Depending on whether you want to add an element to the start or the end, or even in the middle. Using Array.push() or Array.unshift() to add elements to the array With Array.push() you add an item to the end of an array, and with Array.unshift() you add an item to the begin of the array. const cities = [ 'Stormwind' , 'Orgrimmar' ,…
Adding types to your PHP code base is more than just runtime validation. It helps both developers and static analysis tools, by making the code clearer and easier to understand. Adding types makes code more self-explanatory and gives you a form of documentation. A function with proper types will help clarify what it is supposed to do. It becomes easier to determine what a function does from…
When debugging an older application, just reading the code might not be enough to find all the queries it does. Sometimes queries are done in a worker as well, so finding out exactly what happens can be difficult. Thankfully we can enable mysql query log, to see the results. And its easy to enable as well. All you need are the following SQL statements: SET GLOBAL log_output = 'TABLE' ; SET GLOBAL…
A while ago I got a new macbook, and installed firefox again. But I quickly ran into the issue where if you press escape, it closes the fullscreen. Which to me is an insane default, as I might press escape to try and close a modal for example. Thankfully the fix is pretty easy. Just go to about:config (put it in the address bar). You might have to press an Accept the risk and continue button. In…
I’ve come to prefer using array functions over foreach loops in PHP. And while the syntax isn’t as nice as in JavaScript, I still think they work better than a ’normal’ loop. What are array functions In PHP you have quite some array functions , each with their own use. For this post I’m talking about the functions that loop over an array, and execute a function for…
I was a butcher for roughly four years before I became a software engineer. (And nowadays, I’m a vegetarian.) And while one of the jobs doesn’t require you to work inside a refrigerator half the time, there are actually quite some similarities in how we keep our work environment clean. Keeping your work environment clean Both as a butcher and as a software engineer I see four different…
This week I wanted to change all the .js files to .ts recursively in a folder. To change all .js files in the assets folder. With a bit of bash, using a for loop and mv I got the following command to rename all my .js to .ts files. for f in assets/*.js ; do mv -- ' $f ' ' ${ f %.js } .ts' ; done If you want to get notified of the next blog post, join the newsletter.
This week I noticed a test was flaky, and was occasionally failing in CI. So I wanted to re-run my script until it failed. I had no clue how to do this, so after a bit of trying, I got the following script. This keeps running vendor/bin/phpunit until it fails. You can save it as run.sh and then just run sh ./run.sh in your terminal, and it will keep running. #!/bin/sh set -e while [ true ] do…
There are a lot of ‘rules’ in software engineering. Don’t copy-paste your code, don’t use goto , your code should be easily understandable, and many more. Generally these rules make sense, but every once in a while someone will have a hot take, and post about how you should copy-paste your code everywhere, how goto is the greatest invetion ever, or how variable names should…
This week I learned of a small change that got introduced in PHP 8.2 that I completely missed. The iterator_*() functions got an update, which make them actually usable when dealing with the iterable type. Now this is only really relevant if you are dealing with iterables that might not be arrays, but you need to use them as an array. The big change is that a function like iterator_to_array , it…
Something I’ve been hearing myself says in every project that I have installed Psl in, is “Just use Psl for that”. And while some bits and bobs like array_find are getting into PHP 8.4, the library does so much more. In this post I’ll go over the bits that I use often, and maybe convince you to give it a try as well. What is Psl Psl is a php composer package that can be…
We have been able to natively type parameters of methods and functions in PHP for quite some time. In basically any version of PHP you should be running we can do something like the following: function getNames ( array $input ) : array { return array_map ( function ( $item ) { return $item -> getName (); }, $input ) } Basic array types This however tells us very little about the types that we are…
The problem This weekend I was at a holiday resort. In the morning I wanted to do a little bit of work, and encountered the following error when I tried to pull a repo. $ git pull ssh: connect to host github.com port 22: Operation timed out fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. At first, I assumed my internet…
You may have had people tell you that you should use declare(strict_types=1); in your PHP files, but what exactly does it do, and why should (or shouldn’t) you use it? History A long, long time ago PHP didn’t have scalar types, or even return types. In PHP 7.0 both of these got introduced. In 5.6 and before we had to use annotations, and couldn’t add it in the language. (If you…
Recently I wanted to make some changes to my SSH config, but I didn’t want to accidentally break anything, and lose my correct config. So I manually did an mv ~/.ssh/config ~/.ssh/config_back , made some changes, and moved it back again. I had to do this a couple of times to try out different things, and realized I had done things like this quite some times just to make a quick backup with…
When you want to know how many rows a table in MySQL has, the easiest way is: SELECT COUNT ( 1 ) FROM < table_name > ; However, if the table is massive, this might take a long time, as it needs to look at all rows. Thankfully there is another way in mysql, where you can get a rough estimation of the row numbers: SELECT TABLE_ROWS FROM information_schema . tables WHERE TABLE_NAME = '<table_name>'…
PHPStan PHPStan is a static analysis tool for PHP. It helps you find problems in your code base, like passing wrong types, calling methods that don’t exist, detect wrong annotations, and so much more. I would argue you shouldn’t be writing PHP code these days without having a static analyzer to help you. It reduces the errors you create, and speeds up your development significantly.…
Deep work I finished reading deep work about a week ago. If you want to become a mythical 10x developer (or 10x anything really), this book provides you with the tool on how to succeed in just that. A lot of us fall into a trap of doing mostly, what this book calls, shallow work. We have meetings that aren’t really important, we do meaningless tasks, and spend half our day in meeting that…
A big part of software engineering is code review. Good code reviews will help your code base become better and help you and your colleagues learn from each other. Let’s take a look at some code review best practices and tips! 1: Have your tools check the code for you The best way to have good code review is to reduce what needs to be reviewed as much as possible. When reviewing code, I…
In GitLab, sometimes you want to (temporarily) allow a script to fail. It may be that you are running your tests against a newer PHP/NodeJs version, which you are not yet compatible with. In that case you can allow the pipeline to fail, without blocking anything else, or turning it red and blocking your merges. As mentioned in a previous post , you shouldn’t be abusing it, but sometimes you…
In JavaScript, there are a few ways to check if an array contains an element. Depending on if you need to know if it contains an exact value, or match a criteria, you have different options. Using Array.includes to check for an exact value With Array.includes() you can check that your array contains an exact value you are looking for. For example: const trees = [ 'oak' , 'willow' , 'maple' , 'yew'…
In JavaScript, there are a few ways to remove an element from an array. Depending on whether you want to remove elements by value, by index, or based on a condition, you have different options to choose from. Using Array.splice() or Array.toSpliced() to remove elements by index With Array.splice() you can remove an element from an array by telling it from what index you want to start removing and…
Hopefully you are already using PHPStan to analyze your source code. But you shouldn’t stop there, in fact, you should also make sure you are analyzing your test code. Why analyze your tests If you are already using PHPStan to analyze your source code, then you probably see the value in static analysis. The same reasons for analyzing your source code are true for your tests. You can find…
If you want to do a for loop over an array in javascript you generally want to do a for (const value of array) { . Because this will loop over all the items of an array. A for (const key in array) { will instead loop over the keys of an array (or of an object). const letters = [ 'a' , 'b' , 'c' ]; for ( const value of letters ) { console . log ( value ); // 'a', 'b', 'c' } for ( const key in…
There are a lot of ways to generate a random string in PHP. In this post we’ll take a look at two options we have, and how to use them. The Randomizer The Randomizer class (introduced in PHP 8.2) is arguably the best way in OOP PHP to use randomness, and should be used whenever possible. It comes with 2 methods for creating random strings. Where getBytes will give you a random set of bytes…
In javascript there is a few ways of getting the last item in an array. In this post we’ll go over them Using Array.at() Array.at has been available in the major browsers and node, since mid 2021 (except safari which introduced it in safari 15.4 in early 2022). With Array.at you can simply pass -1 to get the last element, or -2 to get the second to last element, and so on. Or if that item…
This is part 4 of a series on PHPUnit testing, you can find part 3 here . In this post we’ll focus on the use of mocks. We’ll cover why we need them, the different types of mocks, and how to use them. Why do we need mocks? A mock is a stand in for a dependency that you dont want to (currently) test. The most commonly used example might be the database. In your unit tests, you…
This is part 3 of a series on PHPUnit testing, you can find part 2 here . In this post we’ll focus on the use of data providers. I have written about them before, but for earlier PHPUnit versions. This post is relevant for PHPUnit version 10 or higher. For version 9 or lower check out the original data provider post What are data providers? A data provider is a function or method that, as…
This is part 2 of a series on PHPUnit testing, you can find part 1 here . This post will have us writing our first unit test, and explain some of the basics in doing so. TestCase class Every test we write has to extend the PHPUnit\Framework\TestCase class. PHPUnit will look for classes in its configured folders that extend from this class, to execute tests. Within your class it will look for all…
Here you can find books that I highly recommend any software developer to read. Clean Code Clean code by Robert Martin is probably the single most influential book for me as a software engineer. I read it while in college, and it changed the way I write code tremendously. It especially opened my eyes on how I wrote comments. You can find it on Amazon . Working Effectively with Legacy Code Working…
In this blog series we’ll go from writing our first unit test to being a PHPUnit master. This first post will go over the basics, and introduce you to PHPUnit What is PHPUnit? PHPUnit is the de facto testing framework for PHP. It initially started in 2001, over 23 years ago at this point. And even today it is still under active development. All its development is done on , where you can open…
Today we ran into an issue with a build in one of our projects. Composer could no longer install, as a dependency was gone. When we opened our pipeline logs we saw the following error: failed to execute git checkout '<ref>' - - && git reset --hard '<ref>' -- fatal: reference is not a tree: <ref> It looks like the commit hash is not available in the repository, maybe the commit was removed from the…
The idea of a Uses page is to tell you about the stuff I use. Make sure to check out uses.tech for a list of everyone’s Uses pages! I often get asked about what software or hardware I use, so this page will serve as a living document and a place to point curious readers to when I get asked. Hardware I’m using a 14" M3 Pro MacBook Pro with 11‑core CPU, 14‑core GPU with 36GB RAM . So far…
We’ve all had our CI fail due to an issue that couldn’t be fixed right away. Usually something like a security issue in a downstream package that can’t be updated yet. This then causes the build to fail, making us unable to merge or deploy. allow_failure seems like a great way to solve this, but it is not. allow_failure is setting us up for failure. Because now any issue with…
When writing code, you generally want to split up the logic in to different classes. You have your controller classes which take a request, and return a response. You write value objects to represent information which is important to your application. You may write commands, command handlers, repositories and more. The most important group of classes you write are probably your services, which…
Recently we’ve been looking into differential serving. With our set up there were a few complications, so in this post i’ll share how we overcame those, and how to set up differential serving with webpack encore. If you want an explanation of what differential serving is, or how to do with with a normal webpack setup, i suggest reading this post . In our project we use webpack encore .…
If you are familiar with Typescript, you may know their any type. With any you can do anything. It signals that you don’t know about the actual type, and that anything goes. The following code is completely valid in Typescript. const doTheThing = ( input : any ) => { input + input ; input . toString (); Object . keys ( input ). map (( key ) => { return input . foo [ key ]; }); const [ one ,…
We’ve been using CSS modules in a react project, and wanted to use those classes in our tests. However we quickly ran into the problem that none of the classes were found. Any wrapper.exists would be false. The problem was with our css modules, as they were not imported correctly during tests. Our code looked like this: import styles from './QA.scss?module' ; interface QAProps { question :…
Last week i gave 10 phpunit tips . This week we’ll take a look at testing exceptions, which wasn’t covered in that post. Lets start with some example code that we will be testing. We have the Email and EmailValidator classes. Email is a value object that makes sure it is a valid email. We use the EmailValidator to make sure that the emails are only from our company. //Email.php final…
PHPUnit is the defacto testing framework for PHP. In this post i want to share with you my top 10 tips for PHPUnit. I’m using PHPUnit 9.5, but most of these apply to older versions as well. So, lets get this party started. 1: Stop using assertEquals One of the most common mistakes is using assertEquals . Instead, you should be using assertSame . When using equals we are doing an == check,…
Recently we ran into a problem with doctrine migrations. The schema was manually edited, and wrong migrations were committed to the repository. For a dev (and even staging) env you could just drop the database, fix the migrations, and run them again. But we didn’t want to lose our production data. So how do we fix this? We really had 2 problems. Our migrations were wrong, and the…
I’m a fan of twig, and wouldn’t consider moving back to plain php. But, it does come with a few problems. In this post we’ll explore one of the problems i have with twig, and how to work around it. The problem When you use a twig file, you do not know what variables it needs, what variables i can use, and what types those variables should be. You have to read the template, or…
Don’t worry, this isn’t a ‘what type of sandwich are you?’ kinda post. Instead we’ll look at how we can safely add types to our legacy code. Adding types There are really two ways of adding types. You either declare what you want your types to be, or you declare what the types can be. When writing new code we should always be precise in our types, so we declare what…
Does your project use PHPStan? Then you really should be using the bleeding edge config, regardless of what level you are running. It will make transition to the newer version much easier. What is bleeding edge To preserve backwards compatibility as much as possible, new rules, and new settings are delayed until the next major version. For example, using null coalesce on a variable that can not be…
Once you have set up your first unit tests, and you have a good configuration , its time to add a lot of tests. Lets take a look at using data providers, as a way to test with a lot of data. For this example we’ll test a piece of code that is supposed to do the following. Given the array ['a', 'b', 'c'] , return the string a a-b a-b-c b b-c c . This function has to combine the array values…
If you just got started with PHPUnit, its configuration file may be a bit daunting. Today we’re gonna walk through (what i consider) the ideal config file. If you’re just here to copy paste the config, then you can find it at the bottom 👇. A minimum phpunit.xml may look like this: <?xml version='1.0' encoding='UTF-8'?> <phpunit> <testsuites> <testsuite name= 'Tests' >…
Just like the factory pattern, the builder is a creational pattern, meaning it is about how objects are created. But unlike a factory, a builder allows you to build an object in parts. I tend to use it for creating objects that take a configuration. Lets start with an example. This class builds a guzzle client, with a certain config. Normally we have a timeout of 10 seconds, with a 5 second…
The previous two chapter of this blog series were about the decorator and the adapter . These are structural design patterns. Meaning they deal with the structure of a system. They can help with simplifying relationships, and moving responsibilities. The factory is a completely different type of design pattern. Its a creational pattern . A creation pattern is intended to make creation of objects…
This is the second post in a series of design patterns i use (almost) daily. You will find the other posts at the bottom of this article. On wikipedia , the adapter pattern is described like so: the adapter pattern is a software design pattern (…) that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others…