nyamsprod.com

Pas un seul de vos ancêtres n'est mort jeune. Ils ont tous copulé au moins une fois.

Always make your constructor private when using value object

Every PHP developer has learned that to instantiate an object since PHP5 one should use PHP’s magic method __construct. But what most developers do not realise is that for a better DX usage, using by default this magic method should be avoided if what you are about to instantiate is not a service but an entity, a data transfer object or a value object.

In the beginning

For the purpose of this article we will work with a putative Example\Geolocation object but it could be whatever you want as long as it is a value object.

Intuitively if you need to create such object you will write the following code

As you can see the fully typed class and its constructor are straightforward. However, this is where the devil starts to show its evil head. While this object will fully do what you expect it to do, you still need to validate the coordinates to be sure that on instantiation the object is valid.

You will want to:

  • create a filterLatitude private method to make sure:
    • the latitude value does not exceed the -90 and +90 range value
    • of if it does you capped that value
  • create a filterLongitude private method to make sure:
    • the longitude value does not exceed the -180 and +180 range value
    • of if it does you wrapped that value

Which means that your constructor becomes something along this line:

Then came unexpected constraints

But then, business comes to you and says that they will get the coordinates in form of degrees and decimal minutes. You have 2 choices, you either create a second class which use degrees, an interface to interact with the current object and a full test suite to the make your developer life more miserable or you can add a named constructor to your object.

For those who do not know what a named constructor is, it is a public static method designed as a small factory to create a new instance of the object to which it is attached to. It is PHP substitution to method overloading which does not exist in PHP.

In our example in means that you end up with something along this line:

Decoupling object instantiation from object usage.

Everything works, and you are happy about yourself. However now you effectively have two ways to instantiate your object and none can take precedence above the other to be declare as the one and only true way to instantiate your object.

As a matter of fact from an outsider point of view, he/she do not care how the object is declare as long as it is valid. The only solution to this is to again rewrite the class as follow:

So now we have an object with a better DX

and with the following added values to named but a few:

  • Both calls can generate a valid Geolocation object which is self validated and simpler to reason with.
  • You removed from public API the ability to being able to call twice the constructor (unless you start using reflection).
  • Your object is extensible enough to be able to be instantiate with meaningful name by supporting other named constructors.

For instance, you can easily add more named constructor depending on new business requirements without having to refactor your application core.

Known pitfalls

Named constructors should never be generics. I often see named constructor called create or make with too much business logic behind them. If we use our Geolocation example, the following is a bad use of the named constructor.

Behind the scene the make method tries other named constructors until it finds the « correct one » or fails. The problem with this sort of construction is that it is difficult to reason with it and it may lead to false positive passing through your tests and business requirements. Your intent should be as clear as your named constructor.

Another pitfall is to make the static named constructor arguments to broad.

The RequestInterface has too many properties that it is virtually impossible to know which value is effectively used.

A better solution would be to use:

I have purposely left the request body parsing outside of the method which means that nothing can now prevent you from using the same named constructor from a Symfony\HttpFoundation\Request object.

TL;DR

Whenever you can please favour named constructor usage and mark PHP default constructor as inaccessible from the public API. While it may at first seems odd or perceived as adding more constraints. It effectively makes your code more flexible and reduce the complexity of your object usage.

A class to generate URI Template in PHP

Ever since I released the League\Uri package I always wanted to add an URI template class in it. But I never felt having to write one because I never used the URI template feature myself and the only time I had to do it I used the implementation that came bundle with the Guzzle library. It turns out that Guzzle's maintainers have decided to drop their own implementation for the next Guzzle major release which is in beta release as of this writing. And since I was in need of such feature I finally got around to add the functionality to the League\Uri library.
In this post I would like to introduce the League\Uri\UriTemplate, the main new feature of League\Uri 6.1.

For starter, like most of the other classes included in the library the League\Uri\UriTemplate follows a known RFC which is RFC6750. This RFC describes how to interpolate and expand a template so that its result is a fully compliant URI as described in RFC3986.

Using the template

While the core expansion logic is based on the Guzzle 6.5 implementation, its public facing API is a combination of the main Python and Java implementations.

The advantage of this public API versus the one that was used in the Guzzle implementation is that with one object you can create an infinite number of URI instance by just changing your variables on each UriTemplate::expand calls. The template is parsed only once on instantiation.

Using the variables

Another nit trick is that you can define default variables on the constructor

In the example above, the version variable is applied without you having to fill it in the when calling the expand method. Keep in mind, that to give you more flexibility the default variables can still be overwritten if the same variables are used with the expand method.

Interoperability

To enable better interoperability with other implementations in other languages, the class was design using an independent URI template test suite for expansion conformance. So while updating the implementation I made sure to always pass this independent test.

In order to do so, under the hood, the class does lots of validations on instantiation and when using the expand method to make sure:

  • the template syntax is conformed to the RFC;
  • the variable syntax is not forbidden by the RFC;
  • the resulting expansion produces an RFC compliant URI instance;

Some optimisations are also introduced to lazy cache template expansion in case no variable and/or no expression are presents.

Alternative

If you already worked with URI Template in PHP you probably came across the rize/uri-template library. The main differences between both implementations apart from the public API are that the latter offers features that are not covered by the RFC, and thus, are not present in this class. Namely an extraction feature which returns the possible variables used in a valid URI and an extension to add the ability to expand URI using http_build_query type parameters.

Final note

The League/Uri is an open source project with a MIT License so contributions are more than welcome and will be fully credited. These contributions can be anything from reporting an issue, requesting or
adding missing features or simply improving or correcting some typo on the documentation website.

And if you appreciate the work and the effort put in the library you can also sponsor me to enable me to continue to fix and improve the library.

How to make your code more flexible

So I had a little exchange on the internet with the developers from @spatie_be. I’ve just discovered that they have a policy to never use final, private and void in their packages and when I ask why the answer was to enable flexibility in package usage.

Suffice to say I don’t agree with this specific rule and even more so once I knew the reasoning behind its existence.

To illustrate why it is a bad guideline let’s assume a PHP package containing the following class

Because this package is great and gets high praises from the internet of things it skyrocks on packagist and is downloaded so much so that someone picks it up and believe he/she can make it great again… no pun intended. How ? Well following said guideline he/she does the following :

Some folks stumble upon the new awesome package and decide to use it. Now without knowing they are all in a huge mess why ?

  • If Foobar\Great updates its codebase and remove the Great::internalMagic method because why not ? Awesome is broken;
  • If Foobar\Great adds a doMore method which returns something other than a int, Awesome is broken;
  • If self::MAGIC_NUMBER constant is called in Great::internalMagic  instead of static::MAGIC_NUMBER the relation between both packages is broken;

Any non BC break action, according to semver, taken by the Foobar\Great will result in Sunday\Dev\Awesome having to check and review if nothing is broken and/or if its test suite is still working. I bet that at some point the Sunday\Dev maintainer will either open issues or completely fork the parent package in hope to resolve his own reported issues.

The root of all this is that both classes are so deeply bound to each others that their real API include public but also protected methods, properties and/or constants. Nothing can be changed or remove without triggering a BC break. You wanted flexibility you ended up with very tight coupling.

All that could have been avoided if the first class had been made final.

So we would have had:

And:

If Foo\Great is really as great as everyone think you can even improve its code and convert it into an interface if the need arise and add an implementation using a final class.

Bottom line, because final classes are closed to extensions they are way more flexible and less error prone as one may think at first glance. They provide a great starting point to improve control and maintenance over your code by embracing the composition over inheritance concept.
That does not mean that inheritance is bad, but before using it on a concrete class ask yourself if the end result is not more harmful than creating a final class.

While some will view my examples as too simplistic to favor my views and others may think that no good developer would do that or that I’m ranting on spatie packages let me end my post by reminding you the following:

First of all, I believe the spatie open source packages are great and I even contribute to some of them because like some of you I use some of their packages. Secondly, you’d be surprise how many other popular packages fail into this simple trap by overusing direct inheritance or other techniques like traits. Last but not least, I, myself, have been guilty of this in the past but I’ve since then learned my lesson and try to course correct things where and when I can and so should you 😉

Using Doctrine Collections to improve CSV filtering

I’m happy to announce the release of League CSV – Doctrine Collection Bridge version 1.0.0. The new package under the bakame namespace is an extension to League\Csv which takes advantage of Doctrine Collections features to better manipulate CSV documents.

CSV Filtering

When working with imported CSV documents it always comes down to filtering and querying data from the document to apply some business logic to them. One of the often suggested method is to import the CSV document data into a RBMS and then use its filtering capabilities to process the data. While this might be tempting it also means wasting  times in thinking about tables structure and resource availability  while often you only want to consume your data and move on to other tasks.

League Csv Statement

For that reason I always prefer using the League\Csv\Statement class. The class uses closures and callables to filter the CSV document as shown below:

Doctrine Collection Criteria

While using the League\Csv\Statement is straightforward, building the correct closure/callable for a given filtering can become a daunting task. Luckily for us, the people behind the Doctrine project have long since resolve this issue with their powerful expression API by introducing the Doctrine\Common\Collections\Criteria class.

Using the Criteria class you can rewrite my previous example as follow:

Which may sound a bit overcomplicated for a simple query but ease debugging and maintenance as filtering requirements become more complex. The expression API is similar to SQL statements so they are easy to understand and use.

From Doctrine Criteria to Csv Statement

This package enables converting any Doctrine\Common\Collections\Criteria object into a League\Csv\Statement object allowing using Doctrine Expression API on any CSV document.

From  a Csv Reader to a Doctrine Collection

But that’s not all the package also comes bundle with an implementation of Doctrine Collection, the Bakame\Csv\Extension\RecordCollection that can turn any League\Csv\Reader or League\Csv\ResultSet into a Doctrine Collection.

Final notes

Depending on your CSV size you may prefer using the Bakame\Csv\Extension\RecordCollection class instead of the League\Csv\ResultSet as the latter uses PHP Iterator and streaming capabilities to reduce memory usage.

Last but not least

The League CSV – Doctrine Collection Bridge is an open source project with a MIT License so contributions are more than welcome and will be fully credited. These contributions can be anything from reporting an issue, requesting or adding missing features or simply improving or correcting some typo on the documentation website.

League\Csv 9 is out

Attention: Les informations de ce billet sont susceptibles d'être obsolètes car vieux de plus 2 ans.

Warning: The information you are reading may be obsolete, this post was published more than 2 years ago.

I’m happy to announce that League\Csv version 9.0 has been released. This is a new major version which requires PHP7 (HHVM support is dropped). This new version focuses on making the code more SOLID while enabling better CSV document manipulation.

What’s new

The library comes bundle with two new stream filters.

League\Csv\CharsetConverter which converts on the fly your CSV document from one charset to another.

League\Csv\RFC4180Field which format on reading or on writing CSV field to be RFC4180 compliant by working around PHP’s bugs.

What’s changed

At the beginning, this library was just a set of 2 classes Reader and Writer that made it painless to interact with CSV documents. But as features were added those classes inherited too many responsabilities making them more difficult to use. By taking advantage of modern PHP features both classes API have been changed and/or improve and their responsabilities restricted:

– The Writer connection primary responsability is to add records to the CSV records;
– The Reader connection primary responsability is to access all CSV records;

Everything else (converting, querying) has been delegated to new classes.

Fetching CSV records

Previously, accessing the document records was done using the Reader object and different methods (ie: Reader::fetchAll, Reader::fetchAssoc, Reader::each, Reader::fetch). In version 9,  you will only need the newly introduced Reader::getRecords method. As such accessing CSV records is easier than before.

Of note, unlike previous version, the Reader now automatically strip the BOM sequence if present.

Querying the CSV document

Searching the CSV document has been decoupled from the Reader class. This means that if you are processing multiple CSV documents you don’t need to repeat your selection on each CSV object or on the same CSV if you need to make multiple queries on it.

Converting the CSV document

Starting with version 9, only the Reader class can be converted or serialized. XML and HTML conversion is done using dedicated classes. For instance, to convert your CSV records to XML you are now required to use the League\Csv\XMLConverter. Not only, This new class improves how the conversion is done by adding more configuration settings but it can be used for any tabular data like the result of a PDO::Statement.

Upgrading to League\Csv 9

As you would expect, this is only a quick view of the new features and changes this new version offers. You should head to the documentation website for a full explanation about the new version capabilities.

Even though this package introduces many backward compatibility breaks. I’m confident that upgrading to League\Csv 9 won’t require changes for most users. If you do encounter an issue the upgrading guide should help you ease the transition path.

Last but not least

The League\Csv is an open source project with a MIT License so contributions are more than welcome and will be fully credited. These contributions can be anything from reporting an issue, requesting or adding missing features or simply improving or correcting some typo on the documentation website.

League Uri decoupled

Attention: Les informations de ce billet sont susceptibles d'être obsolètes car vieux de plus 2 ans.

Warning: The information you are reading may be obsolete, this post was published more than 2 years ago.

Last month the release of League\Uri version 5 was announced using a simple tweet.

While I pointed out in the tweet that this new release is PHP7 only, the main selling point of this new version is the package conversion into a meta-package. (suite…)

League CSV now supports streams

One of the long requested feature to be added to the CSV was stream supports. Starting with League\Csv 8.2, the wait is over, you’ll be able to manipulate CSV objects created from a resource stream. As an example you can now do this

Because your CSV object is created using a resource stream you will not be able to use the CSV stream filter capabilities but since you are already using a resource stream, it does not matter because you can directly use PHP’s stream filter capabilities like shown below.

As you can see supporting streams enables more interactions with CSV documents while still using a familiar API.

Final note

The League CSV is an open source project with a MIT License so contributions are more than welcome and will be fully credited. These contributions can be anything from reporting an issue, requesting or adding missing features or simply improving or correcting some typo on the documentation website.

 

How Many PSR-7 Implementations Exist? No really

Attention: Les informations de ce billet sont susceptibles d'être obsolètes car vieux de plus 2 ans.

Warning: The information you are reading may be obsolete, this post was published more than 2 years ago.

Paul M Jones wrote a blog post around PSR-7 implementations and even though his response was zero I was intrigued by packagist results. Since I am maintaining an implementation of PSR-7 UriInterface, I was curious to see despite his opinion how many different implementations really exists and their quality. (suite…)

League Uri parser

Attention: Les informations de ce billet sont susceptibles d'être obsolètes car vieux de plus 2 ans.

Warning: The information you are reading may be obsolete, this post was published more than 2 years ago.

If you ever worked a lot with URLs you know that the first step before manipulating them is being able to correctly parse them into their different components. In PHP, this is accomplished using the parse_url function. But parse_url contains many bugs and shortcomings like:

Theses issues are known to PHP’s internals which is trying to solve them by introducing a new URL parser, hopefully for PHP7.2. In the meantime, if correctly parsing the URL is crucial for you the PHP League is proud to announce the release of the League URI Parser.

The League URI Parser only works in PHP7+ and required the intl extension to correctly parse RFC3987 URL’s. Here’s a simple example of how this parser works.

As you can see, the parser returns an hash similar to parse_url so switching between them in your application should be straight forward.

Although the returned hash is similar, there are some key differences between this parser and parse_url. The documentation goes into more in depth comparison between both parser but here’s the main points:

  • The parser always returns an array containing all the URL components;
  • The parser makes a distinction between an empty component whose value is the empty string and an undefined one whose value is null;
  • In case of an error, the parser will trigger an InvalidArgumentException instead of just returning false;

The League URI parser also provide a method to validate any host string. This method is capable of validating a:

  • Host as an IP string (IPv4 and IPv6)
  • Host as registered name

Regardless of the parser you will end up using for your next application, do keep in mind that parsing and validating an URL are two different actions. For instance, if you go back to the first example provided, the returned URL is invalid against the rules of a data URL scheme, but parsing was correct.

Final note

The League Uri Parser is an open source project with a MIT License so contributions are more than welcome and will be fully credited. These contributions can be anything from reporting an issue, requesting or adding missing features or simply improving or correcting some typo on the documentation website.

Formatting a Date in PHP the right way

Attention: Les informations de ce billet sont susceptibles d'être obsolètes car vieux de plus 2 ans.

Warning: The information you are reading may be obsolete, this post was published more than 2 years ago.

Lately I’ve been doing some translation in PHP and one of the main issue was to translate a date into a human readable string according to the user settings.

Historically, in PHP people have been using a conjunction of strftime and setlocale to achieve this goal. like in the following example:

This example has many problems:

The string you have to give setlocale depends on the locale that exists on your platform. For instance on Ubuntu if I specify fr_FR instead of fr_FR.UTF8 the result may differ depending on the installed locales. You could come up with a detection function prior to use setlocale but then you add even more burden in the locale detection.

Another problem is that if you only want to convert one specific date and nothing else the code should then be:

As you can see, setlocale affect your environment so using it should not be the recommend way. So what is the alternative ?

Well since PHP5.5 the Intl extension introduce the IntlDateFormatter::formatObject static method. This method addresses all the previous usage limitations. here’s an example:

  • The method expects a DateTime object which means that the object timezone is taken into account. This was not the case with strftime.
  • The formatting string follows the UCI standard which make them understandable not only by PHP users.
  • You can specify the locale per function call so no more changing your environment inside your code.
  • The locale string is also platform independent. Which means that no extra prefix or requirement is needed to make this code works.

The only drawback that I could spot was that DateTimeImmutable also introduced in PHP5.5 is not yet supported by the method despite a bug for its support being filled since 2013.

To put it simple, if you need to format a Date in PHP please use the Intl extension whenever you can.