<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hannes Van De Vreken</title>
    <description>Working as a web developer. On his blog he writes about things he learned while experimenting with tools he might use to speed up his development.
</description>
    <link>https://hannesvdvreken.com/</link>
    <atom:link href="https://hannesvdvreken.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Sat, 24 Dec 2022 11:38:15 +0000</pubDate>
    <lastBuildDate>Sat, 24 Dec 2022 11:38:15 +0000</lastBuildDate>
    <generator>Jekyll v3.9.2</generator>
    
      <item>
        <title>Switching companies</title>
        <description>&lt;p&gt;After precisely 3 years (since 8 September 2014) at &lt;a href=&quot;https://madewithlove.be&quot;&gt;madewithlove&lt;/a&gt;, I’ve decided it was time to move on.
A little while ago, I agreed to join the team at &lt;a href=&quot;https://getstream.io&quot;&gt;Stream&lt;/a&gt; as a PHP Software Engineer and Developer Advocate.
Next Monday I will join them in their office in &lt;a href=&quot;https://tq.co/&quot;&gt;TQ&lt;/a&gt; in Amsterdam.&lt;/p&gt;

&lt;p&gt;My task will be to represent them, and the product, in the PHP community.
Many people know Algolia, Sendgrid, Twilio, etc. and soon Stream will be as well known as those names.
I’ll be creating demo applications, tutorials and workshops in PHP.
Also I’ll be a point of contact (account manager if you will) for customers doing integrations with our product in PHP applications.
Next to that I will keep doing my best to create PHP related talks, that help other people learn new things.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://dvqg2dogggmn6.cloudfront.net/images/getstream_io_og.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’m really looking forward to this new chapter and I’d like to thank my colleagues at madewithlove for the epic ride! Keep rocking.&lt;/p&gt;
</description>
        <pubDate>Thu, 14 Sep 2017 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2017/09/14/switching-companies/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2017/09/14/switching-companies/</guid>
        
        <category>career</category>
        
        <category>job</category>
        
        
      </item>
    
      <item>
        <title>On PSR-7 middlewares</title>
        <description>&lt;p&gt;PSR-7 got released May 4, 2015. There is a discussion about middlewares based on PSR-7 messages, and it is awfully overdue. The most common middlewares in use since June 2015 are callables with this interface:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/hannesvdvreken/6767f0b423a28b24e7c588c22f552b78.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;They just work. I’ve been using them since June 2015. You can stack a number of middlewares with tools like &lt;a href=&quot;https://packagist.org/packages/relay/relay&quot;&gt;relay/relay&lt;/a&gt; or &lt;a href=&quot;https://packagist.org/packages/mindplay/middleman&quot;&gt;mindplay/middleman&lt;/a&gt;. I prefer the latter because it plays well with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;container-interop&lt;/code&gt; containers to resolve middlewares when you need them.&lt;/p&gt;

&lt;p&gt;Granted, you can use them wrong by fiddling with the Response before passing it on to the next middleware. Just don’t do that. But I’d rather educate newbies than to remodel the whole thing and to make it overly complex. I’ve been giving &lt;a href=&quot;https://www.youtube.com/watch?v=gOVALgpqHzM&quot;&gt;this PSR-7 talk&lt;/a&gt; for 12! months now. Please just spread the word and stop discussing something that has been in use for over a year now.&lt;/p&gt;

&lt;p&gt;Thanks.&lt;/p&gt;

&lt;p&gt;PSR-7 middlewares discussion links:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.ircmaxell.com/2016/05/all-about-middleware.html&quot;&gt;Anthony Ferrara’s post&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://shadowhand.me/all-about-psr-7-middleware/&quot;&gt;Woody Gilk’s post&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://philsturgeon.uk/2016/05/31/why-care-about-php-middleware/&quot;&gt;Phil Sturgeon’s post&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://andrewcarteruk.github.io/programming/2016/05/22/psr-7-is-not-immutable.html&quot;&gt;Andrew Carter educating that the StreamInterface isn’t immutable&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://groups.google.com/forum/#!msg/php-fig/vTtGxdIuBX8/NXKieN9vDQAJ&quot;&gt;PHP-FIG discussion on google groups&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://groups.google.com/forum/#!msg/thephpleague/jyztj-Nz_rw/I4lHVFigAAAJ&quot;&gt;PHP league discussion on google groups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some links might be missing here. Feel free to send a PR.&lt;/p&gt;
</description>
        <pubDate>Wed, 01 Jun 2016 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2016/06/01/psr-7-middlewares/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2016/06/01/psr-7-middlewares/</guid>
        
        <category>psr-7</category>
        
        <category>php</category>
        
        <category>http</category>
        
        
      </item>
    
      <item>
        <title>Airbnb tricks</title>
        <description>&lt;p&gt;Hi there! It’s been a while since my last blog post. Sorry for that. Let’s break the silence with a post on travelling with Airbnb.&lt;/p&gt;

&lt;p&gt;I like visiting cities, both for work (conferences) and pleasure. Hotels are often quite expensive in cities, and the value you get from them is often disappointing. Over the past few years I’ve been using Airbnb a lot, so that I can stay in a calming environment, away from the hustle from the city and hotel personnel.&lt;/p&gt;

&lt;p&gt;An Airbnb can be anything. It can be a castle or a villa for 16 people. Or as small as a private room with a bed from wall to wall in a 3 bedroom student apartment. I’ve been there, I’ve done that.&lt;/p&gt;

&lt;h1 id=&quot;building-trust&quot;&gt;Building trust&lt;/h1&gt;

&lt;p&gt;All places on Airbnb are made available by their owners. Every time a stranger contacts an owner (host) to rent a place, the owner can decide whether they trust a stranger to use their property or not. Owners rent their places for a price per night, a handling fee for Airbnb, and optionally a cleaning fee.&lt;/p&gt;

&lt;p&gt;After staying at a place, both hosts and guests get to post a review about each other. If both the host and you (as a guest) send in a review, the host’s review of you will become visible on your profile and vice versa. Future hosts read these reviews as part of their decision process to host you or not. It is thus very important to be kind, stick to the house rules of the owner, and leave the place as clean as you found it. Don’t leave trails of dirt, trash or dirty dishes. It’s obvious that if you’re paying a cleaning fee, you don’t have to wipe the floor. General rule: use common sense, show some empathy with the owner. How would you like to find your place after it has been used by strangers?&lt;/p&gt;

&lt;h1 id=&quot;host-yourself&quot;&gt;Host yourself&lt;/h1&gt;

&lt;p&gt;Obviously when you host yourself you will learn about the logistics, communication and emotions that come with letting strangers inside your home or property. This is valuable when dealing with other hosts.&lt;/p&gt;

&lt;p&gt;I haven’t hosted people myself. I live in a fancy, well located, 2 bedroom apartment with my girlfriend. If it were up to me we’d have guests over regularly, but when you are in a relationship you decide these sorts of things together. Sorry to all the Airbnb guests that I have let down ;-)&lt;/p&gt;

&lt;h1 id=&quot;contact-host-beforehand&quot;&gt;Contact host beforehand&lt;/h1&gt;

&lt;p&gt;On Airbnb, on every page to view a place, there is a button that says “contact host”. Use it. I get in touch with hosts before sending a booking request with my credit card details. I do this to send a little introduction about myself, and the reason why I am looking to rent their place. Don’t tell your bad habits or your life story. Just the information they need. For example: I’m a passionate runner since 2014 and I’m planning on making a weekend trip to Valencia to run the Valencia marathon with X friends from day Y till day Z.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-02-24-airbnb-tricks/contact-host.png&quot; alt=&quot;contact host&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The second reason I contact hosts without a booking request is because hosts have the option to send special offers. After one or two messages I usually ask hosts if they want to make me an offer for a cheaper price. Sometimes they do if you’re trustworthy, if you book well in advance, and even better: if the owner can relate to you because you have something in common. You’re essentially bargaining. A common sentence to use is: “I’ve seen this cheaper place nearby (include link). I’m having doubts if I should book that place or yours. If the price would be the same I would book today.” One time I got the price for a seaside villa in Valencia for 6 nights down from 3500 euro to 2000!&lt;/p&gt;

&lt;p&gt;It’s still people you’re dealing with, so if they don’t buy it: stay friendly, be honest and don’t waste their time.&lt;/p&gt;

&lt;p&gt;If you’re looking for a place for 2 weeks or longer you can ask to only book the first week via Airbnb with an option to stay longer. After one week the trust level between host and guest should be high enough to decide on a fixed price for the rest of the stay without going through Airbnb. Be careful though. Airbnb offers refunds, insurance to the owner that the host can pay the amount, and other legal stuff. If you’re going to shortcut Airbnb, all responsibility is on you, both the host and the guest.&lt;/p&gt;

&lt;h1 id=&quot;getting-there&quot;&gt;Getting there&lt;/h1&gt;

&lt;p&gt;A few days in advance I usually text the host to let him/her know when I’ll arrive. This is to make sure the host is still alive and aware you’re coming over. If the owner responds quickly, you know you can reach him/her when you’re in an emergency situation. When you arrive you can pick up the key, get to know the host and start navigating around the city. Make sure your phone has an internet connection and a fully charged battery and you’ll be good.&lt;/p&gt;

&lt;h1 id=&quot;book-your-own-airbnb-place&quot;&gt;Book your own AirBnb place&lt;/h1&gt;

&lt;p&gt;If you want to try AirBnb for one of your upcoming trips, get &lt;a href=&quot;https://www.airbnb.com/c/hdevreken&quot;&gt;30 euro&lt;/a&gt; off of your first booking.&lt;/p&gt;

&lt;p&gt;That’s it. Happy travelling!&lt;/p&gt;

&lt;p&gt;PS: This was a blog post on travelling. It is not my intention to start making this a travel blog. Though, we’ll see where this goes.&lt;/p&gt;
</description>
        <pubDate>Wed, 24 Feb 2016 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2016/02/24/airbnb-tricks/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2016/02/24/airbnb-tricks/</guid>
        
        <category>airbnb</category>
        
        <category>travel</category>
        
        <category>cheap</category>
        
        
      </item>
    
      <item>
        <title>NYC marathon preparation started</title>
        <description>&lt;p&gt;Hi all! Here’s an update on my latest leisure time activities.&lt;/p&gt;

&lt;p&gt;In April this year I ran &lt;a href=&quot;https://hannesvdvreken.com/2015/04/13/running-my-first-marathon/&quot;&gt;my very first marathon&lt;/a&gt;: the Rotterdam marathon.&lt;/p&gt;

&lt;blockquote class=&quot;instagram-media&quot; data-instgrm-captioned=&quot;&quot; data-instgrm-version=&quot;4&quot; style=&quot; background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);&quot;&gt;&lt;div style=&quot;padding:8px;&quot;&gt; &lt;div style=&quot; background:#F8F8F8; line-height:0; margin-top:40px; padding:50% 0; text-align:center; width:100%;&quot;&gt; &lt;div style=&quot; background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;p style=&quot; margin:8px 0 0 0; padding:0 4px;&quot;&gt; &lt;a href=&quot;https://instagram.com/p/1YnRq_OwU1/&quot; style=&quot; color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;&quot; target=&quot;_top&quot;&gt;3:29:21 #mr15. The crowd was amazing! #marathon #rotterdam&lt;/a&gt;&lt;/p&gt; &lt;p style=&quot; color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;&quot;&gt;Een foto die is geplaatst door Hannes Van De Vreken (@hannesvdvreken) op &lt;time style=&quot; font-family:Arial,sans-serif; font-size:14px; line-height:17px;&quot; datetime=&quot;2015-04-12T18:15:53+00:00&quot;&gt;12 Apr 2015 om 11:15 PDT&lt;/time&gt;&lt;/p&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; defer=&quot;&quot; src=&quot;//platform.instagram.com/en_US/embeds.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;It was until that day (12th of April) that I kept telling others and myself that this was a one time thing.
Though, after the race I was so happy with my result, that I just stopped saying whether or not I would do it again.
Some time was needed to reflect on my result, wether I wanted to go faster, wether I could push my body even further,
and whether I could afford the time needed to improve.&lt;/p&gt;

&lt;h3 id=&quot;after-my-first-marathon&quot;&gt;After my first marathon&lt;/h3&gt;

&lt;p&gt;Four days after the Rotterdam marathon I was able to run (painless) again.
The weeks after that I ran a lot: 6 or 7 times a week. No fast running, no workouts, no more than 20 km per day,
no more than 150 beats per minute heart rate. In the mean time I talked to a few people on marathon running,
ultramarathon running (42+ km) and trail running. The more I talked to people, the more I wanted to have a goal again.
So I started to assemble a calendar of all kinds of races that will take place in late 2015.&lt;/p&gt;

&lt;h3 id=&quot;picking-a-race&quot;&gt;Picking a race&lt;/h3&gt;

&lt;p&gt;On May 28th I registered for, not one, but two marathons. I applied with a good cause initiative which had
50 bib numbers for the TCS New York City marathon. I believed my odds were little, so I didn’t wait for this.&lt;/p&gt;

&lt;p&gt;A few people told me the Eindhoven marathon is a great race, has good atmosphere, and it’s just a short drive by car.
It’s a great race to run, so I registered for this one as well.&lt;/p&gt;

&lt;p&gt;On June 23th I received an email I didn’t expect to receive.&lt;/p&gt;

&lt;blockquote class=&quot;instagram-media&quot; data-instgrm-captioned=&quot;&quot; data-instgrm-version=&quot;4&quot; style=&quot; background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);&quot;&gt;&lt;div style=&quot;padding:8px;&quot;&gt; &lt;div style=&quot; background:#F8F8F8; line-height:0; margin-top:40px; padding:50% 0; text-align:center; width:100%;&quot;&gt; &lt;div style=&quot; background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;p style=&quot; margin:8px 0 0 0; padding:0 4px;&quot;&gt; &lt;a href=&quot;https://instagram.com/p/4RJ9_2OwTF/&quot; style=&quot; color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;&quot; target=&quot;_top&quot;&gt;It&amp;#39;s official now: I will run the @nycmarathon on the first of November! 🗽 #tcsnycmarathon&lt;/a&gt;&lt;/p&gt; &lt;p style=&quot; color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;&quot;&gt;Een foto die is geplaatst door Hannes Van De Vreken (@hannesvdvreken) op &lt;time style=&quot; font-family:Arial,sans-serif; font-size:14px; line-height:17px;&quot; datetime=&quot;2015-06-23T10:19:17+00:00&quot;&gt;23 Jun 2015 om 3:19 PDT&lt;/time&gt;&lt;/p&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Yes, that’s right! I got into the TCS New York City marathon! This means I will raise money for a good cause
(more about that later). I already planned every training for the next 16 weeks leading up to the race.
My goal is to run the marathon in less than 3 hours, which is 29 minutes faster than my last one.
This might be too optimistic, but I feel very strong already after the first week of training.
If I don’t make it, I would be happy with anything faster than 3 hours and 10 minutes still.&lt;/p&gt;

&lt;h3 id=&quot;on-the-good-cause&quot;&gt;On the good cause&lt;/h3&gt;

&lt;p&gt;The initiative I will be raising money for is called &lt;a href=&quot;http://www.mediclowns.be/&quot;&gt;Mediclowns&lt;/a&gt;.
Mediclowns is an organisation of about 10 artists who brighten up ill children.
They visit children that stay home months on end, waiting to see if the treatments they receive have a positive effect
on their horrible illnesses. I really admire people that are so strong and positive that can even entertain
even the sickest and weakest. People living in Belgium might recognise the name Cliniclowns.
Mediclowns is similar, with the big difference that they do home visits.&lt;/p&gt;

&lt;p&gt;The money I will raise will all go to Mediclowns, who will pay for my entire 5 day trip to New York.
In Belgium you (as a tax payer) can deduct gifts from your taxes, and as a business the amount is
100% deductible from your revenue. Please, if this sounds appealing to you, or you can connect me to a company to which this might sound appealing, let me know and we’ll talk more on the details. Every single backer will get a personal souvenir, a thank you letter and a mention in a future blog post. It may not be worth much, but it’s a gesture of gratitude ;)&lt;/p&gt;

&lt;p&gt;The fund raising page is on &lt;a href=&quot;https://gofundme.com/tcsnycmarathon&quot;&gt;gofundme.com/tcsnycmarathon&lt;/a&gt;.&lt;/p&gt;

&lt;object classid=&quot;clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&quot; width=&quot;258&quot; height=&quot;338&quot; title=&quot;Click Here to donate!&quot; type=&quot;application/x-shockwave-flash&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;//funds.gofundme.com/Widgetflex.swf&quot; /&gt;&lt;param name=&quot;quality&quot; value=&quot;high&quot; /&gt;&lt;param name=&quot;flashvars&quot; value=&quot;page=tcsnycmarathon&amp;amp;template=7&quot; /&gt;&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot; /&gt;&lt;embed allowscriptaccess=&quot;always&quot; src=&quot;//funds.gofundme.com/Widgetflex.swf&quot; quality=&quot;high&quot; flashvars=&quot;page=tcsnycmarathon&amp;amp;template=7&quot; type=&quot;application/x-shockwave-flash&quot; wmode=&quot;transparent&quot; width=&quot;258&quot; height=&quot;338&quot; /&gt;&amp;lt;/embed&amp;gt;&lt;/object&gt;

&lt;p&gt;Take care!&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Jul 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/07/20/nyc-marathon/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/07/20/nyc-marathon/</guid>
        
        <category>running</category>
        
        
        <category>running</category>
        
      </item>
    
      <item>
        <title>Displaying stream progress in PHP</title>
        <description>&lt;p&gt;With PHP you can, next to handling HTTP requests, invoke scripts from the command line. For a typical web application this could be used to run database migrations, insert data into the database from fixtures or seeders, repetitive tasks run by cron, clear the cache (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cache:clear&lt;/code&gt;), general admin stuff… basically anything that can be automated.&lt;/p&gt;

&lt;p&gt;The Symfony console component is a very useful tool to define and invoke these kind of CLI tasks. You can view the console application as the command line alternative of your index.php front controller and request/response objects for HTTP requests. It handles calling the right commands, parsing and validating arguments and options, displaying usage help, … All you need to do is to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Command&lt;/code&gt; class per task and define its name, description, arguments and options.&lt;/p&gt;

&lt;p&gt;You command’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execute&lt;/code&gt; method will be called using an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InputInterface&lt;/code&gt; object and an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputInterface&lt;/code&gt; object. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$input&lt;/code&gt; object can be used to retrieve the arguments and options required to run the specific task. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$output&lt;/code&gt; object is used for displaying what the task is doing or has done. What is actually printed on the console is very important for the issuer of the task. Think of it as the command’s usability. Too little runtime information, the less usable the task.&lt;/p&gt;

&lt;p&gt;Opposite to HTTP requests, tasks run from the command line aren’t supposed to return instantly. They can take a very long time. Imagine a task that loops an entire database table or a task that references an external source repetitively, or maybe a taks that performs a large file transfer. It’s very important to show the issuer what is actually going on, or he/she will be left in the dark for minutes/hours. “Is this task still running?”, “How long has this thing been running yet?”, “Is it almost done?”, “Is it running out of memory?”&lt;/p&gt;

&lt;p&gt;Enter the &lt;a href=&quot;http://symfony.com/doc/current/components/console/helpers/progressbar.html&quot;&gt;ProgressBar&lt;/a&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar&lt;/code&gt; is an output helper that wraps the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputInterface&lt;/code&gt; object. Initiate a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar&lt;/code&gt; object with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputInterface&lt;/code&gt; object, and a number that represents the maximum iterations to be executed, for example number of table rows, number of bytes to be transferred, … For example, do a quick count query first on your database to check the amount of rows that will need to be iterated over. Then while iterating call the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar::advance&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar::setProgress&lt;/code&gt; method to indicate progress.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;15214/455642 [=========&amp;gt;------------------]  33%  21 sec/58 sec  2.1 MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When you call any Symfony console application you can indicate the verbosity you want from the output (use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-vvv&lt;/code&gt; option). When adding 3 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt;’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar&lt;/code&gt; will also display the elapsed time, the estimated time left and the memory the process is currently consuming.&lt;/p&gt;

&lt;p&gt;When transferring a file it’s a bit harder to show the progress of the transfer, but possible. When opening resources (also called “streams”) in PHP one can add a “stream context”. The context defines options and parameters. One parameter is the optional &lt;a href=&quot;http://php.net/manual/en/function.stream-notification-callback.php&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream_notification_callback&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/hannesvdvreken/89cc4e7326c7e077b9e9.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;A resource can be a FTP, SFTP, HTTP, HTTPS source, or anything else that can be streamed over TCP sockets.&lt;/p&gt;

&lt;p&gt;The notification callback will be called to notify you of certain events. See of it as an event dispatching mechanism with a single callable event listener. For example: one can get notified how many bytes are available on the readable stream. After every chunk of data transfer the callback is called with the number of bytes that have been transferred up till then. Also a “completed” event, and several other events are responsible of the callable being called during the lifetime of a resource.&lt;/p&gt;

&lt;p&gt;An example of how to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stream_notification_callback&lt;/code&gt;:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/hannesvdvreken/4e20b9f9569f3d5c6245.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;There are a few caveats though…&lt;/p&gt;

&lt;p&gt;First: stream contexts must be created before the resource is opened. This means one cannot use the notification callback for existing resources.&lt;/p&gt;

&lt;p&gt;That is why in the previous example I only used Flysystem to write the stream to a file, but not to initiate the read stream. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FilesystemInterface::readStream&lt;/code&gt; returns a resoure but it doesn’t allow you to set a stream context.
By the way, some Flysystem adapters implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readStream&lt;/code&gt; in a slightly inexpected way. To comply with the interface, the &lt;a href=&quot;https://github.com/thephpleague/flysystem/blob/166a16f7e966d5eac46fb7a9849db21734718495/src/Adapter/Ftp.php#L352-L365&quot;&gt;FTP adapter&lt;/a&gt; and the &lt;a href=&quot;https://github.com/thephpleague/flysystem-dropbox/blob/2f464a6a80c0dcc2113a8cc636ca9d4a0fc26617/src/DropboxAdapter.php#L101-L115&quot;&gt;Dropbox adapter&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readStream&lt;/code&gt; methods need to return a resource. They don’t have a native way to open a stream and return that, so they need to read the entire source file content and append it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php://temp&lt;/code&gt; (in memory) stream. Then the memory stream is rewound, so it is ready to read, and ultimately returned.&lt;/p&gt;

&lt;p&gt;Second caveat: using resources and a notification callback doesn’t mean the transfer is asynchronous. To create truly asynchronous transfers I would recommend taking a look at &lt;a href=&quot;http://reactphp.org/&quot;&gt;ReactPHP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally the true benefits of resources and the notification callback are:&lt;/p&gt;

&lt;p&gt;Large files aren’t stored in memory while transferring. Only buffered chunks are kept in memory. To give an example: I managed to transfer an entire Ubuntu iso file over HTTP to the local file system while the process was using merely 2.2MB of memory. And last but not least: the issuer of the taks sees how the task is progressing. This greatly improves the usability of the task.&lt;/p&gt;

&lt;p&gt;Happy streaming!&lt;/p&gt;
</description>
        <pubDate>Tue, 12 May 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/05/12/stream-progress/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/05/12/stream-progress/</guid>
        
        <category>php</category>
        
        <category>resource</category>
        
        <category>stream</category>
        
        <category>symfony</category>
        
        <category>console</category>
        
        <category>progressbar</category>
        
        
        <category>php</category>
        
      </item>
    
      <item>
        <title>How clean is your code? How clean are your diffs?</title>
        <description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this is a repost from my post on the &lt;a href=&quot;http://blog.madewithlove.be/post/code-style-options-for-cleaner-diffs/&quot;&gt;madewithlove blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.madewithlove.be/post/legacy-code-style-fixing/&quot;&gt;My previous blog post&lt;/a&gt; covered tips on code style fixing while working on legacy projects. The blog post was very generic and the ideas are applicable on projects in any language. I mentioned some tips that help your peer developers review your pull requests. What I didn’t mention are code style standards and code style details.&lt;/p&gt;

&lt;p&gt;In this blog post I would like to share some thoughts on code style details for cleaner diffs.&lt;/p&gt;

&lt;h3 id=&quot;diffs&quot;&gt;Diffs&lt;/h3&gt;

&lt;p&gt;Cleaner diffs make it easier for your peer developers to review code changes. When your peers don’t get distracted by awkward diff lines you can expect a more thoughtful review, less overlooked bugs, and more honest feedback. Here are a couple of code style tips that allow for cleaner diffs.&lt;/p&gt;

&lt;h4 id=&quot;tip-1-add-as-many-trailing-commas-as-possible&quot;&gt;Tip 1: Add as many trailing commas as possible!&lt;/h4&gt;

&lt;p&gt;When you’re appending new lines to a list, you might need to add a comma to the previous last item in order
to comply with the syntax. Some languages allow to append a comma to the last line without throwing syntax errors.&lt;/p&gt;

&lt;p&gt;This first example has a clean diff when you’re appending a new item to the array initialisation:
&lt;script src=&quot;https://gist.github.com/hannesvdvreken/6ceaf8b553af057d8950.js&quot;&gt;&lt;/script&gt;
&lt;a href=&quot;https://gist.github.com/hannesvdvreken/6ceaf8b553af057d8950/revisions&quot;&gt;watch the clean diffs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This second example is less clean:
&lt;script src=&quot;https://gist.github.com/hannesvdvreken/cadc3d8d6ff72e848dea.js&quot;&gt;&lt;/script&gt;
&lt;a href=&quot;https://gist.github.com/hannesvdvreken/cadc3d8d6ff72e848dea/revisions&quot;&gt;watch the harder diffs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is it not possible to add a comma to the last item of a block/array/… because of syntax limitations?
You can sometimes avoid appending to the back of the list by ordering the list items. That way you’ll mostly insert items in the middle and not at the end.
Are you a Composer user? It’s actually a bad practise to touch your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt; file.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;Therefore, use a special flag to have Composer sort your items for you: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer require monolog/monolog --sort-packages&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;tip-2-dont-align-assignments&quot;&gt;Tip 2: Don’t align assignments&lt;/h4&gt;

&lt;p&gt;Don’t align things like consecutive assignments (aligning equal signs) or list definitions (aligning arrows or semicolons). When the longest line changes in length, or when a new longer line is added, you will need to adjust the other lines by adding or removing spaces, resulting in larger diffs. If you didn’t align them, it’s more clear on what has been changed or added.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Consecutive variable assignments:&lt;/li&gt;
&lt;/ul&gt;

&lt;script src=&quot;https://gist.github.com/hannesvdvreken/f8c54e469c8d663c4893.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/hannesvdvreken/f8c54e469c8d663c4893/revisions&quot;&gt;watch the clean diffs&lt;/a&gt;
&lt;script src=&quot;https://gist.github.com/hannesvdvreken/abc21707ff86707131f7.js&quot;&gt;&lt;/script&gt;
&lt;a href=&quot;https://gist.github.com/hannesvdvreken/abc21707ff86707131f7/revisions&quot;&gt;watch the harder diffs&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;List/array assignments:&lt;/li&gt;
&lt;/ul&gt;

&lt;script src=&quot;https://gist.github.com/hannesvdvreken/c5ff31f02dc5aba2b3ee.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/hannesvdvreken/c5ff31f02dc5aba2b3ee/revisions&quot;&gt;watch the clean diffs&lt;/a&gt;
&lt;script src=&quot;https://gist.github.com/hannesvdvreken/62db1c762cf969da5344.js&quot;&gt;&lt;/script&gt;
&lt;a href=&quot;https://gist.github.com/hannesvdvreken/62db1c762cf969da5344/revisions&quot;&gt;watch the harder diffs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just a suggestion, though. People like to align assignments for various reasons. Because it’s pretty, or because it’s visually easier to scan a file. If you like the benefits of aligning over the downside of the heavier diffs, go ahead: align.&lt;/p&gt;

&lt;h4 id=&quot;tip-3-use-as-many-braces-as-possible&quot;&gt;Tip 3: use as many braces as possible&lt;/h4&gt;

&lt;p&gt;It’s sometimes possible to leave off certain braces. For example: calling a constructor in PHP when passing zero arguments is possible without braces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$client = new GuzzleHttp\Client;&lt;/code&gt; but when you need to change that and need to pass one or more arguments to the constructor, you’ll still need to add the braces. You might notice I’m nitpicking here, this doesn’t actually result in super ugly diffs. But what about when you delete the last argument of a constructor? Do you delete the braces from every existing constructor call? If not, you’ll end up with inconsistent notation.&lt;/p&gt;

&lt;p&gt;Often language syntax allows you to use control structures (if, for, while, …) without braces as well: they just use the single next line as the code block to execute conditionally, if no braces are used. Apart from the risk of bugs this also results in &lt;a href=&quot;https://gist.github.com/hannesvdvreken/e87a2a73b5d3df49d572/revisions&quot;&gt;harder diffs&lt;/a&gt; when you add lines, or inconsistencies when you remove lines but don’t remove the braces.&lt;/p&gt;

&lt;h4 id=&quot;tip-4-have-clear-rules-on-whitespace&quot;&gt;Tip 4: have clear rules on whitespace&lt;/h4&gt;

&lt;p&gt;Have your editor and code style tool be clear on whitespace: where to have how many invisible characters (spaces, tabs, new lines). EditorConfig is an editor independent config file that can help you with that. In PHP we like to remove trailing whitespace at the end of a line, and empty lines must be completely empty. We also like to have a single empty line at the end of every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.php&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;When a diff contains whitespace changes one can often ignore those lines. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff -bw&lt;/code&gt; (short for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff --ignore-space-change --ignore-all-space&lt;/code&gt;) or add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?w=0&lt;/code&gt; in the address bar when viewing a diff on GitHub.&lt;/p&gt;

&lt;h3 id=&quot;php-cs-fixer&quot;&gt;PHP CS fixer&lt;/h3&gt;

&lt;p&gt;At &lt;a href=&quot;http://mwl.be&quot;&gt;madewithlove&lt;/a&gt; we like to follow industry standards. This includes code style standards.
For PHP that means PSR-2, and the stricter &lt;a href=&quot;http://symfony.com/doc/current/contributing/code/standards.html&quot;&gt;Symfony coding standards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The tool we use most for automated code style fixing
is &lt;a href=&quot;http://cs.sensiolabs.org/&quot;&gt;php-cs-fixer&lt;/a&gt;, currently maintained by the GitHub organisation &lt;a href=&quot;https://github.com/FriendsOfPHP&quot;&gt;FriendsOfPHP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The php-cs-fixer tool has some options to guard some of the tips mentioned in this post previously.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;multiline_array_trailing_comma&lt;/code&gt; fixer can be used to append commas everywhere, but is never enabled by default.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new_with_braces&lt;/code&gt; fixer is not enabled on the PSR-2 level, but it is on the Symfony level.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;phpdoc_params&lt;/code&gt; is included in the Symfony level, it aligns docblock items so I like to disable it instead.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;align_double_arrow&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;align_equals&lt;/code&gt; options are available, but I rather leave them off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, these aren’t golden rules. I just have my reasons to enable or disable them. Define the rules you like for your projects and make sure to run the code style fixer regularly. For example before every commit, when your code base already adheres to all those rules, or after every commit on the files that have been changes, to slowly move to a cleaner code base.&lt;/p&gt;

&lt;p&gt;Happy CS fixing!&lt;/p&gt;
</description>
        <pubDate>Fri, 08 May 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/05/08/code-style-options-for-cleaner-diffs/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/05/08/code-style-options-for-cleaner-diffs/</guid>
        
        <category>php-cs-fixer</category>
        
        <category>php</category>
        
        <category>cs</category>
        
        <category>whitespace</category>
        
        
        <category>code-style</category>
        
      </item>
    
      <item>
        <title>Improving code style when working on a legacy code base</title>
        <description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this is a repost from my post on the &lt;a href=&quot;http://blog.madewithlove.be/post/legacy-code-style-fixing/&quot;&gt;madewithlove blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;legacy-projects&quot;&gt;Legacy projects&lt;/h3&gt;

&lt;p&gt;Old projects (maybe even 6 months or less) often come without test suites,
are tightly coupled with an outdated version of a framework (if not: has lots of boilerplate code),
and are written without consistency in code style.&lt;/p&gt;

&lt;p&gt;When working on such a project, it’s tempting to start moving brackets around,
replacing old syntax style with newer language version syntax,
and renaming variables/classes/functions. Especially when you’re refactoring or adding a feature.&lt;/p&gt;

&lt;p&gt;With this blog post I wanted to share some tips and pitfalls on code style changes in legacy projects.&lt;/p&gt;

&lt;h3 id=&quot;code-style&quot;&gt;Code style&lt;/h3&gt;

&lt;p&gt;First of all: fixing code style isn’t necessarily a bad thing.
Code style makes code more readable, less personal, and more uniform.
As long as there is some kind of agreement that you will be working on this project for at least the next few months,
your future self and colleagues might benefit from a better code style.&lt;/p&gt;

&lt;h3 id=&quot;how-to-improve-code-style&quot;&gt;How to improve code style&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Do not change code style in files or functions when you’re not required to change the code at all. This confuses your peer developers that need to review your changes.&lt;/li&gt;
  &lt;li&gt;Feel free to adjust docblocks if they are missing or plain wrong and add documentation where needed.&lt;/li&gt;
  &lt;li&gt;When you’re about to adjust a method, always –always– commit code style changes separately from code changes, even if the changed code produces the exact same output and behaves exactly the same. Peer developers that need to review your code can review your pull requests without having to investigate what has changed, and what is just an adjustment of code style. They can review individual commits and ignore commits with “CS” in the commit message.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;cs-fixing-tools&quot;&gt;CS fixing tools&lt;/h3&gt;

&lt;p&gt;You might be tempted to use an automated tool to reformat an entire file, or even your entire code base.
Here’s why that’s not a good idea:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You lose all line history. Imagine backtracking why a certain line has been changed in the past when every line has been changed in the same commit, maybe just because of a tabs to spaces conversion.&lt;/li&gt;
  &lt;li&gt;All existing open pull request will need to be updated to base off of the newly formatted code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a good idea to setup a CS fixer for newly created files though.
You can gradually build up a namespace full of new
classes that adhere to a certain code style standard and have it backed by an automated tool.&lt;/p&gt;

&lt;p&gt;While refactoring you can slim down existing classes and functions and inject new, well tested dependencies.
That way you can slowly move away from the legacy code that’s still badly formatted.&lt;/p&gt;

&lt;p&gt;If you do want to reformat an entire directory of code, despite my advise,
make sure to have as few branches and open pull requests as possible. Ideally: no pull request and only one branch.
Then do a single commit where you only reformat the code, nothing else. Push it, and done!&lt;/p&gt;

&lt;p&gt;Happy CS fixing!&lt;/p&gt;
</description>
        <pubDate>Mon, 27 Apr 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/04/27/legacy-code-style-fixing/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/04/27/legacy-code-style-fixing/</guid>
        
        <category>code-style</category>
        
        <category>legacy</category>
        
        
        <category>code-style</category>
        
        <category>legacy</category>
        
      </item>
    
      <item>
        <title>Running my very first marathon</title>
        <description>&lt;h1 id=&quot;start-to-run&quot;&gt;Start to run&lt;/h1&gt;

&lt;p&gt;In june 2014 I started running because I had secured a speaker slot at the community day of Laracon EU. For my presentation I wanted to look fit on stage. To gain confidence I wanted to drop a few kilograms of weight. I started with a 9 km run and gradually ran further and further.&lt;/p&gt;

&lt;p&gt;In august I had been able to run a 1/2 marathon in one hour and fifty minutes, a week before the conference. The conference happened and I was pretty happy with my performance on stage.&lt;/p&gt;

&lt;p&gt;After that I kept running 1/2 marathons for training but I could only improve my time by 5 minutes. Every time I ran I was completely exhausted and my times weren’t improving. I bought a heart rate monitor on low energy bluetooth and found out I was running at max heart rate. This alarmed me.&lt;/p&gt;

&lt;h2 id=&quot;physical-tests&quot;&gt;Physical tests&lt;/h2&gt;

&lt;p&gt;In November I went to see physiologists in the university hospital. They tested my endurance by measuring oxygen intake, heart rate monitoring and taking blood samples.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2015-04-13-running-my-first-marathon/mofarah.jpg&quot; alt=&quot;physical tests&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;preparing-for-a-marathon&quot;&gt;Preparing for a marathon&lt;/h2&gt;

&lt;p&gt;After those tests I got a 16 week training shedule to lower my heart rate and got some nutrition tips. I also researched about exercises, training schedules, physiology and nutrition on the internet afterwards. And so I started to run 4 sessions a week. Next to running I started climbing again, one time a week, to build upper core muscles. If you would do cardio training only you would burn all your unused muscles and become a walking skeleton, but with strong legs.&lt;/p&gt;

&lt;p&gt;When I saw good progress I decided to register for the Rotterdam Marathon. It’s a big event with good atmosphere and other runners seemded to love it. Rotterdam was a city I’ve never visited and it’s only 80 minutes driving by car. 16 weeks of training turned into 24 weeks of training, because I started training before I knew which marathon I would run and how many weeks I had left.&lt;/p&gt;

&lt;p&gt;I kept running 4 sessions per week during the winter and only took a break for one week to go skiing. I ran multiple sessions of 2.5 hours and 3 hours, with a maximum of one long running session per week. My last training sessions showed me I was capable of running an average pace of sub 5:00 per kilometer for a duration of 3 hours. I was pretty confident I could run a marathon in 3 hours 30 minutes, or less than 3 hours 40 minutes if I wouldn’t be able to keep up the speed till the end.&lt;/p&gt;

&lt;h2 id=&quot;race-day&quot;&gt;Race day&lt;/h2&gt;

&lt;p&gt;April 12th, the day of the marathon came. My girlfriend and her younger sister joined me to Rotterdam. 40 minutes ahead of the race I was ready for departure in wave 1, block E. The sun was behind some tall buildings and the block was pretty crowded for the last 30 minutes before the race, so my muscles weren’t warm at all. I was also in a block of slower runners because 20 weeks ago, when I registered, I didn’t know I would be a 3:30:00 runner rather than a 4:00:00 runner.&lt;/p&gt;

&lt;p&gt;The first 5 km were hard because my legs weren’t warmed up. I had to overtake lots of slower runners in order to not lose too much time. I was acidified after 2 kilometers and had to gently slow down for the next few kilometers to recover. After 10 km I was about 45 seconds behind schedule but I had completely recovered from the start and started to increase my pace again. I only noticed this when we passed the half way point but I had been running behind the same couple since the 10 km mark. They had the perfect pace for me! I planned to be about one or two minutes behind schedule at 21 km. I ended up being only 46 seconds behind schedule. I executed the first half according to plan because I kept calm.&lt;/p&gt;

&lt;h2 id=&quot;second-half-of-the-race&quot;&gt;Second half of the race&lt;/h2&gt;

&lt;p&gt;After the half way point the couple ahead of me started to increase their pace by 5-10 seconds per km, which was my game plan as well, so I kept chasing them. At the 30 km mark they slowed down for drinks, which they did every 5 km. I overtook them, thinking they would keep up with me, but I never saw them again. At 34 km at the side of the track people were handing out capsules of gel (high energy sweet sirup) which I ate together with a cup of water at 35 km. This way I was able to give my body some extra fuel for the last 7 km. The last 7 km I noticed a lot of people started to slow down, even walk. I managed to keep my pace till the very last kilometer, thanks to the Dutch crowd cheering. In the last 500 meters I gave it everything I had left. 3 hours, 29 minutes and 21 seconds after the start I ran across the finish line of my first marathon.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2015-04-13-running-my-first-marathon/finish.jpg&quot; alt=&quot;race result&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To my surprise I didn’t lose any time in the last 5 km. Probably this has something to do with all the measures I took in the last weeks before the race. No alcohol, no intensive workouts, but loads of carbs and water and a few good nights rest. And of course the gel containing high levels of glucose at about 34 kilometer.&lt;/p&gt;

&lt;blockquote class=&quot;instagram-media&quot; data-instgrm-captioned=&quot;&quot; data-instgrm-version=&quot;4&quot; style=&quot; background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);&quot;&gt;&lt;div style=&quot;padding:8px;&quot;&gt; &lt;div style=&quot; background:#F8F8F8; line-height:0; margin-top:40px; padding:50% 0; text-align:center; width:100%;&quot;&gt; &lt;div style=&quot; background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAAGFBMVEUiIiI9PT0eHh4gIB4hIBkcHBwcHBwcHBydr+JQAAAACHRSTlMABA4YHyQsM5jtaMwAAADfSURBVDjL7ZVBEgMhCAQBAf//42xcNbpAqakcM0ftUmFAAIBE81IqBJdS3lS6zs3bIpB9WED3YYXFPmHRfT8sgyrCP1x8uEUxLMzNWElFOYCV6mHWWwMzdPEKHlhLw7NWJqkHc4uIZphavDzA2JPzUDsBZziNae2S6owH8xPmX8G7zzgKEOPUoYHvGz1TBCxMkd3kwNVbU0gKHkx+iZILf77IofhrY1nYFnB/lQPb79drWOyJVa/DAvg9B/rLB4cC+Nqgdz/TvBbBnr6GBReqn/nRmDgaQEej7WhonozjF+Y2I/fZou/qAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;p style=&quot; margin:8px 0 0 0; padding:0 4px;&quot;&gt; &lt;a href=&quot;https://instagram.com/p/1YnRq_OwU1/&quot; style=&quot; color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;&quot; target=&quot;_top&quot;&gt;3:29:05 #mr15. The crowd was amazing!&lt;/a&gt;&lt;/p&gt; &lt;p style=&quot; color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;&quot;&gt;A photo posted by Hannes Van De Vreken (@hannesvdvreken) on &lt;time style=&quot; font-family:Arial,sans-serif; font-size:14px; line-height:17px;&quot; datetime=&quot;2015-04-12T18:15:53+00:00&quot;&gt;Apr 12, 2015 at 11:15am PDT&lt;/time&gt;&lt;/p&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; defer=&quot;&quot; src=&quot;//platform.instagram.com/en_US/embeds.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Will I ever do this again? I think so.
Will I ever beat my personal best? Maybe, because I don’t know if I was just lucky that everything went exactly right, or if I ran this great time just because of good training. I measured my heart rate throughout the race and noticed it’s higher than I would have hoped. I’ll be training on this in the future.&lt;/p&gt;

&lt;p&gt;Thanks for all the wishes and cheers!&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Apr 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/04/13/running-my-first-marathon/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/04/13/running-my-first-marathon/</guid>
        
        <category>marathon</category>
        
        <category>rotterdam</category>
        
        <category>running</category>
        
        <category>fitness</category>
        
        <category>health</category>
        
        
        <category>running</category>
        
      </item>
    
      <item>
        <title>Tilde and caret version constraints in Composer</title>
        <description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this is a repost from my post on the &lt;a href=&quot;http://blog.madewithlove.be/post/tilde-and-caret-constraints/&quot;&gt;madewithlove blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When installing a dependency we are used to install a version that adheres to a
known public interface and does what it promises. That way we can safely use it in our code.&lt;/p&gt;

&lt;p&gt;A dependency that uses semantic versioning allows you to predict wether it is still going to work or not
when you upgrade it to a new version. Basically when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.y.z&lt;/code&gt; version number changes,
you might need to do some changes to be able to work with this new version without problems.
When dealing with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.y.z&lt;/code&gt; version this is slightly different: when the first non-zero number (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;) changes,
backwards compatibility is not guaranteed. If you’re not familiar with semver:
head over to the &lt;a href=&quot;http://semver.org/&quot;&gt;specs&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;A dependency can change without breaking backwards compatibility. A new release will then have a
greater version number (x.y), depending on the type of change (bugfix or added functionality).
When you depend on packages you might want to define a range of versions that are OK to install,
rather than having a locked down version specified. This allows you to receive fixes
(that includes security fixes) from external code for free with a simple update command.&lt;/p&gt;

&lt;p&gt;Depending on your dependency manager you can define version contraints using wildcards (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;), comparators like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;=&lt;/code&gt;,
logical operators (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt; often means AND and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|&lt;/code&gt; means OR), etc… Using logical operators you can mix and match
different version constraints to build even more complex ones. For example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=0.9.0,&amp;lt;0.11.0&lt;/code&gt;
means everything that matches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.9.*&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.10.*&lt;/code&gt;, but can also be noted as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.9.* || 0.10.*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are also some syntactic sugar operators like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; (tilde) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt; (caret).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=laravel%2Fframework&amp;amp;version=~4.2.3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~4.1.3&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=4.1.3,&amp;lt;4.2.0&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=laravel%2Fframework&amp;amp;version=~4.2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~4.1&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=4.1.0,&amp;lt;5.0.0&lt;/code&gt; (most used),&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=league%2Fflysystem&amp;amp;version=~0.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~0.4&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=0.4.0,&amp;lt;1.0.0&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=laravel%2Fframework&amp;amp;version=~4.2.3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~4&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=4.0.0,&amp;lt;5.0.0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The caret sign is slightly different:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=laravel%2Fframework&amp;amp;version=%5E4.1.3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^4.1.3&lt;/code&gt;&lt;/a&gt; (most used) means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=4.1.3,&amp;lt;5.0.0&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=laravel%2Fframework&amp;amp;version=%5E4.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^4.1&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=4.1.0,&amp;lt;5.0.0&lt;/code&gt;, same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~4.1&lt;/code&gt; but:&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=league%2Fflysystem&amp;amp;version=%5E0.4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^0.4&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=0.4.0,&amp;lt;0.5.0&lt;/code&gt;, this is different from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~0.4&lt;/code&gt; and is more useful for defining backwards compatible version ranges.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://semver.mwl.be/#?package=laravel%2Fframework&amp;amp;version=%5E4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^4&lt;/code&gt;&lt;/a&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=4.0.0,&amp;lt;5.0.0&lt;/code&gt; which is the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~4&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4.*&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically use the caret sign to exclude early releases which contain known threats. For example if you need
a dependency which has functionality which got introduced in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.1.x&lt;/code&gt; and version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.1.1&lt;/code&gt; fixes a bug which
was shipped with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.1.0&lt;/code&gt; release. If that bug affected you or when it’s a security bug,
you will be able to exclude all earlier versions with
&lt;a href=&quot;http://semver.mwl.be/#?package=league%2Fevent&amp;amp;version=%5E2.1.1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^2.1.1&lt;/code&gt;&lt;/a&gt;.
This way you can still benefit from all new backward compatible releases.&lt;/p&gt;

&lt;p&gt;Fun fact: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caret&lt;/code&gt; is Latin for “it lacks”, so you can remember this as “it (this version range) lacks
some early releases but it’s backwards compatible up to the next major release”.&lt;/p&gt;

&lt;p&gt;For now when you run the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer require monolog/monolog&lt;/code&gt; it will still save &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~1.13&lt;/code&gt;
(at the time of writing) as the default version constraint in your composer.json file and not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^1.13.1&lt;/code&gt;.
This is to protect users who might not have updated their Composer to a version which can handle
caret &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt; constraints. Expect this to change in the coming weeks or months.&lt;/p&gt;

&lt;p&gt;In case you didn’t notice yet, the links behind all these version constraints point to
&lt;a href=&quot;http://semver.mwl.be&quot;&gt;semver.mwl.be&lt;/a&gt;. We created this tool after &lt;a href=&quot;https://twitter.com/anahkiasen&quot;&gt;Maxime&lt;/a&gt;
posted a link to &lt;a href=&quot;http://semver.npmjs.com/&quot;&gt;semver.npmjs.com&lt;/a&gt; in our &lt;a href=&quot;http://mwl.be&quot;&gt;madewithlove&lt;/a&gt; slack channel.&lt;/p&gt;

&lt;p&gt;I won’t go into stability as it is out of the scope of this blog post, but I suggest you play around with
&lt;a href=&quot;http://semver.mwl.be/#?package=symfony%2Fsymfony&amp;amp;version=~2.4&amp;amp;minimum-stability=RC&quot;&gt;our tool&lt;/a&gt;
to see the effect of selecting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stable&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RC&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beta&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Apr 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/04/13/tilde-and-caret-constraints/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/04/13/tilde-and-caret-constraints/</guid>
        
        <category>php</category>
        
        <category>composer</category>
        
        <category>semver</category>
        
        
        <category>composer</category>
        
      </item>
    
      <item>
        <title>Work-in-progress Pull Requests</title>
        <description>&lt;p&gt;A while ago I saw a discussion on Twitter on when to open a pull request,
when you’re done creating the changes, or when you start working on something?
The latter is the preferred option, in my opinion.&lt;/p&gt;

&lt;p&gt;Crafting a PR is possible from the moment you do a first commit on a new branch. You can start with a “&lt;a href=&quot;http://jason.pureconcepts.net/2015/01/are-you-a-boy-scout/&quot;&gt;boyscouting&lt;/a&gt;”
commit which only moves some code around but doesn’t change any functionality. When you create
a work-in-progress PR make sure to tag it with a WIP label or prepend &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[WIP]&lt;/code&gt; to the title.&lt;/p&gt;

&lt;p&gt;WIP pull requests have several benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The description can be kept up to date with a changelog right from the start. You can keep documenting changes, needed changes for users of the public interface, …&lt;/li&gt;
  &lt;li&gt;Allows peer developers to advice early if a developer is spending time on something that will most probably not be merged.&lt;/li&gt;
  &lt;li&gt;Allows peer developers to take a quick look to see if a feature implementation isn’t getting overcomplicated. Feature requirements aren’t always clear and could sometimes be translated into something much simpler. This could prevent spending a whole week while it could be done in a few hours.&lt;/li&gt;
  &lt;li&gt;When you are pushing a couple of code cleaning commits first, peers know they don’t need to review just yet.&lt;/li&gt;
  &lt;li&gt;Building a clear timeline on the evolution of this branch. Who did what, who reviewed when, who was assigned, what states did it go through (from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIP&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;in review&lt;/code&gt; etc), what extra changes have been made, …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When not to open a WIP pull request?
When the project you are working on is a public project and the feature you are building is top secret,
you might want to postpone pushing your branch. Also a PR for an open source project can start a long discussion
between community members before you even finished your work. In these kind of situations it is perfectly normal
to keep your branch local for the time you’re working on it.&lt;/p&gt;

&lt;p&gt;At &lt;a href=&quot;http://mwl.be&quot;&gt;madewithlove&lt;/a&gt; we definitely like this approach of opening WIP pull requests.
It gives all these benefits to peer developers. For project managers this gives the ability to track
progress, next to what they can see on &lt;a href=&quot;https://huboard.com&quot;&gt;huboard&lt;/a&gt; or &lt;a href=&quot;https://www.zenhub.io/&quot;&gt;zenhub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;
</description>
        <pubDate>Thu, 09 Apr 2015 00:00:00 +0000</pubDate>
        <link>https://hannesvdvreken.com/2015/04/09/work-in-progress-pull-requests/</link>
        <guid isPermaLink="true">https://hannesvdvreken.com/2015/04/09/work-in-progress-pull-requests/</guid>
        
        <category>work</category>
        
        <category>git</category>
        
        
        <category>workflow</category>
        
      </item>
    
  </channel>
</rss>
