DEV Community

Christian
Christian

Posted on • Originally published at en.globalelements.ch on

PHP 8 is amazing. I still prefer C#.

With the end of 2020 came the release of PHP 8 and also the release of .Net 5.0.0, the former also being discussed on HackerNews (and here, here or here). I write a lot of code in PHP, while frequently using C# with .Net Framework and recently more often .Net Core – maybe half/half. I admire PHP and I think PHP 8 proves that the folks designing and developing PHP care much about the language and the future of PHP in general. In this blog post, I would like to show why I think PHP matters and why I still prefer C#.

What’s new in PHP 8?

First, there’s named arguments, so you can much more easily use functions that have a lot of arguments or just to make arguments more clear. As the PHP 8 release announcement shows:

htmlspecialchars($string, double_encode: false);

PHP 8 also supports class/method attributes which may replace the often-used PHPDoc to configure behaviour for classes or methods. They look a bit silly with using #[] as syntax, but it looks like it’s for backwards compatibilty (as # introduces a one-line comment).

#[Route("/api/posts/{id}", methods: ["GET"])]
public function foo()

Then there’s also constructor property promotion, which removes the need to set properties of classes which are arguments of the constructor manually in the constructor. Then there’s union types which allow to pass more than a single type to a strictly typed method. There are match expression, which remove the need to write a switch statement. And there’s a nullsafe operator, which allows to navigate through class methods which may be null:

$country = $session?->user?->getAddress()?->country;

There are also som other improvements under the hood like Just-in-time compilation, a lot of stuff around type system and the error handling and various syntax tweaks. Basically, PHP 8 is a major release in respect to the language design and less regarding the functionality (expect maybe for JIT-compilation). It fixes a lot of legacy that was around for so long and allows the language to grow – and even get better.

Is PHP really worth it?

Yes, absolutely. PHP is an amazing language by providing an easy entry, simple deployment, widely available good webhosters which support it. It is stable, reliable and usually just works. PHP is often laughed at for it’s language design. However, PHP has a vibrant community and one of the largest publicly available package repository. PHP is easy to install, easy to use and quite easy to deploy as it consists only of files that need to be copied to a webserver – there’s no platform-specific compilation.

The most often heard arguments against PHP are it’s sloppiness/laxiness around types (script types are not mandatory), it’s forgiveneess (as long as the syntax is ok, semantic is “adaptable”) and it’s bad language design (way to much legacy).

Then why prefer C#?

I’ll show you some arguments why I prefer the language design of C# over the one of PHP. For context: I mostly use both languages for web-based things. So it’s always usually JSON in and JSON out.

Good dependency management

While I think PHP does the job (it does it very well), I began to like C# (especially with .Net Core). I mostly admire the design of the C# language. Composer, PHP’s semi-official package manager, is one of the best solutions for dependency resolution. It is perfectly capable resolving transitive dependencies which make’s it very easy for package maintainers to define their requirements and makes it very easy for package users to require some package and validate whether it’s acutally compatible with the other dependencies. In .Net, assembly binding and transitive dependencies often caused trouble, issues and build problems. With .Net Core, this got a lot easier having a simpler dependency-definition format.

Strict typing and compile-time syntax validation

One of the quirks of being an interpreted language like PHP is that syntax validation is either done statically or when actually running the code. This can lead to issues that get uncovered quite late (at best when running automated test, at worst in production). With C# being a compiled language, at least the syntax is validated when compiling. This does not mean that your code magically works always, it just means that the most basic issues are catched early.

// This is valid syntax in PHP. Does it make sense? No.
function foobar() : void {}
$val = foobar();

Obviosuly, your preferred IDE may point out that this code does not make sense. But that’s not the point. In a large codebase it gets very hard to keep eyes on all such issues.

Streams

PHP does not have streams available. It does have resources which are some kind of special variable that hold a reference to an external resource. If you search on how to how to read an image (or any file) from a remote host and write it to a local file, you’re pointed to something like this:

$imageString = file_get_contents("http://example.com/image.jpg");
$save = file_put_contents('Image/saveto/image.jpg',$imageString);

C# uses some more code for that, but then: What type does $imageString actually have? It is not a resource, it is a string. And if you guess, you’ll want to load a 100 MB file from a remote server, how much memory do you need? At least 100 MB. Then I simply prefer using some derivate of the Stream class which allows me to read, write, seek and all that using a quite low memory footprint. Having worked on projects which do image processing on webservers with often quite large images (up to 50 or sometims 100 MB), Streams are a welcome gift.

Generics, Enums and all the missing parts of a nice language

PHP actually does have a proposal to implement enums at a future point. It also does have a four year old proposal for implementing generics. Do you need enums and generics to get the job done? Absolutley not. Does it make the job easier? Absolutely yes. Especially, with basically every database providing an enum datatype, it would be nice to have an enum in PHP and not use a string for that. There are great libraries for that, and they work quite well. And that brings me do my last argument:

Proper type deserialization

Searching the web for how to “deserialize in php to a custom class”, the first link that Stackoverflow that pops up, proposes something like that:

$data = json_decode($json, true);
$class = new Foobar();
foreach ($data as $key => $value) $class->{$key} = $value;

Obviously, this does not work with nested classes, strict types (or somehow it does?, because of the lax typing in PHP). Other proposals loke much more fancier, or suggest using stdClass (the base class of every class) and the use PHPDoc type-hints to hint the type to the IDE. Then I prefer the C# way which is perfectly capable of deserializing nested objects into their proper type.

FooObj object = JsonConvert.DeserializeObject<FooObj>(jsonString);

In todays world, with distributed (or micro-) services, it is possible that some data is passed from one service to another. The receiving service gets some JSON string and deserializes that string into a shared class definition. With that, you get script types for free and modifying one side (modifying the contract) also let’s you track the change for the receiving service. Without proper deserializing into actual class types, you’re just guessing a lot.

Whould I still use PHP?

Yes, for sure. With Symfony, one of if not the most advanced PHP frameworks, it’s easy to write webservices. With Doctrine, an ORM, it’s quite easy to read/write to databases and map objects (However, I still prefer something like a passive record pattern). PHP has a large, active community and a lot of open source projects which help you in many cases. PHP is absolutely evoling and I think if it keeps going in the same direction as it did with PHP 8, it may have a position in the language landscape for a long time.

PHP has started of in a (web-) landscape that was so different from what we know today. PHP kept (and still keeps) a lot of legacy around, which can also be a good thing (others don’t, looking at .Net ecosystem and their many UI frameworks) but also can be so bad that, at some point, you will break half of the internet by making the language incompatible with WordPress.

Conclusion

With .Net Core 3 and, the latest release, .Net Core 5, Microsoft shows that it cares aboud it’s .Net plaform and it shows that it is perfectly capable to compete with well-known languages for web APIs like PHP, Python and Java. PHP 8 proved, that the team around PHP is willing to improve the language in significant ways and to cut old tails off. I think PHP 8 is amazing and it does it’s job perfectly. However, I think C# just provides the better language design for todays api-based world.

This blog post was originally posted on my companys blog under https://en.globalelements.ch/2021/01/08/php-8-is-amazing-i-still-prefer-c/.

Top comments (1)

Collapse
 
awons profile image
Aleksander Wons

I'm currently looking around C# to see if this could be something for me. And because I'm a PHP developer (~15 years) I somehow landed on your page.
While I do agree PHP has some issues and there are things that C# probably does better (can't really tell yet), I have to disagree with some of the points you provided.

Streams
PHP has streams since ages: php.net/manual/en/book.stream.php
When it comes to downloading resources using streams you could probably do the same thing in PHP as you can in C#.

Serialization/deserialization
Partially true. PHP has means to serialize/deserialize classes: php.net/manual/en/function.seriali.... It comes with it's own set of issues and quirks, but this is definitely not the only way to do it. As you noticed, PHP has a bit repository of third-party packages. Serializers are among them. And some of them are used by thousands of projects (github.com/schmittjoh/serializer, github.com/laminas/laminas-serializer; just to name a few). They can all deal with class serialization without any additional configurations. And if needed, you can specify what you exactly need.

Enums
Are already there :)

Generics
There is a good article explaining why the community is reluctant to implement them: stitcher.io/blog/generics-in-php-3

A side note: unfortunately StackOverflow is not a good source of good practices and how you should do things. It usually just show things that "work". Don't rely on that source if you want to argument something ;)