<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Johannes Pichler's blog about Web Development</title><link>https://fetzi.dev/</link><description>Recent content on Johannes Pichler's blog about Web Development</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 29 Mar 2026 17:48:33 +0200</lastBuildDate><atom:link href="https://fetzi.dev/feed.xml" rel="self" type="application/rss+xml"/><item><title>Crafting Elegant APIs with Laravel</title><link>https://fetzi.dev/talk/crafting-elegant-apis-with-laravel-dpc/</link><pubDate>Fri, 13 Mar 2026 14:25:00 +0100</pubDate><guid>https://fetzi.dev/talk/crafting-elegant-apis-with-laravel-dpc/</guid><description/></item><item><title>Getting your code ready for PHP 8.5</title><link>https://fetzi.dev/getting-cody-ready-for-php-8-5/</link><pubDate>Thu, 22 Jan 2026 08:00:00 +0100</pubDate><guid>https://fetzi.dev/getting-cody-ready-for-php-8-5/</guid><description>&lt;p&gt;PHP 8.5 was released about two months ago, so it should be stable enough to upgrade. I generally avoid big-bang releases, especially since I run multiple applications on a single server. To prevent a risky all-at-once upgrade and to verify that everything works correctly before switching PHP versions, I was looking for a way to upgrade the codebase beforehand.&lt;/p&gt;
&lt;h2 id="getting-ready"&gt;Getting ready&lt;/h2&gt;
&lt;p&gt;To prepare an application for PHP 8.5, two changes are required.
First, allow the new PHP version in the version constraint inside the &lt;code&gt;require&lt;/code&gt; section:&lt;/p&gt;</description></item><item><title>Crafting Elegant APIs with Laravel</title><link>https://fetzi.dev/talk/crafting-elegant-apis-with-laravel-phpday/</link><pubDate>Thu, 16 May 2024 10:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/crafting-elegant-apis-with-laravel-phpday/</guid><description/></item><item><title>Using action classes for table actions in Filament 3</title><link>https://fetzi.dev/action-classes-in-filament-3/</link><pubDate>Tue, 07 Nov 2023 08:00:00 +0100</pubDate><guid>https://fetzi.dev/action-classes-in-filament-3/</guid><description>&lt;p&gt;I recently switched a private project from Laravel Nova to Filament 3 and had the problem that defining custom table actions was complicated and the produced code was unreadable, at least for me.&lt;/p&gt;
&lt;p&gt;I was spoiled by Nova because it provides Action classes that contain the actual action logic and also the action configuration such as label, name etc.&lt;/p&gt;
&lt;p&gt;Now lets look at some example code from Filament 3:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// ... table definitions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;send-booking-confirmation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Booking&lt;/span&gt; &lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SendBookingConfirmation&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nv"&gt;$booking&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Send confirmation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see there is quite a lot of code necessary in the the resource class to register a custom action. IMHO this configuration should be boxed inside an action class, especially if the action is reused in multiple resources.&lt;/p&gt;</description></item><item><title>Battle tested Laravel API design</title><link>https://fetzi.dev/talk/battle-tested-laravel-api-design/</link><pubDate>Thu, 28 Sep 2023 10:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/battle-tested-laravel-api-design/</guid><description/></item><item><title>Battle tested API design</title><link>https://fetzi.dev/talk/battle-tested-api-design-laraconeu/</link><pubDate>Thu, 28 May 2020 09:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/battle-tested-api-design-laraconeu/</guid><description/></item><item><title>API Caching done right</title><link>https://fetzi.dev/api-caching-done-right/</link><pubDate>Tue, 14 Jan 2020 08:00:00 +0100</pubDate><guid>https://fetzi.dev/api-caching-done-right/</guid><description>&lt;p&gt;Especially for web client applications data caching is an important topic. But as an API developer you want to make sure that every type of client can use your caching mechanism to only download data when it is needed and necessary.&lt;/p&gt;
&lt;p&gt;Ok you may say that if the client requests an endpoint it wants to retrieve the requested data.&lt;/p&gt;
&lt;p&gt;But consider the following example: you are loading a certain product page in your application (a SPA for example) and simply press the refresh button. Your app needs to fetch the product data twice from the API. The second request is completely redundant because it is very unlikely that the resource data has changed between this two requests.&lt;/p&gt;</description></item><item><title>(Understanding) OAuth2... for real?</title><link>https://fetzi.dev/talk/understanding-oauth2-websummercamp/</link><pubDate>Fri, 30 Aug 2019 13:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/understanding-oauth2-websummercamp/</guid><description/></item><item><title>Battle tested API design</title><link>https://fetzi.dev/talk/battle-tested-api-design-websummercamp/</link><pubDate>Fri, 30 Aug 2019 09:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/battle-tested-api-design-websummercamp/</guid><description/></item><item><title>(Understanding) OAuth2... for real?</title><link>https://fetzi.dev/talk/understanding-oauth2-neos/</link><pubDate>Fri, 10 May 2019 12:00:00 +0100</pubDate><guid>https://fetzi.dev/talk/understanding-oauth2-neos/</guid><description/></item><item><title>(Understanding) OAuth2... for real?</title><link>https://fetzi.dev/talk/understanding-oauth2-phpersday/</link><pubDate>Sat, 02 Mar 2019 12:00:00 +0100</pubDate><guid>https://fetzi.dev/talk/understanding-oauth2-phpersday/</guid><description/></item><item><title>An introduction to Golang</title><link>https://fetzi.dev/talk/an-introduction-to-golang/</link><pubDate>Wed, 23 Jan 2019 12:00:00 +0100</pubDate><guid>https://fetzi.dev/talk/an-introduction-to-golang/</guid><description/></item><item><title>Living documentation for developers</title><link>https://fetzi.dev/living-documentation-for-developers/</link><pubDate>Sun, 20 Jan 2019 08:00:00 +0100</pubDate><guid>https://fetzi.dev/living-documentation-for-developers/</guid><description>&lt;p&gt;At work we are storing all our technical documents (process descriptions, technical and functional documentations) in Confluence. For developers (and especially me) it is difficult to store technical documents separated from source code.&lt;/p&gt;
&lt;p&gt;In the past I often got in trouble because the documentation for our current product was outdated and some adapted functionality, after a live deploy, did not work out as expected.&lt;/p&gt;
&lt;p&gt;This led me to think about our current documentation update process, actually there was nothing defined in my team. So I started to think about how I am able to ensure an up to date documentation when the source code changes in confluence.&lt;/p&gt;</description></item><item><title>Decouple everything</title><link>https://fetzi.dev/talk/decouple-everything-devfest/</link><pubDate>Sat, 24 Nov 2018 12:00:00 +0100</pubDate><guid>https://fetzi.dev/talk/decouple-everything-devfest/</guid><description/></item><item><title>Static route parameters in Laravel</title><link>https://fetzi.dev/static-route-parameters-in-laravel/</link><pubDate>Wed, 08 Aug 2018 08:00:00 +0100</pubDate><guid>https://fetzi.dev/static-route-parameters-in-laravel/</guid><description>&lt;p&gt;Route parameters are a very common approach to pass input data to your controller methods. &lt;a href="https://laravel.com/docs/5.6/routing#route-parameters"&gt;Laravel&lt;/a&gt; provides a lot of different features and possiblities for using route parameters in your application.&lt;/p&gt;
&lt;p&gt;Recently I had to implement some content pages that are backed by a database table. This means that every content page has a unique slug and this slug is used to lookup the page content in the database.&lt;/p&gt;

&lt;script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7DKKQM&amp;placement=fetzidev" id="_carbonads_js"&gt;&lt;/script&gt;

&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// routes.php
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/imprint&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ContentController@imprint&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/privacy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ContentController@privacy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This route definitions would call the following Controller methods:&lt;/p&gt;</description></item><item><title>Feature flags in Laravel</title><link>https://fetzi.dev/feature-flags-in-laravel/</link><pubDate>Wed, 04 Jul 2018 20:00:00 +0100</pubDate><guid>https://fetzi.dev/feature-flags-in-laravel/</guid><description>&lt;p&gt;Normally A/B split testing is about smaller layout adaptions or simple feature changes. But in some cases a complete rewrite of a feature is necessary and should be compared to the old solution. The normal workflow in our team is to create a feature cookie to determine if the user should recieve the A or the B version. For example if the cookie exists the user will recieve version A and otherwise version B. Some sort of randomise mechanism is used to set the required cookie for a certain percentage of users.&lt;/p&gt;</description></item><item><title>Implementing JSON Patch in Laravel</title><link>https://fetzi.dev/implementing-json-patch-in-laravel/</link><pubDate>Fri, 25 May 2018 20:00:00 +0100</pubDate><guid>https://fetzi.dev/implementing-json-patch-in-laravel/</guid><description>&lt;p&gt;I&amp;rsquo;ve often struggled with the PATCH request method in the past. Of course it should enable an API user to only send a subpart of the document to update. But I never found a good solution how to implement a PATCH request the works out in all needed cases.&lt;/p&gt;
&lt;p&gt;Last week at the &lt;a href="https://www.wearedevelopers.com/congress"&gt;WeAreDevelopers World Congress 2018&lt;/a&gt; in Vienna I listened to a talk about json:api by &lt;a href="https://jeremiahlee.com/"&gt;Jeremiah Lee&lt;/a&gt; and he mentioned JSON Patch for incremental updates on JSON documents.&lt;/p&gt;</description></item><item><title>Executing login protected actions in Laravel</title><link>https://fetzi.dev/executing-login-protected-actions-in-laravel/</link><pubDate>Tue, 22 May 2018 08:00:00 +0100</pubDate><guid>https://fetzi.dev/executing-login-protected-actions-in-laravel/</guid><description>&lt;p&gt;As you may have already noticed I&amp;rsquo;m working for the biggest job platform in Austria, &lt;a href="https://www.karriere.at"&gt;karriere.at&lt;/a&gt;. Naturally our main feature is to provide a fast and reliable job search on our platform and one user feature on the job search is to allow them to add a certain job to their so called &amp;ldquo;watchlist&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;This feature is available for guest and of course for logged in users. The key difference for guest users is, that when they click on &amp;ldquo;watch job&amp;rdquo; the get a tooltip that tells them, that they need to be logged in to be able to watch the job. After clicking on the login link and entering their credentials they get redirected back to the search page and the &amp;ldquo;watch&amp;rdquo; action was already triggered (as intended).&lt;/p&gt;</description></item><item><title>Add composer-link command for local development</title><link>https://fetzi.dev/add-composer-link-command/</link><pubDate>Sun, 20 May 2018 08:00:00 +0100</pubDate><guid>https://fetzi.dev/add-composer-link-command/</guid><description>&lt;p&gt;I&amp;rsquo;ve written a &lt;a href="https://fetzi.dev/developing-composer-packages-locally/"&gt;blog post&lt;/a&gt; a year ago about developing a composer package locally by using it in another project.&lt;/p&gt;
&lt;p&gt;To do so you need to setup a local repository configuration in your &lt;code&gt;composer.json&lt;/code&gt; file and then require the dependency with &lt;code&gt;composer require&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Caleb Porzio has written an article about his &lt;a href="http://calebporzio.com/bash-alias-composer-link-use-local-folders-as-composer-dependancies/"&gt;bash function composer-link&lt;/a&gt; and I enhanced this command to directly require the package with &lt;code&gt;composer-link&lt;/code&gt;.&lt;/p&gt;

&lt;script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7DKKQM&amp;placement=fetzidev" id="_carbonads_js"&gt;&lt;/script&gt;

&lt;h2 id="the-command"&gt;The command&lt;/h2&gt;
&lt;p&gt;The command is responsible for adding the local repository configuration and also to require the dependency.&lt;/p&gt;</description></item><item><title>(Understanding) OAuth2... for real?</title><link>https://fetzi.dev/talk/understanding-oauth2-wad/</link><pubDate>Wed, 16 May 2018 12:00:00 +0100</pubDate><guid>https://fetzi.dev/talk/understanding-oauth2-wad/</guid><description/></item><item><title>Implicit model binding in Slim APIs</title><link>https://fetzi.dev/implicit-model-binding-in-slim-apis/</link><pubDate>Mon, 26 Feb 2018 20:00:00 +0100</pubDate><guid>https://fetzi.dev/implicit-model-binding-in-slim-apis/</guid><description>&lt;p&gt;In my daily job I&amp;rsquo;m building resource APIs based on the &lt;a href="https://www.slimframework.com/"&gt;Slim framework&lt;/a&gt;. Our apis use &lt;a href="https://laravel.com/docs/5.6/eloquent"&gt;Eloquent&lt;/a&gt; for database access and I often miss the convenient functionality of Laravel (called Implicity Binding) to automatically get the corresponding model instance based on a route parameter.&lt;/p&gt;
&lt;p&gt;For example a route &lt;code&gt;/user/{user}&lt;/code&gt; with a controller method that has an annotated input parameter like &lt;code&gt;User $user&lt;/code&gt; will automatically load the &lt;code&gt;User&lt;/code&gt; model for the given identifier.&lt;/p&gt;</description></item><item><title>Profiling PHP applications with XHGui</title><link>https://fetzi.dev/profiling-php-applications-with-xhgui/</link><pubDate>Fri, 26 Jan 2018 10:00:00 +0100</pubDate><guid>https://fetzi.dev/profiling-php-applications-with-xhgui/</guid><description>&lt;p&gt;To profile my php applications I used xdebug in combination with webgrind in the past. Webgrind visualizes the cachegrind files generated by xdebug. This approach is ok but webgrind only contains basic visualization features.&lt;/p&gt;
&lt;p&gt;After some research I ended up with a tool called &lt;a href="http://php.net/manual/en/book.xhprof.php"&gt;Xhprof&lt;/a&gt;. But Xhprof does not have a version for PHP 7.x. So I looked for an alternative and found the cloud service &lt;a href="https://tideways.io"&gt;tideways.io&lt;/a&gt; that provides a profiler extension that is compatible with Xhprof and is available for free.&lt;/p&gt;</description></item><item><title>Why commit messages matter</title><link>https://fetzi.dev/why-commit-messages-matter/</link><pubDate>Wed, 24 Jan 2018 18:00:00 +0100</pubDate><guid>https://fetzi.dev/why-commit-messages-matter/</guid><description>&lt;p&gt;A few months ago we published git commit message guidelines at our company. The defined rules are quite the same as the guidelines from &lt;a href="https://chris.beams.io/posts/git-commit"&gt;Chris Beams&lt;/a&gt;. Before this step every development team had its own commit message &amp;ldquo;standard&amp;rdquo; and it was hard for developers to lookup some details inside the code base of another team. Almost every team only used one line commits and a few devs used ticket numbers as prefix of the commit message.&lt;/p&gt;</description></item><item><title>Getting more out of Git (german)</title><link>https://fetzi.dev/talk/getting-more-out-of-git-technologieplauscherl/</link><pubDate>Tue, 23 Jan 2018 18:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/getting-more-out-of-git-technologieplauscherl/</guid><description/></item><item><title>Getting rid of view models</title><link>https://fetzi.dev/getting-rid-of-view-models/</link><pubDate>Thu, 24 Aug 2017 21:00:00 +0200</pubDate><guid>https://fetzi.dev/getting-rid-of-view-models/</guid><description>&lt;p&gt;In my &lt;a href="https://fetzi.dev/using-laravels-responsable-interface"&gt;last article&lt;/a&gt; I mentioned that I have to use view models to transform my model data into an array representation that can be used by &lt;a href="http://handlebarsjs.com/"&gt;Handlebars&lt;/a&gt;. If you are using the standard Laravel models and blade as view engine you will be fine with just passing on the eloquent models directly into your view and access properties/methods as needed.&lt;/p&gt;
&lt;p&gt;But if you are consuming multiple differrent data sources that should be presented by a different view engine you need to provide a way to prepare your models for the view.&lt;/p&gt;</description></item><item><title>Using Laravel's Responsable Interface</title><link>https://fetzi.dev/using-laravels-responsable-interface/</link><pubDate>Thu, 17 Aug 2017 22:00:00 +0200</pubDate><guid>https://fetzi.dev/using-laravels-responsable-interface/</guid><description>&lt;p&gt;In the next Laravel version 5.5 a new interface called &lt;code&gt;Responseable&lt;/code&gt; gets introduced. It is a simple interface that defines one method called &lt;code&gt;toResponse&lt;/code&gt; that returns an instance of &lt;code&gt;Illuminate\Http\Response&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This new feature is looking really nice. Especially for the project I&amp;rsquo;m currently working on at work. We use a variety of datasources (php api&amp;rsquo;s, elasticsearch, cache, &amp;hellip;) in our controllers. This leads to a very unstructured and big controller file.&lt;/p&gt;</description></item><item><title>Go for PHP devs</title><link>https://fetzi.dev/talk/go-for-php-devs-viennaphp/</link><pubDate>Tue, 20 Jun 2017 18:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/go-for-php-devs-viennaphp/</guid><description/></item><item><title>From JSON to model instances in PHP</title><link>https://fetzi.dev/from-json-to-model-instances-in-php/</link><pubDate>Mon, 22 May 2017 21:30:00 +0200</pubDate><guid>https://fetzi.dev/from-json-to-model-instances-in-php/</guid><description>&lt;p&gt;JSON is the format I use the most when it comes to data transfer. In almost every case I serialize my data with &lt;code&gt;json_encode&lt;/code&gt; and at some point in time I use &lt;code&gt;json_decode&lt;/code&gt; to get the data back into a somehow structured format.&lt;/p&gt;
&lt;p&gt;For example I&amp;rsquo;m trying to encode/decode a class called &lt;code&gt;Person&lt;/code&gt;. The encoding part is easy, add the &lt;code&gt;JsonSerializable&lt;/code&gt; interface to the model and implement the &lt;code&gt;JsonSerialize&lt;/code&gt; method, call &lt;code&gt;json_encode&lt;/code&gt; on a model instance and you are done.&lt;/p&gt;</description></item><item><title>Developing composer packages locally</title><link>https://fetzi.dev/developing-composer-packages-locally/</link><pubDate>Thu, 06 Apr 2017 08:00:00 +0100</pubDate><guid>https://fetzi.dev/developing-composer-packages-locally/</guid><description>&lt;p&gt;Assume you are creating a new php package that will be shipped via composer/packagist. During development you will use your unit tests for validating the features.&lt;/p&gt;
&lt;p&gt;But at some point in time you need to include your package in a &amp;ldquo;real&amp;rdquo; application to ensure everything is working as expected. To do so you will push your dev branch to github and reference a new repository in your application&amp;rsquo;s &lt;code&gt;composer.json&lt;/code&gt;.&lt;/p&gt;

&lt;script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7DKKQM&amp;placement=fetzidev" id="_carbonads_js"&gt;&lt;/script&gt;

&lt;p&gt;This approach has one big disadvantage: You need to set the &lt;code&gt;minimum-stability&lt;/code&gt; of your project to &lt;code&gt;dev&lt;/code&gt; and this change will pull in the development versions of all referenced packages.&lt;/p&gt;</description></item><item><title>Refactoring to Collections</title><link>https://fetzi.dev/talk/refactoring-to-collections-viennaphp/</link><pubDate>Thu, 23 Mar 2017 18:30:00 +0100</pubDate><guid>https://fetzi.dev/talk/refactoring-to-collections-viennaphp/</guid><description/></item><item><title>Monitoring your Laravel Schedule</title><link>https://fetzi.dev/monitoring-your-laravel-schedule/</link><pubDate>Tue, 14 Mar 2017 20:00:00 +0100</pubDate><guid>https://fetzi.dev/monitoring-your-laravel-schedule/</guid><description>&lt;p&gt;Getting an overview of your scheduled tasks in Laravel and when they run, can be quite tricky. In your console &lt;code&gt;Kernel&lt;/code&gt; class you define your scheduled commands, but you do not get any information about the defined schedules out of the kernel.&lt;/p&gt;

&lt;script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7DKKQM&amp;placement=fetzidev" id="_carbonads_js"&gt;&lt;/script&gt;

&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="nx"&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Schedule&lt;/span&gt; &lt;span class="nv"&gt;$schedule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$schedule&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ExampleCommand&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;everyFiveMinutes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;appendOutputTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;logs/examplecommand.log&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="constructing-the-schedule"&gt;Constructing the Schedule&lt;/h2&gt;
&lt;p&gt;By moving the &lt;code&gt;$schedule-&amp;gt;command&lt;/code&gt; calls into a seperate class you get the possibility to access the schedule information from another context.&lt;/p&gt;</description></item><item><title>Common testing fails - testing the right scope</title><link>https://fetzi.dev/common-testing-fails-testing-the-right-scope/</link><pubDate>Mon, 20 Feb 2017 20:40:00 +0100</pubDate><guid>https://fetzi.dev/common-testing-fails-testing-the-right-scope/</guid><description>&lt;p&gt;When I started with phpspec I often wrote tests for already existing classes. In the last few weeks I read over some test cases from my phpspec beginnings and some of them really scared me. With this series of blog articles I&amp;rsquo;d like to share my learnings on general testing or phpspec specific fails.&lt;/p&gt;

&lt;script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7DKKQM&amp;placement=fetzidev" id="_carbonads_js"&gt;&lt;/script&gt;

&lt;h2 id="an-example"&gt;An example&lt;/h2&gt;
&lt;p&gt;I would like to look at a pretty simple and very common task. Let&amp;rsquo;s fetch some data from an api or a database, transform the data into a DTO and return this object. Let&amp;rsquo;s assume we want to retreive a user object from a database, the corresponding service class code would look like this:&lt;/p&gt;</description></item><item><title>Writing custom phpspec matchers</title><link>https://fetzi.dev/writing-custom-phpspec-matchers/</link><pubDate>Tue, 07 Feb 2017 22:30:00 +0100</pubDate><guid>https://fetzi.dev/writing-custom-phpspec-matchers/</guid><description>&lt;p&gt;Writing tests is sometimes a hard an time consuming task. Especially if you have functionality that cannot be easily tested with your testing framework. phpspec provides an awesome set of so called &lt;a href="http://www.phpspec.net/en/stable/cookbook/matchers.html"&gt;matchers&lt;/a&gt;. But sometimes the predefined matchers are not useful or suitable for implementing a certain test case.&lt;/p&gt;
&lt;p&gt;In this article I will use a very trivial example for a custom matcher. Let&amp;rsquo;s asume you have some sort of random mechanism that outputs an integer in the range [1,5] or a random string from a list. It would be cool to have a matcher to do a call like &lt;code&gt;$this-&amp;gt;something()-&amp;gt;shouldBeAnyOf(1,2,3,4,5)&lt;/code&gt; or &lt;code&gt;$this-something()-&amp;gt;shouldBeAnyOf('string1', 'string2', 'string3')&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Testing with phpspec</title><link>https://fetzi.dev/testing-with-phpspec/</link><pubDate>Tue, 31 Jan 2017 20:00:00 +0100</pubDate><guid>https://fetzi.dev/testing-with-phpspec/</guid><description>&lt;p&gt;Testing a web application can be very challenging. Should tests cover the whole system (frontend, businesslogic, backend, &amp;hellip;) or do you want to test these parts on their own? In this article, I&amp;rsquo;m explaining why I am using phpspec for testing my business logic at the unit level.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve used xUnit for testing over years now, but I often struggled with some recurring code that exists in almost every xUnit test class in the past. There is always this SUT class instance variable lying around, dependencies get injected into a constructor or getting set in some sort of setup method, these dependencies need to be also stored in class properties.&lt;/p&gt;</description></item><item><title>Storing an application's state</title><link>https://fetzi.dev/storing-an-applications-state/</link><pubDate>Thu, 26 Jan 2017 19:00:00 +0100</pubDate><guid>https://fetzi.dev/storing-an-applications-state/</guid><description>&lt;p&gt;Storing the current state of an application is a very difficult task. If you are building an application that is rendering its content on the server side you need to store the application state somehow on the server.&lt;/p&gt;
&lt;p&gt;A good example for the described situation would be if a user is browsing a blog listing on page 2 and wants to comment on a certain post. When he clicks on the &amp;ldquo;add comment&amp;rdquo; link, the server side checks if the user has a valid session started and if not would send him to the login page. After logging in, the user expects to see the blog listing on page 2 with a comment form beneath the blog post preview.&lt;/p&gt;</description></item><item><title>Talks</title><link>https://fetzi.dev/talks/</link><pubDate>Thu, 26 Jan 2017 19:00:00 +0100</pubDate><guid>https://fetzi.dev/talks/</guid><description/></item><item><title>About me</title><link>https://fetzi.dev/about/</link><pubDate>Sun, 01 Jan 2017 19:00:00 +0100</pubDate><guid>https://fetzi.dev/about/</guid><description>&lt;p&gt;Hey, my name is Johannes Pichler. I&amp;rsquo;m working as a Team Lead @ &lt;a href="https://wimbergergruppe.at/"&gt;Wimberger Management GmbH&lt;/a&gt; in Lasberg, Upper Austria.&lt;/p&gt;
&lt;div class="flex flex-col md:flex-row gap-4"&gt;
 &lt;img src="https://fetzi.dev/images/about2.jpg" class="w-full md:w-1/2 object-cover max-w-none h-auto" alt="Johannes @ Dutch PHP Conference 2026"&gt;
 &lt;img src="https://fetzi.dev/images/about.png" class="w-full md:w-1/2 object-cover max-w-none h-auto pr-4" alt="Johannes @ We are Developers World Congress 2018"&gt;
&lt;/div&gt;
&lt;p&gt;In my spare time I love to contribute to open source projects like &lt;a href="https://laravel.io"&gt;laravel.io&lt;/a&gt; and other PHP/Laravel related projects.&lt;/p&gt;
&lt;p&gt;Based on former experiences I force my team mates and myself to follow a test-driven development approach and to use supportive tools as efficient as possible.&lt;/p&gt;</description></item><item><title>Privacy &amp; Imprint</title><link>https://fetzi.dev/privacy/</link><pubDate>Sun, 01 Jan 2017 19:00:00 +0100</pubDate><guid>https://fetzi.dev/privacy/</guid><description>&lt;p&gt;This page gives you relevant privacy information and of course the imprint for using fetzi.dev.&lt;/p&gt;
&lt;h2 id="what-data-is-collected"&gt;What data is collected?&lt;/h2&gt;
&lt;p&gt;If you sign up for the newsletter on the blog your e-mail address gets stored.&lt;/p&gt;
&lt;h2 id="how-is-this-data-used"&gt;How is this data used?&lt;/h2&gt;
&lt;p&gt;Your e-mail address is used to send you a newsletter with the latest blog articles. This is done by using the MailChimp e-mail service. You can find the privacy policy from MailChimp by following &lt;a href="https://mailchimp.com/legal/privacy/"&gt;this link&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>HTTP/2 NOW!</title><link>https://fetzi.dev/http2-now/</link><pubDate>Wed, 03 Feb 2016 10:12:00 +0100</pubDate><guid>https://fetzi.dev/http2-now/</guid><description>&lt;p&gt;Yesterday I heard a great keynote about the current status of HTTP/2 at the Topconf conference in Linz, Austria. In the evening I tried to upgrade my website to use HTTP/2.&lt;/p&gt;
&lt;p&gt;Amazingly, I was able to update my webserver within &lt;strong&gt;2 or 3 minutes&lt;/strong&gt; by executing one software update command and one small configuration change in my nginx config.&lt;/p&gt;

&lt;script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7DKKQM&amp;placement=fetzidev" id="_carbonads_js"&gt;&lt;/script&gt;

&lt;h2 id="nginx-version-upgrade"&gt;NGINX Version Upgrade&lt;/h2&gt;
&lt;p&gt;To be able to use HTTP/2 you need at least nginx version 1.9.5 (mine was at 1.6.x). This update can be easily executed by calling
&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install nginx&lt;/code&gt;.&lt;/p&gt;</description></item></channel></rss>