{"id":1421,"date":"2015-02-20T04:59:37","date_gmt":"2015-02-20T03:59:37","guid":{"rendered":"https:\/\/www.entropywins.wtf\/blog\/?p=1421"},"modified":"2019-07-21T07:04:56","modified_gmt":"2019-07-21T06:04:56","slug":"phpcs-and-phpmd-my-experiences","status":"publish","type":"post","link":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/","title":{"rendered":"PHPCS and PHPMD: my experiences"},"content":{"rendered":"<p>PHPCS (<a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer\">PHP Code Sniffer<\/a>) detects violations against a specified coding standard. PHPMD (<a href=\"http:\/\/phpmd.org\/\">PHP Mess Detector<\/a>) is a similar tool, though with more of a focus on metrics. In this post I&#8217;ll go over how I started using them, and what I learned in the process.<\/p>\n<p>They are both very useful in that they can automatically detect a variety of things such as unused variables, misplaced brackets and overly long methods. These are things looked out for during code review, yet this takes time, and is quite error prone. I often find myself running PHPStorms &#8220;code analysis&#8221; to find newly introduced dead code which up till that point had gone undetected.<\/p>\n<p>I&#8217;ve known about tools such as PHPCS and PHPMD for quite some time, though never got round to actually using them. Then some time ago, I stumbled across a recently created <a href=\"https:\/\/github.com\/wikimedia\/mediawiki-tools-codesniffer\">PHPCS ruleset for the MediaWiki coding style<\/a>. Since we&#8217;re using the MediaWiki coding style in most of our PHP projects at WMDE (<a href=\"https:\/\/wikimedia.de\">Wikimedia Deutchland<\/a>), I started looking into how we could make use of this ruleset.<\/p>\n<p>The first step I took was taking the already created ruleset for the MediaWiki coding style and trying it out against a small project that&#8217;s essentially done and sees very little development activity: <a href=\"https:\/\/github.com\/wmde\/Diff\">the Diff library<\/a>. Apart from a few misplaced spaces, which where quickly fixed, it worked right away &#8211; yay. Step two was to actually look at the ruleset in more detail.<\/p>\n<p>I realized that several exceptions to the rules could be removed, since the Diff library is more strict about things than the MediaWiki software. After removing those, I started looking for other things that could easily be added to the ruleset. I ended up looking through the various PHPCS so called <a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer\/tree\/master\/CodeSniffer\/Standards\">coding standards<\/a>, and picked rules matching the Diff guidelines from several, which where then added to <a href=\"https:\/\/github.com\/wmde\/Diff\/blob\/master\/phpcs.xml\">my own ruleset<\/a>.<\/p>\n<p>One thing that I was keen to add where limitations on code complexity. PHPCS allows setting a maximum nesting level, and upperbounding the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Cyclomatic_complexity\">Cyclomatic Complexity<\/a> of methods. That&#8217;s great, though hardly covers all metrics I want. You can still create a 10k ELOC class with 50 fields that couples to 100 classes without the tool shouting at you. I did some research on the other code analysis tools for PHP, and figured PHPMD was the best fit.<\/p>\n<p>As with PHPCS, I went through all the <a href=\"http:\/\/phpmd.org\/rules\/index.html\">PHPMD rules<\/a>, to determine which ones where applicable to my usecase, and put them in <a href=\"https:\/\/github.com\/wmde\/Diff\/blob\/95222719760889e1559661d8d09f696f10248a57\/phpmd.xml\">my rule file<\/a>.<\/p>\n<p>At this point I could validate the Diff code against both the PHPCS and PHPMD rules by running<\/p>\n<pre class=\"lang:default decode:true\">phpcs src\/* tests\/* --standard=phpcs.xml --extensions=php -sp\nphpmd src\/ text phpmd.xml<\/pre>\n<p>The -p option for PHPCS shows the progress with a pile of dots, much like done in PHPUnit. Unfortunately PHPMD has no such feature. The -s option prints the names of the rules in the report. This is very useful when you do not know the rules yet, and are trying to find out which ones are applicable for your project. If the name of the rule is included, rather than the error message, you don&#8217;t need to hunt for it before you&#8217;re able to disable it or change its configuration.<\/p>\n<p>Next I looked into how to run this on TravisCI, so new violations would not get introduced. The most obvious thing to do is of course to simply look at how existing projects are doing this. In doing so, I ran into a Composer feature I had not used before: <a href=\"https:\/\/getcomposer.org\/doc\/articles\/scripts.md\">Composer scripts<\/a>. Diff now has <a href=\"https:\/\/github.com\/wmde\/Diff\/blob\/95222719760889e1559661d8d09f696f10248a57\/composer.json#L45-L58\">these scripts<\/a>, which allows me to simply run &#8220;composer ci&#8221; to run all tests and code style checks that are also run on TravisCI.<\/p>\n<p>With the basic work done for the Diff library, I proceeded to add the rulesets I created to the Wikibase DataModel component. This component is bigger, though still reasonably small, and is more active development wise. Like Diff, it is quite clean and mostly adheres to the more strict and recent code style and complexity expectations we have at WMDE. This is why I figured Wikibase DataModel to be a good choice to test the rulsets and general setup against.<\/p>\n<p>Right away several rules where found that had to be removed or configured differently, since they prohibited things we&#8217;re actually fine with, or in some cases demand. (There are many rules in PHPCS that conflict with each other, so you will never be able to enable all rules.) An example of this is the PHPMD TooManyMethods rule, which I figured was just about public non-getter-setter methods. Apparently it also includes private methods as well, which makes the rule a lot less useful in my opinion (see <a href=\"https:\/\/github.com\/phpmd\/phpmd\/issues\/248\">GitHub issue<\/a>). Another thing I ran into is that we have test methods named like testGivenInvalidLanguage_exceptionIsThrown, which violates the CamelCase rule. I filed an <a href=\"https:\/\/github.com\/phpmd\/phpmd\/issues\/251\">issue for this<\/a>, and have a <a href=\"https:\/\/github.com\/phpmd\/phpmd\/pull\/257\">preliminary pull request<\/a> open as well.<\/p>\n<p>I&#8217;ve now started using these tools for several projects, including some in which there where a lot of deviations from the standard. PHPCS comes with a &#8220;<a href=\"https:\/\/github.com\/squizlabs\/PHP_CodeSniffer\/wiki\/Fixing-Errors-Automatically\">PHP Code Beautifier and Fixer<\/a>&#8221; tool that allows you to quickly fix whole classes of certain violations. For instance, your coding style might dictate a line at the end of each file. This tool can automatically add one wherever one is missing, and remove additional ones where there is more than one.<\/p>\n<p>In legacy projects it can be hard to enable these tools and have them prevent regressions against your coding standard. If you have a lot of code violating your own standard, you need to fix it before you can enable the associated rules. This can be a lot of work, and not something you want to do in one go. You might not even want to do it at all at places, for instance parts of your codebase that are not actively developed. You can simply omit rules that are presently violated, though that likely leaves you with a much reduced ruleset, forcing you to still pay a lot of attention to prevent new violations of the omitted rules from being added. Alternatively you can have the whole rulset, and simply not have your CI server use it. The danger with this is obvious, and as with not running tests on your CI and accepting some are broken, a lot of vigilance is needed to prevent regressions, especially in teams.<\/p>\n<p>In one legacy project where I&#8217;ve introduced these tools, I went with a combined approach. This project has two rulsets for both PHPCS and PHPMD: a strict one, and a reduced one that works with the legacy code. In this project there already was a devision between old and new code. The old code was in one directory using a custom autoloader, while the new one was in <code>src\/<\/code>, using the Composer PSR-4 autoloader. This made it trivial to run the strict rules against the code in <code>src\/<\/code>, and new things added there, while running the more relaxed ones against the old directory.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PHPCS (PHP Code Sniffer) detects violations against a specified coding standard. PHPMD (PHP Mess Detector) is a similar tool, though&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[7],"tags":[363,306,362,156,181,195,360,361,197,364,215,317,318,336],"class_list":["post-1421","post","type-post","status-publish","format-standard","hentry","category-programming","tag-code-quality","tag-composer","tag-continuous-integration","tag-mediawiki","tag-open-source","tag-php","tag-phpcs","tag-phpmd","tag-planet-wikimedia","tag-quality-assurance","tag-refactoring","tag-wikibase","tag-wikibase-datamodel","tag-wmde"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>PHPCS and PHPMD: my experiences - Blog of Jeroen De Dauw<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PHPCS and PHPMD: my experiences - Blog of Jeroen De Dauw\" \/>\n<meta property=\"og:description\" content=\"PHPCS (PHP Code Sniffer) detects violations against a specified coding standard. PHPMD (PHP Mess Detector) is a similar tool, though&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog of Jeroen De Dauw\" \/>\n<meta property=\"article:published_time\" content=\"2015-02-20T03:59:37+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-07-21T06:04:56+00:00\" \/>\n<meta name=\"author\" content=\"Jeroen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/JeroenDeDauw\" \/>\n<meta name=\"twitter:site\" content=\"@JeroenDeDauw\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeroen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\"},\"author\":{\"name\":\"Jeroen\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"headline\":\"PHPCS and PHPMD: my experiences\",\"datePublished\":\"2015-02-20T03:59:37+00:00\",\"dateModified\":\"2019-07-21T06:04:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\"},\"wordCount\":1167,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"keywords\":[\"Code Quality\",\"composer\",\"Continuous Integration\",\"MediaWiki\",\"Open Source\",\"PHP\",\"PHPCS\",\"PHPMD\",\"Planet Wikimedia\",\"Quality Assurance\",\"Refactoring\",\"Wikibase\",\"Wikibase DataModel\",\"WMDE\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\",\"url\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\",\"name\":\"PHPCS and PHPMD: my experiences - Blog of Jeroen De Dauw\",\"isPartOf\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#website\"},\"datePublished\":\"2015-02-20T03:59:37+00:00\",\"dateModified\":\"2019-07-21T06:04:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.entropywins.wtf\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PHPCS and PHPMD: my experiences\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#website\",\"url\":\"https:\/\/www.entropywins.wtf\/blog\/\",\"name\":\"Entropy Wins\",\"description\":\"A blog on Software Architecture, Design and Craftsmanship\",\"publisher\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.entropywins.wtf\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7\",\"name\":\"Jeroen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g\",\"caption\":\"Jeroen\"},\"logo\":{\"@id\":\"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/jeroendedauw\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/JeroenDeDauw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"PHPCS and PHPMD: my experiences - Blog of Jeroen De Dauw","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/","og_locale":"en_US","og_type":"article","og_title":"PHPCS and PHPMD: my experiences - Blog of Jeroen De Dauw","og_description":"PHPCS (PHP Code Sniffer) detects violations against a specified coding standard. PHPMD (PHP Mess Detector) is a similar tool, though&hellip;","og_url":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/","og_site_name":"Blog of Jeroen De Dauw","article_published_time":"2015-02-20T03:59:37+00:00","article_modified_time":"2019-07-21T06:04:56+00:00","author":"Jeroen","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/JeroenDeDauw","twitter_site":"@JeroenDeDauw","twitter_misc":{"Written by":"Jeroen","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#article","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/"},"author":{"name":"Jeroen","@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"headline":"PHPCS and PHPMD: my experiences","datePublished":"2015-02-20T03:59:37+00:00","dateModified":"2019-07-21T06:04:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/"},"wordCount":1167,"commentCount":1,"publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"keywords":["Code Quality","composer","Continuous Integration","MediaWiki","Open Source","PHP","PHPCS","PHPMD","Planet Wikimedia","Quality Assurance","Refactoring","Wikibase","Wikibase DataModel","WMDE"],"articleSection":["Programming"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/","url":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/","name":"PHPCS and PHPMD: my experiences - Blog of Jeroen De Dauw","isPartOf":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#website"},"datePublished":"2015-02-20T03:59:37+00:00","dateModified":"2019-07-21T06:04:56+00:00","breadcrumb":{"@id":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.entropywins.wtf\/blog\/2015\/02\/20\/phpcs-and-phpmd-my-experiences\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.entropywins.wtf\/blog\/"},{"@type":"ListItem","position":2,"name":"PHPCS and PHPMD: my experiences"}]},{"@type":"WebSite","@id":"https:\/\/www.entropywins.wtf\/blog\/#website","url":"https:\/\/www.entropywins.wtf\/blog\/","name":"Entropy Wins","description":"A blog on Software Architecture, Design and Craftsmanship","publisher":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.entropywins.wtf\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/4e2ef14f2ca7dc3a0ac137d1692b66b7","name":"Jeroen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d62e6b5b8e332335cf17854fac850d9c70ba367c4692872613c3110ebd4e009b?s=96&d=mm&r=g","caption":"Jeroen"},"logo":{"@id":"https:\/\/www.entropywins.wtf\/blog\/#\/schema\/person\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/in\/jeroendedauw\/","https:\/\/x.com\/https:\/\/twitter.com\/JeroenDeDauw"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p74TBF-mV","jetpack-related-posts":[{"id":1466,"url":"https:\/\/www.entropywins.wtf\/blog\/2015\/09\/30\/phpmd-toomanypublicmethods-and-allow-underscores\/","url_meta":{"origin":1421,"position":0},"title":"PHPMD: TooManyPublicMethods and allow-underscores","author":"Jeroen","date":"2015-09-30","format":false,"excerpt":"Earlier this month, PHPMD 2.3 was released. It contains several new features, including two that I added primarily for use in Wikibase, the software behind Wikidata. For a more general post on PHPMD and style checks in PHP, see PHPCS and PHPMD: my experiences. New rule: TooManyPublicMethods When I first\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2101,"url":"https:\/\/www.entropywins.wtf\/blog\/2018\/01\/20\/php-project-template\/","url_meta":{"origin":1421,"position":1},"title":"PHP project template","author":"Jeroen","date":"2018-01-20","format":false,"excerpt":"Want to start a new PHP project? Perhaps yet another library you are creating? Tired of doing the same lame groundwork for the 5th time this month? Want to start a code kata and not lose time on generic setup work? I got just the project for you! Edit: there\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/01\/php.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/01\/php.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/01\/php.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/01\/php.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.entropywins.wtf\/blog\/wp-content\/uploads\/2018\/01\/php.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":1453,"url":"https:\/\/www.entropywins.wtf\/blog\/2015\/08\/11\/wikibase-datamodel-services\/","url_meta":{"origin":1421,"position":2},"title":"Wikibase DataModel Services","author":"Jeroen","date":"2015-08-11","format":false,"excerpt":"I'm happy to announce the immediate availability of a new Wikibase library: Wikibase DataModel Services (which I'll in this blog post refer to as DMS). Rationale behind the library The main motivation for introducing this new library is to reduce technical debt and draw more solid architectural boundaries in the\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1287,"url":"https:\/\/www.entropywins.wtf\/blog\/2014\/03\/20\/status-of-the-new-wikibase-deserialization-code\/","url_meta":{"origin":1421,"position":3},"title":"Status of the new Wikibase (de)serialization code","author":"Jeroen","date":"2014-03-20","format":false,"excerpt":"A quick update on the status of the new serialization and deserialization code for Wikibase, the software behind Wikidata. For a long time now, we've had two serialization formats. One intended for external usage, and one intended for internal usage. The former one is the format our web API uses.\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/www.entropywins.wtf\/blog\/category\/software\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1401,"url":"https:\/\/www.entropywins.wtf\/blog\/2014\/09\/02\/wikibase-datamodel-1-0\/","url_meta":{"origin":1421,"position":4},"title":"Wikibase DataModel 1.0","author":"Jeroen","date":"2014-09-02","format":false,"excerpt":"I'm happy to announce the 1.0 release of Wikibase DataModel.\u00a0Wikibase DataModel is the canonical PHP implementation of the Data Model at the heart of the Wikibase software. This is a big release which has been some time in the making, even though many additions have been split of and included\u2026","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/www.entropywins.wtf\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1165,"url":"https:\/\/www.entropywins.wtf\/blog\/2013\/12\/23\/wikibase-datamodel-released\/","url_meta":{"origin":1421,"position":5},"title":"Wikibase DataModel released!","author":"Jeroen","date":"2013-12-23","format":false,"excerpt":"I\u2019m happy to announce the 0.6 release of Wikibase DataModel. This is the first real release of this component. DataModel? Wikibase is the software behind Wikidata.org. At its core, this software is about describing entities. Entities are collections of claims, which can have qualifiers, references and values of various different\u2026","rel":"","context":"In \"Component\"","block_context":{"text":"Component","link":"https:\/\/www.entropywins.wtf\/blog\/tag\/component\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/1421","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/comments?post=1421"}],"version-history":[{"count":4,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/1421\/revisions"}],"predecessor-version":[{"id":2643,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/posts\/1421\/revisions\/2643"}],"wp:attachment":[{"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/media?parent=1421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/categories?post=1421"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.entropywins.wtf\/blog\/wp-json\/wp\/v2\/tags?post=1421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}