PHP Internals News: Episode 52: Floats and Locales – Derick Rethans

PHP Internals News: Episode 52: Floats and Locales

In this episode of “PHP Internals News” I talk with George Banyard (Website, Twitter, GitHub, GitLab) about an RFC that he has proposed together with Máté Kocsis (Twitter, GitHub, LinkedIn) to make PHP’s float to string logic no longer use locales.

The RSS feed for this podcast is https://derickrethans.nl/feed-phpinternalsnews.xml, you can download this episode’s MP3 file, and it’s available on Spotify and iTunes. There is a dedicated website: https://phpinternals.news

Transcript

Derick Rethans 0:16

Hi, I’m Derick. And this is PHP internals news, a weekly podcast dedicated to demystifying the development of the PHP language. This is Episode 52. Today I’m talking with George Banyard about an RFC that he’s made together with Mate Kocsis. This RFC is titled locale independent floats to string. Hello, George, would you please introduce yourself?

George Banyard 0:39

Hello, I’m George Peter Banyard. I’m a student at Imperial College and I work on PHP in my free time.

Derick Rethans 0:47

All right, so we’re talking about local independent floats. What is the problem here?

George Banyard 0:52

Currently when you do a float to string conversion, so all casting or displaying a float, the conversion will depend on like the current local. So instead of always using like the decimal dot separator. For example, if you have like a German or the French locale enabled, it will use like a comma to separate like the decimals.

Derick Rethans 1:14

Okay, I can understand that that could be a bit confusing. What are these locales exactly?

George Banyard 1:20

So locales, which are more or less C locales, which PHP exposes to user land is a way how to change a bunch of rules on how string and like stuff gets displayed on the C level. One of the issues with it is that like it’s global. For example, if you use like a thread safe API, if you use the thread safe PHP version, then set_locale() is not thread safe, so we’ll just like impact other threads where you’re using it.

Derick Rethans 1:50

So a locale is a set of rules to format specific things with floating point numbers being one of them in which situations does the locale influence the display a floating point numbers in every situation in PHP or only in some?

George Banyard 2:06

Yes, it only impacts like certain aspects, which is quite surprising. So a string cast will affect it the strval() function, vardump(), and debug_zval_dump() will all affect the decimal locator and also printf() with the percentage lowercase F, but that’s expected because it’s locale aware compared to the capital F modifier.

Derick Rethans 2:32

But it doesn’t, for example, have the same problem in the serialised function or say var_export().

George Banyard 2:37

Yeah, and json_encode() also doesn’t do that. PDO has special code which handles also this so that like all the PDO drivers get like a constant treat like float string, because that could like impact on the databases.

Derick Rethans 2:53

How is it a problem that with some locales enabled and then uses a comma instead of the decimal point. How can this cause bugs and PHP applications?

Truncated by Planet PHP, read more at the original (another 17468 bytes)

Xdebug Update: April 2020 – Derick Rethans

Xdebug Update: April 2020

Another monthly update where I explain what happened with Xdebug development in this past month. These will be published on the first Tuesday after the 5th of each month. Patreon supporters will get it earlier, on the first of each month. You can become a patron to support my work on Xdebug. If you are leading a team or company, then it is also possible to support Xdebug through a subscription.

In March, I worked on Xdebug for about 60 hours, on the following things:

Xdebug 2.9.5

The 2.9.5 release addresses a few bugs. One of them was a follow on from the issue where Xdebug would crash when another extension would run code in PHP’s Request Init stage, but only on a second or later request in the same PHP process. As this is not something that’s easy to catch with PHP’s testing framework that Xdebug uses, this issue slipped through the cracks.

The release fixes another bug, where throwing an exception from within a destructor would crash Xdebug. The fix for this was merely making sure that PHP’s internal state is still available:

- if (!(ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
+ if (EG(current_execute_data) && !(ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_SYMBOL_TABLE)) { 

Beyond these two crashes, the release also addressed an issue where Xdebug did not always correct catch where executable code could exist for code coverage analyses. Over the last decade, PHP has been getting more and more optimised, with more internal engine instructions. Unfortunately that sometimes means that these are not hooked into by Xdebug, to see whether there could be a line of code that would make use of these opcodes. As this is often very dependent on how developers lay out their code, these issues are often found by them. Luckily, these issues are trivially fixed, as long as I have access to just the file containing that code. I then analyse it with vld to see which opcode (PHP engine instruction) I have missed.

Xdebug 3 and Xdebug Cloud

Most of my time was spend on getting Xdebug Cloud to a state where I can invite select developers to alpha test it. This includes allowing for Xdebug to connect to Xdebug Cloud. There is currently a branch available, but it still lacks the addition of SSL encryption, which is a requirement for allowing safe transport of debug information.

The communications between an IDE and Xdebug through Xdebug Cloud is working, with a few things related to detecting disconnections more reliably still outstanding.

As Xdebug Cloud needs integration in debugging clients (such as PhpStorm, and other IDEs), I have been extending the dbgpProxy tool to act as intermediate link between existing IDEs and Xdebug Cloud without IDEs having to change anything. This work is still ongoing, and is not documented yet, but I hope to finish that in the next week. Once that and SSL support in the Xdebug to Xdebug Cloud communication has been finalized, I will reach out to subscribers of the Xdebug Cloud newsletter to see if anybody is interested in trying it out.

Podcast

The PHP Internals News continues its second season. Episodes in the last month included a discussion on PHP 8’s JIT engine and increasing complexity,

Truncated by Planet PHP, read more at the original (another 720 bytes)

PHP Internals News: Episode 51: Object Ergonomics – Derick Rethans

PHP Internals News: Episode 51: Object Ergonomics

In this episode of “PHP Internals News” I talk with Larry Garfield (Twitter, Website, GitHub) about a blog post that he was written related to PHP’s Object Ergonomics.

The RSS feed for this podcast is https://derickrethans.nl/feed-phpinternalsnews.xml, you can download this episode’s MP3 file, and it’s available on Spotify and iTunes. There is a dedicated website: https://phpinternals.news

Transcript

Derick Rethans 0:16

Hi, I’m Derick. And this is PHP internals news, a weekly podcast dedicated to demystifying the development of the PHP language. This is Episode 51. Today I’m talking with Larry Garfield, not about an RFC for once, but about a blog post that he’s written called Object Ergonomics. Larry, would you please introduce yourself?

Larry Garfield 0:38

Hello World. My name is Larry Garfield, also Crell, CRELL, on various social medias. I work at platform.sh in developer relations. We’re a continuous deployment cloud hosting company. I’ve been writing PHP for 21 years and been a active gadfly and nudge for at least 15 of those.

Derick Rethans 1:01

In the last couple of months, we have seen quite a lot of smaller RFCs about all kinds of little features here and there, to do with making the object oriented model of PHP a little bit better. I reckon this is also the nudge behind you writing a slightly longer blog post titled “Improving PHP object ergonomics”.

Larry Garfield 1:26

If by slightly longer you mean 14 pages? Yes.

Derick Rethans 1:29

Yes, exactly. Yeah, it took me a while to read through. What made you write this document?

Larry Garfield 1:34

As you said, there’s been a lot of discussion around improving PHP’s general user experience of working with objects in PHP. Where there’s definitely room for improvement, no question. And I found a lot of these to be useful in their own right, but also very narrow and narrow in ways that solve the immediate problem but could get in the way of solving larger problems later on down the line. So I went into this with an attitude of: Okay, we can kind of piecemeal and attack certain parts of the problem space. Or we can take a step back and look at the big picture and say: Alright, here’s all the pain points we have. What can we do that would solve not just this one pain point. But let us solve multiple pain points with a single change? Or these two changes together solve this other pain point as well. Or, you know, how can we do this in a way that is not going to interfere with later development that we’ve talked about. We know we want to do, but isn’t been done yet. So how do we not paint ourselves into a corner by thinking too narrow?

Derick Rethans 2:41

It’s a curious thing, because a more narrow RFC is likely easier to get accepted, because it doesn’t pull in a whole set of other problems as well. But of course, as you say, if the whole idea hasn’t been thought through, then some of these things might not actually end up being beneficial. Because it can be combined with some other things to directly address the problems that we’re trying to solve, right?

Larry Garfield 3:07

Yeah, it comes down to what are the smallest changes we can make that taken together have the largest impact. That kind of broad picture thinking is something that is hard to do in PHP, just given the way it’s structured. So I took a stab at that.

Derick Rethans 3:21

What are the main problems that we should address?

Larry Garf

Truncated by Planet PHP, read more at the original (another 29525 bytes)

Creating a simple link registry – Matthias Noback

The problem: if you publish any document as PDF, in print, etc. and the text contains URLs, there is a chance that one day those URLs won’t work anymore.
There’s nothing to do about that, it happens.

Luckily, this is a solved problem.
The solution is to link to a stable and trustworthy website, that is, one that you maintain and host (of course, you’re trustworthy!).
Then in the document you link to that website, and the website redirects visitors to the actual location.

An example: my book contains a link to https://enjoy.gitstore.app/repositories/matthiasnoback/read-with-the-author.
When I moved that repository to a new organization on GitHub, this link resulted in a 404 Page not found error.
The proper URL is now https://enjoy.gitstore.app/repositories/read-with-the-author/read-with-the-author.
Chris from Gitstore was able to save the day by setting up a redirect on their site, but I wanted to make sure this kind of problem would never be a problem for me again.

The ingredients for the solution:

  • A domain name (I registered advwebapparch.com)
  • A simple website that can redirect visitors to the actual locations

I wanted to hook this new website into my existing Docker-based setup which uses Traefik to forward traffic to the right container based on labels.
It turns out, with a simple Nginx image and some custom setup we can easily set up a website that is able to redirecting visitors.

The Dockerfile for such an image:

FROM nginx:stable-alpine
COPY default.conf /etc/nginx/conf.d/default.conf

Where default.conf looks like this:

server { listen 80 default_server; index index.html; root /srv; error_page 404 /404.html; rewrite /repository https://enjoy.gitstore.app/repositories/read-with-the-author/read-with-the-author redirect;
}

This already works, and when I deploying the resulting image to the server that receives traffic for advwebapparch.com, a request for /repository will indeed redirect a visitor to https://enjoy.gitstore.app/repositories/read-with-the-author/read-with-the-author using a temporary redirect.

Generating the Nginx configuration from a text file

When I’m working on my book, I don’t want to manually update a server configuration file every time I’m adding a URL.
Instead, I’d like to work with a simple text file.
Let’s name this file forwards.txt:

/repository https://enjoy.gitstore.app/repositories/read-with-the-author/read-with-the-author
/blog https://matthiasnoback.nl

And then I want the Docker image build process to add rewrite rules automatically,
So I wrote a little PHP script that does this runs during the build.
Here’s what the Dockerfile looks like.
It uses a multi-stage build:

FROM php:7.4-alpine as php
# This will copy build.php from the build context to the image
COPY . .
# This will generate default.conf based on template.conf
RUN php build.php FROM nginx:stable-alpine
# Copy the default.conf from the php image to the nginx image
COPY --from=php default.conf /etc/nginx/conf.d/default.conf

Here’s what happens inside the PHP script:

function insertRewritesInNginxConf(string $conf): string
{ $rewrites = []; foreach (file('forwards.txt') as $line) { $line = trim($line); if (empty($line)) { continue; } $rewrites[] = ' ' . 'rewrite ' . $line . ' redirect;'; } return str_replace( '%INSERT_URL_REWRITES_HERE%', implode("\n", $rewrites), $conf );
} /* * Generate the Nginx configuration which includes all the actual * redirect instructions */
file_put_contents( 'default.conf', insertRewritesInNginxConf(file_get_contents('template.conf'))
);

We should add a bit of validation for the data from the forwards.txt file so we don’t end up with a broken Nginx configuration, but otherwise, this works just fine.

I don’t want to manually check that all the links that are inside the “link registry” still work.
Instead, I’d like to use Oh Dear for that, which does uptime monitoring and checks for broken links as well.

For this purpose I added another function to the PHP script, which, based

Truncated by Planet PHP, read more at the original (another 1844 bytes)

Making bugs ex-bugs with Xdebug – platform.sh

Xdebug is an indispensable tool for every PHP developer. PHP’s favorite real-time debugger, it supports breakpoints, more detailed debug output, and deeper introspection of PHP code to determine just what it’s doing (and what it’s doing wrong). Sadly, it comes at a huge cost in performance, though, making it unsuitable for production.
Not on Platform.sh, though. Xdebug is now available on all Grid environments, secure and without a performance loss.

Switching phubb’s HTTP client – Christian Weiske

phubb is a WebSub hub that notifies subscribers in realtime when your website is updated.

Up to this year, phubb sent HTTP requests (GET + POST) with file_get_contents() and a HTTP stream context – see my previous example.

But then I needed a 100% correct way of detecting a page’s Hub URL, and copied the code from phinde, my blog search engine. With that I introduced a dependency to PEAR’s good old HTTP_Request2 library and I decided to use that library for all requests.

Unfortunately, now the problems began: During development I got an error in about one of 10-20 requests on my machine and could not find the cause:

PHP Fatal error: Uncaught HTTP_Request2_MessageException: Malformed response: in HTTP/Request2/Adapter/Socket.php on line 1019 #0 HTTP/Request2/Adapter/Socket.php(1019): HTTP_Request2_Response->__construct('', true, Object(Net_URL2))
#1 HTTP/Request2/Adapter/Socket.php(136): HTTP_Request2_Adapter_Socket->readResponse()
#2 HTTP/Request2.php(946): HTTP_Request2_Adapter_Socket->sendRequest(Object(phubb\HttpRequest))
#3 phubb/src/phubb/HttpRequest.php(22): HTTP_Request2->send()
#4 phubb/src/phubb/Task/Publish.php(283): phubb\HttpRequest->send()
#5 phubb/src/phubb/Task/Publish.php(248): phubb\Task_Publish->fetchTopic(Object(phubb\Model_Topic))
#6 phubb/src/phubb/Task/Publish.php(77): phubb\Task_Publish->checkTopicUpdate('http://push-tes...')
#7 in HTTP/Request2/Response.php on line 215

The socket adapter has this problem, and I did not want to try to debug that strange problem. (No idea if the cURL one has it; I do not want to rely on php-curl). Finding a new HTTP library was the only option.

New HTTP library

The PHP Framework Interop Group has several HTTP-related proposals; one of them PSR-18: HTTP Client. Now that we have a standardized way to send HTTP requests in 2020, I should use a library that implements it.

The psr-18 topic on Github listed some clients:

Symfony’s HTTP client was among them, and it provides a mock client for unit tests! Unfortunately, it also introduces a million dependencies.

There were two others that looked ok-ish on first sight (diciotto and http-client-curl) but both of them had no mock client, and the latter was even curl only. Again nothing for me.

Then I found PHP-HTTP that promises a standard interface for HTTP clients in PHP, and it supports PSR-18! It even has a socket client that has nearly no dependencies, and a mock client for unit tests. I’ll try that one for now.