Is the PHP Intl extension thread safe?

2019-05-05 14:15发布

问题:

I've been reading about locales in PHP and it seems setlocale() has problems with threads. (I'm not too familiar with threads - the docs mention it is not thread safe)

I'd like to give my project the ability to deal with certain number formats and the Intl extension seems interesting.

http://php.net/manual/en/book.intl.php

Should I expect the same problems that setlocale() has using the Intl extension?

回答1:

Ok, I was curious about this myself as well, so I devised a test.

First I tested setlocale() with these two files:

<?php
# locale1.php
error_reporting( E_ALL | E_STRICT );

date_default_timezone_set( 'Europe/Amsterdam' );
setlocale( LC_ALL, 'dutch_nld' ); // awkward Windows locale string

sleep( 10 ); // let's sleep for a bit here

echo strftime( '%A, %B %d, %Y %X %Z', time() );

and

<?php
# locale2.php
error_reporting( E_ALL | E_STRICT );

date_default_timezone_set( 'America/Los_Angeles' );
setlocale( LC_ALL, 'english_usa' ); // awkward Windows locale string

echo strftime( '%A, %B %d, %Y %X %Z', time() );

Then I executed them in two seperate tabs. First locale1.php, that sleeps for 10 seconds after setting the locale, giving us time to execute locale2.php in the meanwhile.

To my surprise locale2.php isn't even allowed to change the locale correctly. It appears sleep( 10 ) in locale1.php hijacks the Apache/PHP process in such a way that it doesn't allow locale2.php to alter the locale in the meanwhile. It does however echo the date in the meanwhile of course, just not localized as you'd expect.

Edit: sorry, scrap that. It appears locale2.php does change the locale and locale1.php then prints the English date in stead of Dutch after sleeping. So that does appear to be in accordance with what is expected behavior from setlocale(). /Edit

Then, I tested IntlDateFormatter with these two files:

<?php
# locale1.php
error_reporting( E_ALL | E_STRICT );

$dateFormatter = new IntlDateFormatter(
    'nl_NL',
     IntlDateFormatter::FULL,
     IntlDateFormatter::FULL,
     'Europe/Amsterdam'
);

sleep( 10 ); // let's sleep for a bit here

echo $dateFormatter->format( time() );

and

<?php
# locale2.php
error_reporting( E_ALL | E_STRICT );

$dateFormatter = new IntlDateFormatter(
    'en_US',
     IntlDateFormatter::FULL,
     IntlDateFormatter::FULL,
     'America/Los_Angeles'
);

echo $dateFormatter->format( time() );

and then executed them again in two separate tabs, the same way as with the first set of files. This does give the expected results: while locale1.php is sleeping locale2.php nicely prints a date in American-English according to American rules, after which locale1.php nicely prints a date in Dutch according to Dutch rules.

So, concluding, it appears Intl is safe from that setlocale problem.

But also mind Hyunmin Kim's answer of course. I couldn't comment on that, due to lack of experience with using Intl. I only recently discovered Intl.



回答2:

The Intl extension is safe and very useful if you're working not working inside a framework.

For example, if you're using Symfony2, your programs will most likely crash when using Forms and Validators.