skoop.dev

  • About
  • @skoop@phpc.social
  • Sustainable open source

    May 1, 2026
    contribute, open source, php

    Some years ago, during lockdown times, ThePHP.cc talked me into writing a talk for their online conference. They knew my company tried to support open source in several ways and hoped that I would share the how and why. Since then, I’ve done that talk at several conferences (including the amazing Dutch PHP Conference and PHPDay). I’ve not done this talk since 2024, but the lessons are still important. After a little prod by Stefan Priebsch, I decided to write a blogpost about how I look at this now.

    Open source

    Open source exists in many forms, but the basic idea behind it is that the source code for software (or libraries) is available to look at, audit, and use. If the license permits, you could even alter and re-use.

    But open source doesn’t just exist. It is built by many people around the world, for all kinds of reasons. To me, open source is not just “a thing I can use”. If I decide to use open source, I become part of the community. And a community is not a place where you just take. It is an interactive organism where you give and take.

    Given the amount of open source I use, it would be impossible for me to give back to all projects all the time. But we shouldn’t feel the necessity to give back to all open source projects. Being an active part of one or several communities is already a great way. The choices you make in what projects to support can be important, however.

    The responsibility for companies

    As a personal user of open source, I feel I should be part of the community. But for commercial organizations, I feel there is an added responsibility. Because if you use open source inside your company, either as user of software or as developer building on top of libraries and frameworks, you earn a (hopefully healthy) profit off open source.

    I feel that if you earn money off of open source, then it is your responsibility to support open source. There are a lot of ways to do that and I’ll go into that later, but for now I just want to say: You should actively support open source.

    What projects to support

    Whether you’re an individual developer or a company, the first thing you need to do is make a choice. As I said before, it’s nigh impossible to support all open source projects. So instead, you can make a choice. And you can make that choice over and over again if you want. You don’t have to choose once and then keep supporting that project all the time.

    A great way of making that choice is to look at all the open source you use. Software, frameworks, libraries. By actively contributing to the projects you use yourself, you actively get value from your own contributions, because the project you contribute to gets better thanks to your contribution.

    It is important to have a critical look though at what projects to support. Every contribution helps, but a contribution to a project that has a small team or even a single person behind it has more impact. Of course it’s great if you contribute to Symfony or Laravel or phpBB or Drupal. But perhaps also have a good look at your composer.json file to see what other libraries you use that are made and maintained by less people. Not just will your impact be bigger because there aren’t a lot of other contributions, but those projects are also at a bigger risk of being abandoned. The bus factor is a lot higher on those projects. So having even just a single contributor added to such a project is huge.

    How to support a project

    There are many ways to support a project. Some are really easy, others are perhaps a bit harder. You don’t have to pick one, you can do multiple.

    The most obvious one that everyone thinks of is to contribute code. Send a pull request with a new feature is the one thing everything thinks is the best contribution to open source. And of course, that is great. But consider this: The maintainers of an open source project need to do everything: bug fixing, new features, keeping an eye on the big picture. So sending a pull request with a bugfix, or even some added documentation, is also extremely valuable, and allows for the maintainers to focus on the big picture and the new features. Having said that, if you think a new feature would be a great addition, by all means, start building it. But communicate with the maintainers, to make sure they agree on the feature and the way you want to approach it. It isn’t for for the maintainers and for you if your contributions gets rejected.

    But code is certainly not the only way to contribute. Some things we did as Ingewikkeld to support open source:

    • Give our developers work time to work on open source
    • Rector rules to migrate mockery to prophecy
    • Bug reports to several projects
    • Adding PHP8 support to some phpDocumentor components
    • Contribute to a PSR
    • Help users of open source projects on social media or in chats

    Aside from that, we’ve organized several events. WeCamp was a physical event, a 5-day code retreat where developers would be taken out of their comfort zone to learn new things and focus on both code and personal development. Comference, an online conference with a variety of speakers. And the Ingewikkeld Sessions, live streams focussing on a single topic, with a podcast on the same topic.

    And aside from that, we’ve also donated money. Because we can’t underestimate the importance of funding projects and developers. There are a lot of examples of maintainers spending way too much of their time on their open source work. Donating money really helps them in the most practical of ways. That can be a one-time donation, but a recurring donation is really useful as well.

    For PHP, another really important contribution is donating to The PHP Foundation. This non-profit organization secures the future of the language in many ways by funding development and projects.

    Why?

    I started this article already with some reasons to support open source. As individual developer, you become part of a community once you start using a project. It is good open source citizenship to support the ecosystem that you are a part of. As a company, I feel you have an actual responsibility that goes beyond simple “good open source citizenship” because the benefit to your company is not just making your life easier, it’s also an economic, clearly monetary benefit to you.

    There are more benefits though: People that contribute to open source projects learn about the things they work on. You do work on a project in a different context from what you usually work on, work with different people, perhaps even with a different process. There’s a lot of lessons we can learn by looking outside of our usual context.

    As a company, it can also be marketing or a recruitment tool: Your contributions to open source projects can be noticed by potential customers or potential developers. Your contributions will automatically make you an expert. Or make you a really interesting employer. Several people that have worked for Ingewikkeld have explicitly mentioned that part of their choice for our company was because we allow people to contribute to open source during work hours. Better yet, one of the people that worked for Ingewikkeld was introduced to me by Sebastian Bergmann of PHPUnit and thePHP.cc. He introduced us at SymfonyCon, and not long after, he worked for us.

    The benefit of open source

    As you can see, the benefit of open source is much more than just free code you can use. As such, it’s important to make sure that that ecosystem can keep existing. As an individual developer, but more importantly, as a company.

  • PHPStorm 2026.1 dark overlay fix

    April 1, 2026
    jetbrains, phpstorm, wayland, wsl2

    Yesterday my PHPStorm updated to the latest version 2026.1, and since then I had issues with it. It seemed to have a dark overlay or a shadow of a window over part of or the whole window (depending on whether the screen was maximized or not).

    I could still work in PHPStorm, but it was really annoying and made my code very unreadable.

    After posting on Mastodon and then searching around the Internet for a bit, I found out that this release is the first that turns on Wayland support by default. And this seems to be what is causing this problem. Luckily, Jetbrains already had a support issue with the information I needed!

    Basically, when you have PHPStorm open, in the Help menu you click the option to Edit Custom VM Options. That opens a file in the editor. There, you simply add


    -Dawt.toolkit.name=XToolkit

    Save, restart PHPStorm, and the issue is gone.

    Yes, this does mean you’re not on Wayland anymore. But hey, if that makes sure I can do my work, I’m happy.

    Technical information: I run PHPStorm from WSL2 from an Ubuntu image. PHPStorm is not running on my Windows host, but inside the WSL2. This might have something to do with it. I have reports that this issue does not seem to happen on Linux Mint.

  • Dutch PHP Conference 2026

    March 24, 2026
    conferences, DPC, Dutch PHP Conference, php

    It took me a while to really sit down and reflect on it, but March 13 was the day of Dutch PHP Conference aka WebDevCon aka AppDevCon. What I love about this threesome of conferences is that it isn’t limited to just PHP, while you can still enjoy a whole lot of PHP content. Funny enough though, my planning this year did not even include that much PHP. Yet I still had a blast and learned a lot. If you can ever make it to Amsterdam, take that chance. You won’t regret it.

    The day started with PHP, and mostly the power of PHP today and tomorrow. Johan Janssens of Joomla! fame told us about the olden days of PHP including some key moments and key people. But then he switched to the now, and to the bright future of PHP. He went into FrankenPHP and what it means to PHP and what it could mean to PHP. About the possibility of distributing executables of PHP applications that can run without dependencies, without even having PHP installed. I know most of what Johan was saying, but it really boosted my morale. It confronted me with YES, PHP is awesome and it has a very bright future ahead.

    Next up was my second and also last PHP-related talk of the day. How could I not go to a talk about another part of the future of PHP: PIE. This talk had a bit of a similar structure to the talk Johan just did. We got a bit of history (PEAR, PECL etc) but then moved on to the now and the future. PIE is a new installer for PHP extensions (say: PECL on steroids). James gave a clear overview of what it already can do and where it’s heading. This was very inspiring (to me) and really triggered me to try and make some time in the coming months to replace my PECL usage with PIE in several projects. This talk really made me feel YES, PHP is awesome and it has a very bright future ahead. Again.

    Crime is bad. Let’s do crime. In How to Git away with murder, Sergès Goma presented her usual combination of serious learning with a great sense of humor. There is no way you’re ever going to fall asleep when Sergès is speaking. During this talk, we learned about some of the crimes of Git and version control, and ways to either avoid those, or get away with it. Good stuff to know for any developer.

    After lunch, it was my time to hit the stage. I presented my sociocratic decision making talk in which I first present sociocracy in general and then zoom in on the sociocratic decision making method. I could elaborate but I’m planning to talk some time to write a full post on this subject at a later moment.

    They always say silence is golden, right? Nope, wrong! Helvira Goma presented a very engaging talk on the power of music to support your work. I really wanted to see this talk because I have long ago realised how important music is for my ability to focus and perform certain tasks, but I had no idea about the science behind that. Helvira gave me exactly what I was hoping for: Explanations on why music helps (or well, can help, not everyone is the same) and even how different styles of music are a better fit for different types of tasks. I can now be more concious about this in the future.

    The last talk of the day was Derick Rethans. A DPC regular and someone I really respect talking about a subject I also care deeply about: owning your content. Any content you post in one of the several big tech platforms, whether that is Xitter, Facebook, or any of the other big platforms is basically not yours anymore. It’s extremely hard to control that content: who reads it, where it goes, how it’s used. Derick introduced the ActivityPub protocol and the many applications that the Fediverse already offers as an alternative to big tech applications. As someone who made the move away from big tech (nope, not completely done yet) I really enjoyed Derick’s talk. On my personal blog, I also wrote about this topic. I really hope that Derick’s talk will inspire more people to join the fediverse and consider using more open platforms and protocols.

    Concluding

    Dutch PHP Conference was awesome as ever. It was very interesting to hear so much critique on usage of (generative) AI at a conference that started a sister conference on AI this year from both speakers and attendees. Having said that, most conversations on that topic were constructive and not simply bashing because of the bashing.

    In terms of line-up, there were several timeslots where it was really hard to choose between different speakers. I really had FOMO several times during the day. That is a sign of an excellent conference with an excellent line-up.

    Of course, I also spent some time in the hallway track, aka talking to people and visiting sponsor booths. There were some interesting sponsors this year to talk to. I really enjoyed my conversation with Rentman for instance.

    I do have to conclude that from a social perspective, a single-day conference is really too short. There are so many people that I would’ve loved to catch up with that I only saw in passing or just could say “hi” to between talks and other conversations. This partially had to do with me as well, since I had very little time around the conference to hang out with people. Ah well. I’m sure I’ll see some people again soon(-ish). It was a wonderful day. I will certainly be there again next year.

  • Deploying Mattermost to Nexaa

    February 20, 2026
    hosting, kubernetes, mattermost, nexaa, slack

    This post is long overdue. We made the switch from Slack to Mattermost early last year, in our effort to have more control over the systems that we rely on, and also to try and remove the dependency on the US given the current (geo)political climate there.

    I’d been wanting to try out Nexaa for a while now. Some of my friends work there, and their serverless containers solution seemed quite easy. I had not realized how incredibly easy it would be, but I’d find out soon enough. In this post I want to document what I did, lessons I learned and give you some tips if you’d want to host your own Mattermost on Nexaa.

    The plan

    Our initial plan was to do a full user-and-data migration from our Slack. We’d read that this could be done and since our history felt important (even if we only rarely searched through our history) we wanted to try and do a full migration.

    Did I reach all the goals set in this plan? Nope. Let’s dissect what happened.

    First of all: we need a database

    Before we can even set up Mattermost we need a database. Mattermost supports both Postgres and MySQL, but since I plan on deploying more apps on Nexaa and most of those are MySQL, I set up a managed database in the Nexaa portal. It’s literally completing a form, and the database server is set up for you. I decided on a 1 node setup. Well, that was easy.

    Setting up Mattermost

    This is probably the second easiest step of this whole setup (after the database). Nexaa makes it super easy to deploy containers, so all you need to do is configure the registry or, in this case, use a publicly available image. Since we’re going to deploy Mattermost, it’s as simple as using the Mattermost image. Right now we’re on mattermost/mattermost-team-edition:release-10.12. We still need to upgrade to Mattermost 11, it’s on our TODO. But when we started, we were on an even lower version. Upgrading is as simple as editting the container and changing the tag (unless there are other, manual, steps to be done as part of the upgrade).

    The rest of the form for creating a new container is relatively straightforward, although some things require some research. I found the minimum requirements for the system Mattermost ran on and decided to run our server on a 1CPU 2GB RAM container.

    It took me a bit to figure out which environment variables I should set. The most important one is the MM_SQLSETTINGS_DATASOURCE. That contains the DSN for your database. The DOMAIN is also important, it’s the URL that your Mattermost instance will be available on. Other settings I configured: MM_LOGSETTINGS_CONSOLEJSON, MM_SQLSETTINGS_DRIVERNAME (which is mysql in our case) and MM_LOGSETTINGS_CONSOLELEVEL. Although the latter was mostly useful to set during initial debugging (set to debug) so you can figure out what goes wrong if anything goes wrong.

    Nexaa: setting ports and Internet access

    By default, your container is not publicly reachable, so you need to configure that it is. You also add a port mapping: In this case public port 80 maps to port 8065 of the Mattermost container.

    Under step 8, you can also configure the ingress to use TLS. It will do the SSL termination for you, so your containers only need to listen to port 80. You also configure the URL on which your container is available.

    Next thing is volumes. Some things need to be kept even if the container restarts. In the above screenshot you can see how we configured this. As you can see, we configured waaaaay too big volumes. Smaller volumes are also possible. Better yet: You can better start out small and then make them bigger if needed. Why? Because you can not shrink volumes, but you can always make them bigger. The above usage is after a year of using Mattermost with about 10 users. That might give you an idea of what kind of volume size you may need.

    The last step is to configure the scaling. Nexaa has autoscaling and manual scaling. Since our Mattermost is only used by a few people, manual scaling will do the trick, and a single replica is fine for us.

    Once I saved this, the container was set up and booted. And indeed, things worked. Well… I of course needed to configure some things.

    Configuring Mattermost

    On the system console of Mattermost, I can now start configuring things. Most of the settings are fine by default, but some things you might want to change.

    You can click all the options to customize stuff as needed, but some things should be configured:

    • Environment -> SMTP: You need to configure this to allow Mattermost to send email. We use our Mailgun for this
    • Site configuration -> Customization: I guess this is not required, but fun: Give your server a name, a description, a custom logo and configure some other things.
    • Authentication -> Signup: Unless you want your server to be open to everyone, make sure that Enable open server is set to False.
    • Integrations -> GIF: Very important: Make sure the Gif picker is enabled
    • User management -> Teams: Make sure to create your first team!

    Teams

    Now this perhaps warrants an explanation. Within a Mattermost server, you can have multiple teams. Consider a team similar to a workspace in Slack: Every team has its own set of channels and it’s own environment. Teams in Mattermost can be public (anyone on the server can join the team) or private (if you have an account on the server you still need an invite to be part of the team). In our case, we only needed a single team: Ingewikkeld.

    Importing from Slack

    Now this is where things failed. Slack allows you to easily export all your data (if you have a paid plan). Mattermost has great documentation on how to migrate. So we downloaded all the users, the channels and the messages and used the mmetl tool to convert it to the Mattermost format. You do that on your local machine.

    For me, that was when the trouble started. We’ve used Slack for over 10 years within Ingewikkeld, so the archive was huge. And it seems the Nexaa ingress has a maximum request size/upload size that you can not configure. The result for us was that we would get errors when trying to import into Mattermost.

    I spend way too long on trying to solve this and eventually gave up. The import had succeeded for users and channels, and that was the most important part for me. The message archive… we’ve backed it up somewhere so we can always search in it, but have not imported it into our Mattermost. A fresh start is nice as well, right?

    Using Mattermost

    Now you can use Mattermost on the web (through the configured URL, assuming you did change the DNS) or using the Mattermost app on your computer or smartphone. And so far, it works really well for us. The only downtime so far was when I updated the configuration and made a mistake, but that was easily fixed.

    Fun fact

    Fun fact: I did most of the setup of our Mattermost on the train from SymfonyCon Vienna to Klosters, Switzerland (where I would be visiting my sister and her family). If I can do this on an international train in the alps, you can do it in your (home) office as well 😉

  • Firefox NS_ERROR_CORRUPTED_CONTENT confusion

    November 19, 2025
    403, 404, firefox, NS_ERROR_CORRUPTED_CONTENT

    OK, so this is a short and quick post just to clear some confusion. I spent hours and hours trying to figure out what the hell was going on when I was running into this NS_ERROR_CORRUPTED_CONTENT for javascript files

    For the life of me I couldn’t figure out what the cause was for this error. It turns out that, at least in some situations, the error is actually more confusing than it should be. When I opened the URL in my browser, it turns out that this was simply a 404 or 403 (I have two different situations where I encountered this). There is nothing corrupted about the response even though the error seems to imply that. Don’t get fooled by the weird error string, just inspect the response and check the status code and you’ll probably quickly figure out what the actual solution will be.

  • My first Azure Pipeline

    September 12, 2025
    azure, ci, php, pipeline

    Last week I started at a new customer and they’re fully committed to the Azure DevOps environment. They use their Git repositories, their project boards and also their pipelines. Since the project I’m working is currently their only PHP project, they did not yet have any experience with setting up pipelines for a PHP project. So I set out to do just that, and found it surprisingly easy.

    Just like many other Git hosting sites, you can configure the pipelines using a YAML file, in this case azure-pipelines.yml, in the root of your project. They do also offer an online editor, but I haven’t actually tried that, preferring the YAML format for configuring pipelines.

    If you have experience with Bitbucket pipelines or Gitlab pipelines, then configuring Azure pipelines will be a breeze. Most things make a lot of sense. There’s a few things that I did need to take into account while setting up, and in this article I want to share these things.

    Tasks

    The first thing I found out: The predefined tasks beat having to create your custom scripts any day. Azure Pipelines have a huge list of predefined tasks that can make your life with pipelines a lot easier. For instance, this project uses private composer packages that are located inside Git repositories. So I have to insert an SSH key into the runner to make sure that when running composer install it can fetch those packages. A pretty common situation. Before I knew about the tasks I tried to manually do this myself. But I have very little knowledge of the insides of the runner, so it’s pretty hard to figure out exactly how to do that. Luckily, there is a task for that. This will save you a lot of time.

    Secure files

    Speaking about SSH keys (or other things that need to be injected that need to be securely stored) the Secure files feature is the answer. It’s really easy to insert those secure files into your runner context, and tasks such as the earlier mentioned InstallSSHKey@0 task allows you to simply reference the secure file to use. Again, this will save you a lot of time and frustration.

    Similar to secure files, there’s also variables that you can configure, that are stored securely and can then be used in the azure-pipelines.yml file.

    Conditions

    By default the whole pipeline is triggered on each push of each branch. You can limit when things are run by using the triggers. But there is another way of limited when things are run: by using conditions. Triggers are configured on the top level and so apply to your whole pipeline configuration. But sometimes you want certain stages, jobs or steps to run only in specific situations. For instance, you only want to build and push the image when all previous steps have succeeded and only for your main branch.

    This is where conditions come in. Let’s take the above example of wanting to run a stage only when all previous stages have succeeded and only when the branch is main. You can add a relatively simple condition to do that:

    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

    By adding the above to a stage, job or step, that item will in this case only be run when previous items have succeeded (succeeded()), and when the branch this runs on (Build.SourceBranch) is main (refs/heads/main).

    And you can start doing pretty fancy stuff with this. There’s a lot of logic you can add, based on variables, attributes of the current build, success or failure of previous steps, etc.

    This is pretty cool

    My experience with Microsoft stuff has always been a bit hit or miss, but so far I must say I’m actually quite impressed by the Azure Pipelines and the ease and speed with which it works. And not just that: Their git repository hosting in general works pretty well (except that pipelines work on branches and are not directly linked to pull requests, which is unfortunate). Their Jira replacement also seems to work pretty well. So yes, I quite like how this works.

  • Explicit code

    August 8, 2025
    code, explicit code, inclusive code, php

    One of the most discussed subjects during code reviews or in projects is not a functional thing but more a style thing: How does the code look? What coding style do we adopt?

    And while it feels like mostly a cosmetic thing, the code style is actually quite important. It determines not just how you write code, but also how you can read it. And since you usually read the code a lot more often than you write it, this is quite important.

    The race for shorter code

    More and more I see that developers opt for the shortest bit of code they can possibly write. And PHP as a language is also changing to make things a lot shorter. Think of the Null Coalescing Assignment Operator or the Pipe Operator, for instance.

    Now in essence of course, the longing for shorter code can be understood. A lazy developer is a good developer. And if anything, wanting to type less characters is a great property of a lazy developer.

    Write once, read often

    Up to a certain point I can follow the idea of a lazy developer. Hell, I’m a lazy developer. However, as I mentioned before, you read the code a lot more than you write it. And if you think about that, it’s much more important to optimize your code for reading than it is for writing.

    Combine that with the fact that our modern tooling with IDE’s that help us write the code makes it very easy to write code. With templates, macro’s and auto-complete, we don’t actually have to type all our characters anymore. Our laziness is supported by our tooling. So is it really needed to shorten our code that much anymore?

    Optimize for reading

    I don’t know about you, but I spend a lot of time reading code. Whether that is brand new code or older legacy code, if I need to modernize a codebase or simply implement a new feature into some existing code, I need to write what is there, determine what it does, then make whatever change I was going to make. And usually this involves stepping into called methods to see what these do, sometimes several levels deep. The most important thing for me, therefore, is to be able to quickly read what code does. How it behaves, how it alters values, what it returns.

    Let’s borrow an example from the pipe operator RFC:

    function getUsers(): array {
        return [
            new User('root', isAdmin: true),
            new User('john.doe', isAdmin: false),
        ];
    }
     
    function isAdmin(User $user): bool {
        return $user->isAdmin;
    }

    So far so good, right? Two methods. Now to figure out how many users are admins, I’d write a pretty simple bit of code:

    $numberOfAdmins = 0;
    
    foreach (getUsers() as $user) {
        if (isAdmin($user) === true) {
            $numberOfAdmins++;
        }
    }

    The new pipe operator would turn this into the following piece of code:

    $numberOfAdmins = getUsers()
        |> fn ($list) => array_filter($list, isAdmin(...)) 
        |> count(...);

    Granted, this is indeed shorter. But does this really make it more readable? I understand that this is subjective, but if you just take a quick glance, which gives you more information in less time, the top or the bottom code snippet?

    Let’s borrow another example from an RFC, this time the earlier references Null Coalescing Assignment Operator. This change to the PHP language is a shortening of an earlier syntax shortening. Old man speaking: Back in the old days, we’d write this bit of code as follows:

    if ($this->request->data['comments']['user_id'] !== null) {
        $this->request->data['comments']['user_id'] = 'value';
    }

    Earlier on, this was shortened to:

    $this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ?? 'value';

    and now, it’s become:

    $this->request->data['comments']['user_id'] ??= 'value';

    I would like to repeat my questions from the last set of code snippets: But does this really make it more readable? I understand that this is subjective, but if you just take a quick glance, which gives you more information in less time, the top or the bottom code snippet?

    And it doesn’t stop at that. I still encounter the exclamation mark a lot. For instance:

    if (!$variable) {
        // do something
    }

    That exclamation mark is easily overlooked when quickly scanning over code. And how much more typing does it take to make this:

    if ($variable === false) {
        // do something
    }

    Inclusive coding

    Even if you don’t have an issue with reading these shorter versions, it might be good to adopt a more explicit style of coding. Because most probably, you won’t be the only person reading the code. And the shorter the code and more complex the syntax, the heavier the mental load is on developers to read the code. Not just you (or you in six months after focussing on a lot of other stuff), but also other developers (including potentially those under high stress, with mental health issues, junior developers who just don’t have that much experience yet, etc). By keeping the code explicit and basic, you help those developers understand what is happening. Doing so will make your code more inclusive.

    Make your code more explicit

    I would love to see more people adopting more explicit coding styles. Keep in mind that someone, possibly you, might be reading this code in a few months or years time, trying to figure out what’s going on. Do you really want them to have to take a long time to understand what is happening?

  • The lost art of training?

    July 4, 2025
    learning, lessons, php, training

    Disclaimer: I deliver courses and organize training sessions myself as part of Ingewikkeld Trainingen. As such, I have written this with a certain bias.

    With the risk of sounding old: When I was young, if you wanted to learn something, you basically had two options: Read a book and start self-teaching, or book a training session and learn through that.

    Since then, a lot has changed. And that’s a good thing. Video tutorials, podcasts, blogs, magazines, monthly usergroups, conferences, even LLMs… there are so many ways to learn these days. It’s fantastic! Because not everyone learns well from reading a book or just trying something. Not everyone learns well from attending a training session.

    What I’ve noticed is that all these new ways of learning have caused the original way of learning to almost be lost. Having a teacher come in to teach a course or booking a seat on a classroom training. It’s something that rarely happens anymore. And I can sort of see why: Booking a course means committing one, two or even three(+) days to that course. It costs a set amount of money (either per student or per course). It’s cheaper to recommend some podcasts, get a subscription to Udemy or give someone a ChatGPT subscription. That also takes less time. I get that.

    Advantages of the course

    Actually attending a physical course with a trainer teaching you things does have certain advantages that all the other forms of learning don’t have. Let’s have a look at four of those advantages.

    1. Focus

    A lot of things are happening in your work, your life and the world. There are a lot of things that are constantly asking for our attention. Whether that is your manager, your social media notifications, your team or the latest BREAKING NEWS, keeping focus on learning is hard. And that while focussing on the topic at hand is instrumental in actually learning something. As Cal Newport wrote:

    To remain valuable in our economy, therefore, you must master the art of quickly learning complicated things. This task requires deep work. If you don’t cultivate this ability, you’re likely to fall behind as technology advances.

    A physical teacher can not just be paused every time something asks for your attention. They can also see you and call you out on any distractions they might notice, adding motivation for paying attention and focussing on the material you are learning.

    2. Interactivity

    Most of the “modern” training options have no interactivity. There is material, and you can consume that material. You can not ask questions, or discuss certain topics. You get what you get. This can be nice because it’s predictable, but once you don’t understand something or would like to dive deeper into something, you’ll have to figure that out by yourself.

    Having someone that delivers the content also allows you to ask questions, get clarification or even steer the content that you’re given into a certain direction (within the limits of the course).

    This can be invaluable in understanding the topic and not getting stuck somewhere without knowing how to move forward.

    3. Customization

    In line with the previous point, customization is also great. With “standard” content such as a podcast, video tutorial or book, you get what you get. But when you book a training course for your team, the trainer will be able to prepare custom content for your team. If you book a PHPUnit Masterclass and your team has a pre-existing codebase, you can ask the trainer to use that for the exercises on testing untestable code instead of the default exercises. If you book a training on Docker and Kubernetes and your company uses a specific cloud provider, you can ask the course the be customized for that specific platform. This is priceless: Your team is getting exactly the content they need.

    4. The hallway track

    Do not underestimate the informal contact different students have during breaks when attending a training course. While the formal content of the course is of course very important, the social aspect of sharing experiences, lessons learned and also non-course-related topics is also very important. Your team can reflect, learn from each other and also get to know each other better. If you booked seats on an external classroom training, they can also do this with people with completely different background and experiences, which could make the learning experience even more extensive.

    Book a course?

    Nope. I’m not going to tell you that you should now immediately book a course. First of all, in previous years it seems that, especially in the programming world, courses have become rarer. They’re not offered as much anymore unfortunately. But what I do want to ask you is to seriously consider booking a course in case it is available for the topic that you or your team wants or needs to learn more on.

  • Migrating to e/OS

    May 30, 2025
    android, apple, e/OS, fairphone, gadget bridge, ios, pinetime, pocket casts, technology

    For as long as I can remember, I’ve been an Apple Fanboi. Well, no, not that long, but ever since I started working at Ibuildings in the 00’s and getting my first Mac, I was sold. Unfortunately at some point for a power user like me the laptops started becoming less interesting (and also way too expensive), but for my phone I stuck with Apple because iOS was far superior to Android in terms of UX and consistency.

    In recent times, however, I’ve been becoming more privacy aware. Aside from that, with the current geopolitical situation and the “mightiest country in the world” being led by an unstable and unpredictable leader, I want to prevent my dependency (US-based) big tech.

    Some months ago I got introduced to the de-Googled GrapheneOS and e/OS. I got to try out e/OS on a secondary phone for a while and had to admit: Android has improved a lot since the last time I played with it. It compares quite well with iOS these days in terms of usability. So that’s when I started considering the move.

    It’s not an easy move though. Migrating from one platform to the other requires some planning and serious thought. When you’ve invested so many years into a platform, switching to another platform means figuring out how to replace certain platform-specific features. To my surprise, however, this turned out to not be that hard. Over the time I’ve switched mostly to apps that support both iOS and Android, and files I’ve been storing in for instance Proton Drive, not iCloud, so… hey, switching might not be as hard as I thought.

    Fairphone

    The first thing then is to think of which hardware to get. I was using an iPhone 12 mini, which is a very small phone, and quite quickly I came to the conclusion that it wouldn’t be that easy to get a similar device. Especially since I needed to keep in mind the device had to be compatible with e/OS. I preferred a phone that would also have official support instead of community support so that I could use the official installer. A sustainable and European company would also be nice. I’d heard a lot of good things about Fairphone and given their focus is on sustainability and right to repair, and they’re Amsterdam-based… that seemed like a fine choice.

    Installing e/OS

    My previous experience with installing e/OS on an old Samsung device was horrible. Hence my mention of wanting to use an officially supported device. The Fairphone I ordered came with a standard Android instead of e/OS, but hey, I’ve gone through the ordeal of installing it on that Samsung device, I can do this.

    So, connect Phone to laptop, go through setup steps so that I can start using the official installer, go through the first couple of steps… so far so good. One step was confusing: the e/OS documentation mentions having to unlock the bootloader, but as I did that it asked for a code, which the documentation did not mention anywhere. Turns out this is a Fairphone-specific thing. Fairphone offers a tool to calculate that code based on your IMEI and serial number.

    The phone is recognized and I can connect to it. But at the second point where I need to connect with the laptop… nope. It didn’t connect. Searching around a bit, this turned out to be related to the phone being locked. I found this blogpost and by just going through the first couple of steps (up to and including the fastboot flashing unlock_critical step), I got it to work. Now the second connect step of the installer did work.

    One thing to note in the official installer: Your progress is usually at the bottom of the screen, but any errors are shown in tiny letters at the top of the screen. So while you might be waiting for things to finish, there might already be errors. Keep your eyes on the top of the screen as well!

    After this, the installer was able to finish all the way to the end, and I had a Fairphone with e/OS. Yay!

    Another thing I noticed, however, is that I do not find anything in the documentation about, after finalizing the install, putting to lock back on using the fastboot flashing lock_critical and fastboot flashing lock commands. I did that regardless.

    App lounge

    After booting into e/OS I had another issue. The App lounge, the app with which you install other apps, would not load in anonymous mode. It would just keep on loading without being able to do anything. Unfortunately clearing the cache and storage, as recommended by the official documentation, did not solve it either. The official documentation suggested that if it couldn’t be solved, to still use a Google account. Which kind of defeats the purpose of using a de-Googled Android, imho. On the Internet I found some people who suggested just to wait a bit, however, and a friend made the same recommendation. So I wanted and lo and behold: It started working. I’m still not sure why it didn’t work before, but who am I to complain.

    Migrating

    Next step: migration. I had to install a whole bunch of apps of course. The first one was my password manager, because after installing all those apps, I would have to log in to most of them. This was a boring but very straightforward task. A big shout-out to Pocket Casts that after I logged in even remembered exactly where I was in the podcast I was listening to. Talk about a seamless migration experience!

    Contacts

    One thing I was quite scared of was how to ensure my contacts were migrated. Turns out that fear was based on nothing. The e/OS documentation offers a very simple tutorial: Download a vcf-file from iCloud, transfer that to the new phone, then import that file into your Contacts app. Everything was transferred!

    The watch

    My trusty iPhone had a trust companion: The Apple Watch. In my evaluation of my Apple usage, I’d come to the conclusion that while the Apple Watch can do a whole lot of things, all I really used it for on a daily basis was keeping track of my exercise and getting notifications of important things happening on my phone. I don’t really need such a complex watch for that. After looking around I found the PineTime watch: I very simple “sort of smart” watch. After posting on Mastodon about this I got a response from someone one village away who had one lying around that I could test-drive. I’ve been wearing it for three days now and I haven’t even had to charge it yet! And yes, this is not as fancy as an Apple Watch, but it tracks my steps (not all my exercise, sure, but my steps) and after setting up the Gadgetbridge app on my Fairphone I do get notifications. So hey, this works just fine!

    Airpods

    The only thing now that I still have from the Apple ecosystem is a set of airpods. I hardly use those, though, since I also own a pair of Bose QC-35 headphones. And the airpods connect just fine with the Fairphone, so I have no real need to replace those. And even if I wanted to replace them, Fairphone has a solution for that as well.

    Concluding

    I had expected that escaping the Apple ecosystem would be hard. But, some minor setbacks aside, it was pretty much smooth sailing. Whether I will bump into other things, only time will tell of course, but so far my experience with the Fairphone, with e/OS and with the Pine Time has been great!

  • Dutch PHP Conference 2025

    March 18, 2025
    amsterdam, conferences, DPC, php

    With only a few more days to go until Dutch PHP Conference 2025 it’s time to look forward to the conference. DPC is always a good conference (and has always been so), but I’m going to put focus on some talks that I’m really looking forward to.

    Sacred Syntax: Dev Tribes, Programming Languages, and Cultural Code

    One of the best and most entertaining talks at DPC last year was by Serges Goma and was titled Evil Tech: How Devs Became Villains. In it, Serges put focus on ethics in software development in a very fun and accessible way.

    With the great way that topic was approached I’m really looking forward to Serges’ take on tribalism, which is the subject of the talk this year!

    Small Is Beautiful: Microstacks Or Megadependencies

    Bert Hubert has been big in media in recent times talking about the EU dependency on US-based cloud providers, talking about the risks and even the potentially unlawfulness of doing that. However, Bert is also someone with a big history in tech, being the founder of PowerDNS.

    In his closing keynote, he will talk about microstacks and megadependencies. I’m really curious to hear about this from Bert.

    Don’t Use AI! (For Everything)

    After my recent blogpost on AI I got a response from Ivo Jansch, one of the organizers of DPC but also a really smart person that I’ve enjoyed working with in the past, to attend this talk by Willem Hoogervorst. I am really looking forward to the considerations that Willem will be sharing on when to use AI and when not to.

    Parallel Futures: Unlocking Multithreading In PHP

    Multithreading and PHP is not a good combination? Apparently it is! Florian Engelhardt will be talking about ext-parallel and I do want to hear more. I’m intrigued!

    Our tests instability Prevent Us From Delivering

    I’ve seen this situation with several of my customers: tests that can not be trusted. Either tests turned out green when something was wrong, or tests would be red while everything was fine. I’m looking forward to hearing from Sofia Lescano Carroll on what can lead to this and how to mitigate this.

1 2 3 … 61
Next Page

skoop.dev

  • Bandcamp
  • Mastodon
  • Bandcamp